diff --git a/.drone.yml b/.drone.yml index ac8c929181..e2ad7ccfe1 100644 --- a/.drone.yml +++ b/.drone.yml @@ -105,12 +105,6 @@ services: from_secret: gitlab_read_token depends_on: - build - when: - branch: - - master - event: - - push - - pull_request - name: mysql8 pull: default @@ -658,7 +652,6 @@ steps: event: exclude: - pull_request - --- kind: pipeline name: docker-linux-arm64-dry-run @@ -688,6 +681,9 @@ steps: tags: linux-arm64 build_args: - GOPROXY=off + environment: + PLUGIN_MIRROR: + from_secret: plugin_mirror when: event: - pull_request @@ -732,11 +728,13 @@ steps: from_secret: docker_password username: from_secret: docker_username + environment: + PLUGIN_MIRROR: + from_secret: plugin_mirror when: event: exclude: - pull_request - --- kind: pipeline name: docker-manifest diff --git a/.eslintrc b/.eslintrc index 8f337baec5..346ae71c49 100644 --- a/.eslintrc +++ b/.eslintrc @@ -25,7 +25,7 @@ globals: Tribute: false overrides: - - files: ["web_src/**/*.worker.js"] + - files: ["web_src/**/*worker.js"] env: worker: true rules: @@ -48,6 +48,7 @@ rules: no-cond-assign: [2, except-parens] no-console: [1, {allow: [info, warn, error]}] no-continue: [0] + no-empty: [2, {allowEmptyCatch: true}] no-eq-null: [2] no-mixed-operators: [0] no-multi-assign: [0] @@ -57,6 +58,7 @@ rules: no-restricted-syntax: [0] no-return-await: [0] no-shadow: [0] + no-underscore-dangle: [0] no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, ignoreRestSiblings: true}] no-use-before-define: [0] no-var: [2] diff --git a/.gitignore b/.gitignore index d14544c721..9c4a15c9cc 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,7 @@ coverage.all /node_modules /yarn.lock /public/js +/public/serviceworker.js /public/css /public/fonts /public/fomantic diff --git a/CHANGELOG.md b/CHANGELOG.md index b5431762bb..e04b05df9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,507 @@ This changelog goes through all the changes that have been made in each release without substantial changes to our git log; to see the highlights of what has been added to each release, please refer to the [blog](https://blog.gitea.io). +## [1.12.6](https://github.com/go-gitea/gitea/releases/tag/v1.12.6) - 2020-11-11 + +* SECURITY + * Prevent git operations for inactive users (#13527) (#13537) + * Disallow urlencoded new lines in git protocol paths if there is a port (#13521) (#13525) +* BUGFIXES + * API should only return Json (#13511) (#13564) + * Fix before and since query arguments at API (#13559) (#13560) + * Prevent panic on git blame by limiting lines to 4096 bytes at most (#13470) (#13492) + * Fix link detection in repository description with tailing '_' (#13407) (#13408) + * Remove obsolete change of email on profile page (#13341) (#13348) + * Fix permission check on get Reactions API endpoints (#13344) (#13346) + * Add migrated pulls to pull request task queue (#13331) (#13335) + * API deny wrong pull creation options (#13308) (#13327) + * Fix initial commit page & binary munching problem (#13249) (#13259) + * Fix diff parsing (#13157) (#13136) (#13139) + * Return error 404 not 500 from API if team does not exist (#13118) (#13119) + * Prohibit automatic downgrades (#13108) (#13111) + * Fix GitLab Migration Option AuthToken (#13101) + * GitLab Label Color Normalizer (#12793) (#13100) + * Log the underlying panic in runMigrateTask (#13096) (#13098) + * Fix attachments list in edit comment (#13036) (#13097) + * Fix deadlock when deleting team user (#13093) + * Fix error create comment on outdated file (#13041) (#13042) + * Fix repository create/delete event webhooks (#13008) (#13027) + * Fix internal server error on README in submodule (#13006) (#13016) + +## [1.12.5](https://github.com/go-gitea/gitea/releases/tag/v1.12.5) - 2020-10-01 + +* BUGFIXES + * Allow U2F with default settings for gitea in subpath (#12990) (#13001) + * Prevent empty div when editing comment (#12404) (#12991) + * On mirror update also update address in DB (#12964) (#12967) + * Allow extended config on cron settings (#12939) (#12943) + * Open transaction when adding Avatar email-hash pairs to the DB (#12577) (#12940) + * Fix internal server error from ListUserOrgs API (#12910) (#12915) + * Update only the repository columns that need updating (#12900) (#12912) + * Fix panic when adding long comment (#12892) (#12894) + * Add size limit for content of comment on action ui (#12881) (#12890) + * Convert User expose ID each time (#12855) (#12883) + * Support slashes in release tags (#12864) (#12882) + * Add missing information to CreateRepo API endpoint (#12848) (#12867) + * On Migration respect old DefaultBranch (#12843) (#12858) + * Fix notifications page links (#12838) (#12853) + * Stop cloning unnecessarily on PR update (#12839) (#12852) + * Escape more things that are passed through str2html (#12622) (#12850) + * Remove double escape on labels addition in comments (#12809) (#12810) + * Fix "only mail on mention" bug (#12775) (#12789) + * Fix yet another bug with diff file names (#12771) (#12776) + * RepoInit Respect AlternateDefaultBranch (#12746) (#12751) + * Fix Avatar Resize (resize algo NearestNeighbor -> Bilinear) (#12745) (#12750) +* ENHANCEMENTS + * gitea dump: include version & Check InstallLock (#12760) (#12762) + +## [1.12.4](https://github.com/go-gitea/gitea/releases/tag/v1.12.4) - 2020-09-02 + +* SECURITY + * Escape provider name in oauth2 provider redirect (#12648) (#12650) + * Escape Email on password reset page (#12610) (#12612) + * When reading expired sessions - expire them (#12686) (#12690) +* ENHANCEMENTS + * StaticRootPath configurable at compile time (#12371) (#12652) +* BUGFIXES + * Fix to show an issue that is related to a deleted issue (#12651) (#12692) + * Expire time acknowledged for cache (#12605) (#12611) + * Fix diff path unquoting (#12554) (#12575) + * Improve HTML escaping helper (#12562) + * models: break out of loop (#12386) (#12561) + * Default empty merger list to those with write permissions (#12535) (#12560) + * Skip SSPI authentication attempts for /api/internal (#12556) (#12559) + * Prevent NPE on commenting on lines with invalidated comments (#12549) (#12550) + * Remove hardcoded ES indexername (#12521) (#12526) + * Fix bug preventing transfer to private organization (#12497) (#12501) + * Keys should not verify revoked email addresses (#12486) (#12495) + * Do not add prefix on http/https submodule links (#12477) (#12479) + * Fix ignored login on compare (#12476) (#12478) + * Fix incorrect error logging in Stats indexer and OAuth2 (#12387) (#12422) + * Upgrade google/go-github to v32.1.0 (#12361) (#12390) + * Render emoji's of Commit message on feed-page (#12373) + * Fix handling of diff on unrelated branches when Git 2.28 used (#12370) + +## [1.12.3](https://github.com/go-gitea/gitea/releases/tag/v1.12.3) - 2020-07-28 + +* BUGFIXES + * Don't change creation date when updating Release (#12343) (#12351) + * Show 404 page when release not found (#12328) (#12332) + * Fix emoji detection in certain cases (#12320) (#12327) + * Reduce emoji size (#12317) (#12327) + * Fix double-indirection bug in logging IDs (#12294) (#12308) + * Link to pull list page on sidebar when view pr (#12256) (#12263) + * Extend Notifications API and return pinned notifications by default (#12164) (#12232) + +## [1.12.2](https://github.com/go-gitea/gitea/releases/tag/v1.12.2) - 2020-07-11 + +* BUGFIXES + * When deleting repository decrese user repository count in cache (#11954) (#12188) + * Return full commit message instead of summary in commits API (#12186) (#12187) + * Properly set HEAD when a repo is created with a default branch that is not named 'master' (#12135) (#12182) + * Ensure GPG Subkeys are verified (#12155) (#12168) + * Fix failing to cache last commit with key being to long (#12151) (#12161) + * Multiple small admin dashboard fixes (#12153) (#12156) + * Remove spurious logging of " Delete all repository archives" at startup (#12139) (#12148) + * Fix repository setup instructions when default branch is not named 'master' (#12122) (#12147) + * Move EventSource to SharedWorker (#12095) (#12130) + * Fix ui bug in wiki commit page (#12089) (#12125) + * Fix gitgraph branch continues after merge (#12044) (#12105) + * Set the base url when migrating from Gitlab using access token or username without password (#11852) (#12104) + * Ensure BlameReaders close at end of request (#12102) (#12103) + * Fix panic when adding review comment (#12058) +* ENHANCEMENTS + * Disable dropzone's timeout for file uploads (#12024) (#12032) + +## [1.12.1](https://github.com/go-gitea/gitea/releases/tag/v1.12.1) - 2020-06-21 + +* BUGFIXES + * Handle multiple merges in gitgraph.js (#11996) (#12000) + * Add serviceworker.js to KnownPublicEntries (#11992) (#11994) + * For language detection do not try to analyze big files by content (#11971) (#11975) +* ENHANCEMENTS + * Fix scrollable header on dropdowns (#11893) (#11965) + +## [1.11.8](https://github.com/go-gitea/gitea/releases/tag/v1.11.8) - 2020-06-21 + +* BUGFIXES + * Really fix __webpack_public_path__ for 1.11 (#11961) + +## [1.12.0](https://github.com/go-gitea/gitea/releases/tag/v1.12.0) - 2020-06-17 + +* BREAKING + * When using API CreateRelease set created_unix to the tag commit time (#11218) + * Enable ENABLE_HARD_LINE_BREAK by default for rendering markdown (#11162) + * Fix sanitizer config - multiple rules (#11133) + * Remove check on username when using AccessToken authentication for the API (#11015) + * Return 404 from Contents API when items don't exist (#10323) + * Notification API should always return a JSON object with the current count of notifications (#10059) + * Remove migration support from versions earlier than 1.6.0 (#10026) +* SECURITY + * Use -1 to disable key algorithm type in ssh.minimum_key_sizes (#11635) (#11662) +* FEATURES + * Improve config logging when WrappedQueue times out (#11174) + * Add branch delete to API (#11112) + * Use markdown frontmatter to provide Table of contents, language and frontmatter rendering (#11047) + * Add a way to mark Conversation (code comment) resolved (#11037) + * Handle yaml frontmatter in markdown (#11016) + * Cache PullRequest Divergence (#10914) + * Make `gitea admin auth list` formatting configurable (#10844) + * Add Matrix webhook (#10831) + * Add Organization Wide Labels (#10814) + * Allow to set protected file patterns for files that can not be changed under no conditions (#10806) + * Option to set default branch at repository creation (#10803) + * Add request review from specific reviewers feature in pull request (#10756) + * Add NextCloud oauth (#10562) + * System-wide webhooks (#10546) + * Relax sanitization as per (#10527) + * Use media links for img in post-process (#10515) + * Add API endpoints to manage OAuth2 Application (list/create/delete) (#10437) + * Render READMEs in docs/ .gitea or .github from root (#10361) + * Add feishu webhook support (#10229) + * Cache last commit to accelerate the repository directory page visit (#10069) + * Implement basic app.ini and path checks to doctor cmd (#10064) + * Make WorkerPools and Queues flushable (#10001) + * Implement "embedded" command to extract static resources (#9982) + * Add API endpoint for repo transfer (#9947) + * Make archive prefixing configurable with a global setting (#9943) + * Add Unique Queue infrastructure and move TestPullRequests to this (#9856) + * Issue/PR Context Popups (#9822) + * Add "Update Branch" button to Pull Requests (#9784) + * Add require signed commit for protected branch (#9708) + * Mark PR reviews as stale at push and allow to dismiss stale approvals (#9532) + * Add API notification endpoints (#9488) + * Issue search support elasticsearch (#9428) + * Add API branch protection endpoint (#9311) + * Add a new command doctor to check if some wrong configurations on gitea instance (#9095) + * Add support for migrating from Gitlab (#9084) + * Add support for database schema in PostgreSQL (#8819) + * Add setting to set default and global disabled repository units. (#8788) + * Language statistics bar for repositories (#8037) + * Restricted users (#6274) +* BUGFIXES + * Fix commenting on non-utf8 encoded files (#11916) (#11950) + * Use google/uuid to instead satori/go.uuid (#11943) (#11946) + * Align show/hide outdated button on code review block (#11932) (#11944) + * Update to go-git v5.1.0 (#11936) (#11941) + * Use ID or Where to instead directly use Get when load object from database (#11925) (#11934) + * Update CommitsAhead CommitsBehind on Pull BaseBranch Change too (#11912) (#11915) + * Invalidate comments when file is shortened (#11882) (#11884) + * Rework api/user/repos for pagination (#11827) (#11877) + * Handle more pathological branch and tag names (#11843) (#11863) + * Add doctor check to set IsArchived false if it is null (partial #11853) (#11859) + * Prevent panic on empty HOST for mysql (#11850) (#11856) + * Use DEFAULT_PAGING_NUM instead of MAX_RESPONSE_ITEMS in ListOptions (#11831) (#11836) + * Fix reply octicon (#11821) (#11822) + * Honor DEFAULT_PAGING_NUM for API (#11805) (#11813) + * Ensure rejected push to refs/pull/index/head fails nicely (#11724) (#11809) + * In File Create/Update API return 404 if Branch does not exist (#11791) (#11795) + * Fix doer of rename repo (#11789) (#11794) + * Initialize SimpleMDE when making a code comment (#11749) (#11785) + * Fix timezone on issue deadline (#11697) (#11784) + * Fix to allow comment poster to edit or delete his own comments (#11671) (#11774) + * Show full 500 error in API when Gitea in dev mode (#11641) (#11753) + * Add missing templates for Matrix system webhooks (#11729) (#11748) + * Fix verification of subkeys of default gpg key (#11713) (#11747) + * Fix styling for commiter on diff view (#11715) (#11744) + * Properly truncate system notices (#11714) (#11742) + * Handle expected errors in FileCreate & FileUpdate API (#11643) (#11718) + * Fix missing authorization check on pull for public repos of private/limited org (#11656) (#11682) + * Doctor check & fix db consistency (#11111) (#11676) + * Exclude generated files from language statistics (#11653) (#11670) + * Return json on 500 error from API (#11574) (#11659) + * When must change password only show Signout (#11600) (#11637) + * Backport various styling fixes (#11619) + * Fix wrong milestone in webhook message (#11596) (#11611) + * Fix serviceworker output file and misc improvements (#11562) (#11610) + * When initialising repositories ensure that the user doing the creation is the initializer (#11601) (#11608) + * Prevent empty query parameter being set on dashboard (#11561) (#11604) + * Fix images in wiki edit preview (#11546) (#11602) + * Prevent (caught) panic on login (#11590) (#11597) + * Prevent transferring repos to invisible orgs (#11517) (#11549) + * Move serviceworker to workbox and fix SSE interference (#11538) (#11547) + * API PullReviewComment HTMLPullURL should return the HTMLURL (#11501) (#11533) + * Fix repo-list private and total count bugs (#11500) (#11532) + * Fix form action template substitutions on admin pages (backport #11519) (#11531) + * Fix a bug where the reaction emoji doesn't disappear. (#11489) (#11530) + * TrimSpace when reading InternalToken from a file (#11502) (#11524) + * Fix selected line color in arc-green (#11492) (#11520) + * Make localstorage read ssh or https correctly (#11483) (#11490) + * Check branch protection on IsUserAllowedToUpdate (#11448) + * Fix margin on attached segment headers when they are separated by other element (#11425) + * Fix webhook template when validation errors occur (#11421) + * Fix NPE in template due to missing signing key on commit page (#11392) + * Restore active background to Register button on Register page (#11390) + * Fix hook failure due to relative LFS_CONTENT_PATH (#11362) + * Correctly set the organization num repos (#11339) + * Prevent 500 with badly formed task list (#11328) + * Allow compare page to look up base, head, own-fork, forkbase-of-head (#11327) + * Handle panics that percolate up to the graceful module (#11291) + * Don't allow registration via the web form, when AllowOnlyExternalRegistration is True (#11248) + * Patch fomantic-ui to workaround build issue (#11244) + * Prevent panic during wrappedConn close at hammertime (#11219) + * On logout force redirect to start page (#11202) + * Fix creation of Organization repos by Users with max created personal repos (#11183) + * Add option to increase provided OAuth2 token maximum size (#11180) + * Log the indexer path on failure (#11172) + * Ensure that relative paths in edit preview work (#11143) + * Make API EditIssue and EditPullRequest issue notifications (#11123) + * Send 404 immediately for known public requests (#11117) + * Remove nil inserts in models (#11096) + * Add GetReviews() to RetryDownloader (#11093) + * Remove nonexistent serviceworker entries (#11091) + * Simplify and fix GetApprovalCounts (#11086) + * Fix wiki revision template and simplify some tmpl conditions (#11080) + * Make branch parameter optional for /api/v1/repos/{owner}/{repo}/contents/{filepath} (#11067) + * Align review-item svg octicons (#11065) + * Automatically remove Watches, Assignments, etc if user loses access due to being removed as collaborator or from a team (#10997) + * Users should not be able to prohibit their own login (#10970) + * Fix scrollbar issues in dropdowns (#10897) + * Change the order of issues.closed_by to list opening user first (#10876) + * Allow site admin to check /api/v1/orgs endpoints (#10867) + * Avoid logging []byte in queue failures - convert to string first (#10865) + * Use ErrKeyUnableToVerify if fail to calc fingerprint in ssh-keygen (#10863) + * Fix assignees double load bug (#10856) + * Handle push rejection in branch and upload (#10854) + * In authorized_keys use double-quote for windows compatibility (#10841) + * Fix milestone template (#10824) + * log.Fatal on failure to listen to SSH port (#10795) + * Fix forked repo has no icon and language stat. (#10791) + * Fix tag/release deletion (#10663) + * Fix webhook migration (#10641) + * Migration for deleting orphaned dependencies (#10617) + * Add migration to fix the old broken merge-bases (#10604) + * Update templates for Go 1.14 (#10596) + * Remove unnecessary parentheses in wiki/view template (#10583) + * Change default value of DefaultCommandExecutionTimeout to match docs (#10581) + * Handle panic in indexer initialisation better (#10534) + * Set correct content_type value for Gogs/Gitea webhooks (#9504) (#10456) + * Fixed wrong AppSubUrl in multiple templates (#10447) + * Fix profile page CSS (#10406) + * Inject SVG sprite via ajax (#10320) + * Fix migration information update bug when linked github account (#10310) + * Allow admin to check org membership by API for other users (#10201) + * Fix topics dropdown (#10167) + * Ensure DeleteUser is not allowed to Delete Orgs and visa versa (#10134) + * Fix IsErrPullClosed (#10093) + * Accept punctuation after simple+cross repository issue references (#10091) + * On merge of already closed PR redirect back to the pulls page (#10010) + * Fix crowdin update script (#9969) + * Fix pull view when head repository or head branch missed and close related pull requests when delete head repository or head branch (#9927) + * Add option to prevent LDAP from deactivating everything on empty search (#9879) + * Fix admin handling at merge of PR (#9749) + * err_admin_name_pattern_not_allowed String Clarification (#9731) + * Fix wrong original git service type on a migrated repository (#9693) + * Fix ref links in issue overviews for tags (#8742) +* ENHANCEMENTS + * Fix search form button overlap (#11840) (#11864) + * Make tabular menu styling consistent for arc-green (#11570) (#11798) + * Add option to API to update PullRequest base branch (#11666) (#11796) + * Increase maximum SQLite variables count to 32766 (#11696) (#11783) + * Update emoji dataset with skin tone variants (#11678) (#11763) + * Add logging to long migrations (#11647) (#11691) + * Change language statistics to save size instead of percentage (#11681) (#11690) + * Allow different HardBreaks settings for documents and comments (#11515) (#11599) + * Fix alignment for commits on dashboard (#11595) (#11680) + * Default MSSQL port 0 to allow automatic detection by default (#11642) (#11673) + * Handle expected errors in AddGPGkey API (#11644) (#11661) + * Close EventSource before unloading the page (#11539) (#11557) + * Ensure emoji render with regular font-weight (#11541) (#11545) + * Fix webpack chunk loading with STATIC_URL_PREFIX (#11526) (#11542) + * Tweak reaction buttons (#11516) + * Use more toned colors for selected line (#11493) (#11511) + * Increase width for authors on commit view (#11441) + * Hide archived repos by default in repo-list (#11440) + * Better styling for code review comment textarea (#11428) + * Support view individual commit for wiki pages (#11415) + * Fix yellow background on active elements in code review (#11414) + * Better styling for code review comment form (#11413) + * Change install description on homepage (#11395) + * Ensure search action button is coalesced to adjacent input (#11385) + * Switch code editor to Monaco (#11366) + * Add paging and archive/private repository filtering to dashboard list (#11321) + * Changed image of openid-connect logo for better look on arc-green theme (#11312) + * Load Repo Topics on blame view too (#11307) + * Change the style in admin notice content view from `

` to `

` (#11301)
+  * Allow log.xxx.default to set logging settings for the default logger only (#11292)
+  * Automatically attempt auto recovery of broken disk queues (Update lunny/levelqueue to 0.3.0) (#11285)
+  * Make sendmail a Process and have default timeout (#11256)
+  * Check value of skip-repository flag in dump command (#11254)
+  * Fix submit review form (#11252)
+  * Allow unauthenticated users to compare (#11240)
+  * Add EventSource support (#11235)
+  * Refactor Milestone related (#11225)
+  * Add pull review API endpoints (#11224)
+  * Add a 'this' to issue close/reopened messages (#11204)
+  * When migrating from Gitlab map Approvals to approving Reviews (#11147)
+  * Improve representation of attachments in issues (#11141)
+  * Protect default branch against deletion (#11115)
+  * Add X-Total-Count on /repos/{owner]/{repo}/pulls API endpoint (#11113)
+  * Fix status label on branches list vertical alignment (#11109)
+  * Add single release page and latest redirect (#11102)
+  * Add missing commit states to PR checks template (#11085)
+  * Change icon on title for merged PR to git-merge (#11064)
+  * Add MergePull comment type instead of close for merge PR (#11058)
+  * Upgrade jQuery to 3.5.0, remove jQuery-Migrate, fix deprecations (#11055)
+  * Consolidate author name across timeline (#11053)
+  * Refactor UpdateOAuth2Application (#11034)
+  * Support unicode emojis and remove emojify.js (#11032)
+  * Add git hook "warning" to admin panel (#11030)
+  * Add flash notify for email preference setting success (#11027)
+  * Remove package code.gitea.io/gitea/modules/git import out of models (#11025)
+  * Match arc-green code tag color to code blocks (#11023)
+  * Move syntax highlighting to web worker (#11017)
+  * Prevent merge of outdated PRs on protected branches (#11012)
+  * Add Get/Update for api/v1/user/applications/oauth2 (#11008)
+  * Upgrade to most recent bluemonday (#11007)
+  * Tweak code tags in markdown (#11000)
+  * Reject duplicate AccessToken names (#10994)
+  * Fix Ctrl-Enter shortcut for issues (#10986)
+  * Provide `OwnerName` field for README template (#10981)
+  * Prettify Timeline (#10972)
+  * Add issue subscription check to API (#10967)
+  * Use AJAX for notifications table (#10961)
+  * Adjust label padding (#10957)
+  * Avoiding directory execution on hook (#10954) (#10955)
+  * Migrate ActivityHeatmap to Vue SFC (#10953)
+  * Change merge strategy๏ผš do not check write access if user in merge white list (#10951)
+  * Enable GO111MODULE=on globally in Makefile (#10939)
+  * API endpoint to get single commit via SHA and Ref (#10915)
+  * Add accordion to release list and hide non-latest (#10910)
+  * Split dashboard elements into separate template files (#10885)
+  * Add more message on sidebar menus (#10872)
+  * Set MySQL rowtype to dynamic for new tables (#10833)
+  * Completely fix task-list checkbox styling (#10798)
+  * Hide gear icon for user who can't use them on sidebar (#10750)
+  * Refactor Cron and merge dashboard tasks (#10745)
+  * Change review status icons on pr view style to github style (#10737)
+  * Make pagination optional for API list notification endpoints (#10714)
+  * Fix tab indentation in code view (#10671)
+  * Fix task-list checkbox styling (#10668)
+  * Multiple LFS improvements (#10667)
+  * Make PR message on pushes configurable (#10664)
+  * Move dropzone.js to npm/webpack (#10645)
+  * Ensure Update button is enabled even when CI has failed (#10640)
+  * Add restricted user filter to LDAP authentication (#10600)
+  * Add Yandex OAuth2 provider (#8335) (#10564)
+  * Make avatar lookup occur at image request (#10540)
+  * Prevent accidential selection of language stats bar (#10537)
+  * Add fluid-icon (#10491)
+  * Inform participants on UI too (#10473)
+  * Build with go 1.14 (and raise minimum go version to 1.12) (#10467)
+  * Add max-file-size to LFS (#10463)
+  * Enable paggination for ListRepoTags API (#10454)
+  * Update JS dependencies (#10450)
+  * Show the username as a fallback on feeds if full name is blank (#10438)
+  * Various dark theme fixes (#10416)
+  * Display pull request head branch even the branch deleted or repository deleted (#10413)
+  * Prevent Firefox from using apple-touch-icon (#10402)
+  * Fix input[type=file] on dark theme (#10382)
+  * Improve mobile review-box sizing (#10297)
+  * Notification: queue ui.go notification-service (#10281)
+  * Add detected file language to code search (#10256)
+  * Index code and stats only for non-empty repositories (#10251)
+  * Add Approval Counts to pulls list (#10238)
+  * Limit label list height on edit issue page (#10216)
+  * Improve 404 error message (#10214)
+  * Tweak locale to respect singular conflicting file message in PR list (#10177)
+  * Fix commit view (#10169)
+  * Reorganize frontend files and tooling (#10168)
+  * Allow emoji on popup label (#10166)
+  * ListIssues add filter for milestones API (#10148)
+  * Show if a PR has conflicting files on the PR lists (#10130)
+  * Fix inconsistent label color format in API (#10129)
+  * Show download count info in release list (#10124)
+  * Add Octicon SVG spritemap (#10107)
+  * Update aria-fixed semantic-dropdown to fomantic master (#10096)
+  * Fix apple-touch-icon, regenerate images (#10065)(#10006)
+  * Style blockquote for default issue mail template (#10024)
+  * More expansions in template repositories (#10021)
+  * Allow list collaborators for users with Read access to repo (#9995)
+  * Add explicit dimensions to navbar avatar (#9986)
+  * Remove loadCSS and preload woff2 icon fonts (#9976)
+  * Fix commit view JS features, reimplement folding (#9968)
+  * Fix review avatar image (#9962)
+  * Improve notification pager (#9821)
+  * Move jquery and jquery-migrate to npm/webpack (#9813)
+  * Change font to Roboto to support more charsets (#9803)
+  * Move mailer to use a queue (#9789)
+  * Issue search on my related repositories (#9758)
+  * Add "before" query to ListIssueComments and ListRepoIssueComments API (#9685)
+  * Move tracked time api convert to convert package (#9665)
+  * Improve PR info in default merge message (#9635)
+  * Granular webhook events (#9626)
+  * Add Reviewed-on in commit message (#9623)
+  * Add top author stats to activity page (#9615)
+  * Allow repo admin to merge PR regardless of review status (#9611)
+  * Migrate reactions when migrating repository from github (#9599)
+  * API orgEditTeam make Fields optional (#9556)
+  * Move create/fork repository from models to modules/repository (#9489)
+  * Migrate reviews when migrating repository from github (#9463)
+  * Times API add filters (#9373)
+  * Move push commits from models to modules/repository (#9370)
+  * Add API endpoint to check notifications [Extend #9488] (#9595)
+  * Add GET /orgs API endpoint (#9560)
+  * API add/generalize pagination (#9452)
+  * Make create org repo API call same as github (#9186)
+* BUILD
+  * Turn off go modules for xgo and gxz (#10963)
+  * Add gitea-vet (#10948)
+  * Rename scripts to build and add revive command as a new build tool command (#10942)
+  * Add 'make lint', restructure 'compliance' pipeline (#10861)
+  * Move JS build dependencies to 'dependencies' (#10763)
+  * Use whitelist to find go files, run find only once (#10594)
+  * Move vue and vue-calendar-heatmap to npm/webpack (#10188)
+  * Move jquery.are-you-sure to npm/webpack (#10063)
+  * Move highlight.js to npm/webpack (#10011)
+  * Generate Bindata if TAGS="bindata" and not up-to-date (#10004)
+  * Move CSS build to webpack (#9983)
+  * Move fomantic target, update 'make help' (#9945)
+  * Add css extraction and minification to webpack (#9944)
+  * Misc webpack tweaks (#9924)
+  * Make node_modules a order-only prerequisite (#9923)
+  * Update documentation for the go module era (#9751)
+  * Move swagger-ui to webpack/npm and update it to 3.24.3 (#9714)
+  * Use npm to manage fomantic and only build needed components (#9561)
+* MISC
+  * Add gnupg to Dockerfile (#11365)
+  * Update snapcraft.yaml for core18 and latest features (#11300)
+  * Update JS dependencies, min Node.js version 10.13 (#11246)
+  * Change default charset for MySQL on install to utf8mb4 (#10989)
+  * Return issue subscription status from API subscribe (#10966)
+  * Fix queue log param (#10733)
+  * Add warning when using relative path to app.ini (#10104)
+
+## [1.11.7](https://github.com/go-gitea/gitea/releases/tag/v1.11.7) - 2020-06-18
+
+* BUGFIXES
+  * Use ID or Where to instead directly use Get when load object from database (#11925) (#11935)
+  * Fix __webpack_public_path__ for 1.11 (#11907)
+  * Fix verification of subkeys of default gpg key (#11713) (#11902)
+  * Remove unnecessary parentheses in wiki/view template (#11781)
+  * Doctor fix xorm.Count nil on sqlite error (#11741)
+
+## [1.11.6](https://github.com/go-gitea/gitea/releases/tag/v1.11.6) - 2020-05-30
+
+* SECURITY
+  * Fix missing authorization check on pull for public repos of private/limited org (#11656) (#11683)
+  * Use session for retrieving org teams (#11438) (#11439)
+* BUGFIXES
+  * Return json on 500 error from API (#11574) (#11660)
+  * Fix wrong milestone in webhook message (#11596) (#11612)
+  * Prevent (caught) panic on login (#11590) (#11598)
+  * Fix commit page js error (#11527)
+  * Use media links for img in post-process (#10515) (#11504)
+  * Ensure public repositories in private organizations are visible and fix admin organizations list (#11465) (#11475)
+  * Set correct Content-Type value for Gogs/Gitea webhooks (#9504) (#10456) (#11461)
+  * Allow all members of private orgs to see public repos (#11442) (#11459)
+  * Whenever the ctx.Session is updated, release it to save it before sending the redirect (#11456) (#11457)
+  * Forcibly clean and destroy the session on logout (#11447) (#11451)
+  * Fix /api/v1/orgs/* endpoints by changing parameter to :org from :orgname (#11381)
+  * Add tracked time fix to doctor (part of #11111) (#11138)
+  * Fix webpack chunk loading with STATIC_URL_PREFIX (#11526) (#11544)
+  * Remove unnecessary parentheses in wiki/revision.tmpl to allow 1.11 to build on go1.14  (#11481)
+
 ## [1.11.5](https://github.com/go-gitea/gitea/releases/tag/v1.11.5) - 2020-05-09
 
 * BUGFIXES
@@ -113,6 +614,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
   * Blacklist manifest.json & milestones user (#10292) (#10293)
 
 ## [1.11.0](https://github.com/go-gitea/gitea/releases/tag/v1.11.0) - 2020-02-10
+
 * BREAKING
   * Fix followers and following tabs in profile (#10202) (#10203)
   * Make CertFile and KeyFile relative to CustomPath (#9868) (#9874)
@@ -586,6 +1088,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Ensure that 2fa is checked on reset-password (#9857) (#9877)
 
 ## [1.10.3](https://github.com/go-gitea/gitea/releases/tag/v1.10.3) - 2020-01-17
+
 * SECURITY
   * Hide credentials when submitting migration (#9102) (#9704)
   * Never allow an empty password to validate (#9682) (#9684)
@@ -604,6 +1107,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Branches not at ref commit ID should not be listed as Merged (#9614) (#9639)
 
 ## [1.10.2](https://github.com/go-gitea/gitea/releases/tag/v1.10.2) - 2020-01-02
+
 * BUGFIXES
   * Allow only specific Columns to be updated on Issue via API (#9539) (#9580)
   * Add ErrReactionAlreadyExist error (#9550) (#9564)
@@ -624,6 +1128,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix File Edit: Author/Committer interchanged (#9297) (#9300)
 
 ## [1.10.1](https://github.com/go-gitea/gitea/releases/tag/v1.10.1) - 2019-12-05
+
 * BUGFIXES
   * Fix max length check and limit in multiple repo forms (#9148) (#9204)
   * Properly fix displaying virtual session provider in admin panel (#9137) (#9203)
@@ -645,6 +1150,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Shadow password correctly for session config (#8984) (#9002)
 
 ## [1.10.0](https://github.com/go-gitea/gitea/releases/tag/v1.10.0) - 2019-11-13
+
 * BREAKING
   * Fix deadline on update issue or PR via API (#8698)
   * Hide some user information via API if user doesn't have enough permission (#8655) (#8657)
@@ -942,6 +1448,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix Statuses API only shows first 10 statuses: Add paging and extend API GetCommitStatuses (#7141)
 
 ## [1.9.6](https://github.com/go-gitea/gitea/releases/tag/v1.9.6) - 2019-11-13
+
 * BUGFIXES
   * Allow to merge if file path contains " or \ (#8629) (#8772)
   * Fix 500 when edit hook (#8782) (#8790)
@@ -950,6 +1457,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Add Close() method to gogitRepository (#8901) (#8958)
 
 ## [1.9.5](https://github.com/go-gitea/gitea/releases/tag/v1.9.5) - 2019-10-30
+
 * BREAKING
   * Hide some user information via API if user doesn't have enough permission (#8655) (#8658)
 * BUGFIXES
@@ -974,6 +1482,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Update heatmap fixtures to restore tests (#8615) (#8617)
 
 ## [1.9.4](https://github.com/go-gitea/gitea/releases/tag/v1.9.4) - 2019-10-08
+
 * BUGFIXES
   * Highlight issue references (#8101) (#8404)
   * Fix bug when migrating a private repository #7917 (#8403)
@@ -1000,6 +1509,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Make show private icon when repo avatar set (#8144) (#8175)
 
 ## [1.9.3](https://github.com/go-gitea/gitea/releases/tag/v1.9.3) - 2019-09-06
+
 * BUGFIXES
   * Fix go get from a private repository with Go 1.13 (#8100)
   * Strict name matching for Repository.GetTagID() (#8082)
@@ -1015,6 +1525,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Keep blame view buttons sequence consistent with normal view when viewing a file (#8007) (#8009)
 
 ## [1.9.2](https://github.com/go-gitea/gitea/releases/tag/v1.9.2) - 2019-08-22
+
 * BUGFIXES
   * Fix wrong sender when send slack webhook (#7918) (#7924)
   * Upload support text/plain; charset=utf8 (#7899)
@@ -1022,18 +1533,19 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix non existent milestone with 500 error (#7867) (#7873)
 * SECURITY
   * Fix No PGP signature on 1.9.1 tag (#7874)
-  * Release built with go 1.12.9 to fix security fixes in golang std lib, ref: https://groups.google.com/forum/#!msg/golang-announce/oeMaeUnkvVE/a49yvTLqAAAJ
+  * Release built with go 1.12.9 to fix security fixes in golang std lib, ref: 
 * ENHANCEMENTS
   * Fix pull creation with empty changes (#7920) (#7926)
 * BUILD
   * Drone/docker: prepare multi-arch release + provide arm64 image (#7571) (#7884)
 
 ## [1.9.1](https://github.com/go-gitea/gitea/releases/tag/v1.9.1) - 2019-08-14
+
 * BREAKING
   * Add pagination for admin api get orgs and fix only list public orgs bug (#7742) (#7752)
 * SECURITY
   * Be more strict with git arguments (#7715) (#7762)
-  * Release built with go 1.12.8 to fix security fixes in golang std lib, ref: https://groups.google.com/forum/#!topic/golang-nuts/fCQWxqxP8aA
+  * Release built with go 1.12.8 to fix security fixes in golang std lib, ref: 
 * BUGFIXES
   * Fix local runs of ssh-requiring integration tests (#7855) (#7857)
   * Fix hook problem (#7856) (#7754)
@@ -1056,6 +1568,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Correct wrong datetime format for git (#7689) (#7690)
 
 ## [1.9.0](https://github.com/go-gitea/gitea/releases/tag/v1.9.0) - 2019-07-30
+
 * BREAKING
   * Better logging (#6038) (#6095)
 * SECURITY
@@ -1412,6 +1925,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Added docker example for backup (#5846)
 
 ## [1.8.3](https://github.com/go-gitea/gitea/releases/tag/v1.8.3) - 2019-06-17
+
 * BUGFIXES
   * Always set userID on LFS authentication (#7224) (Part of #6993)
   * Fix LFS Locks over SSH (#6999) (#7223)
@@ -1422,6 +1936,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix GCArgs load from ini (#7156) (#7157)
 
 ## [1.8.2](https://github.com/go-gitea/gitea/releases/tag/v1.8.2) - 2019-05-29
+
 * BUGFIXES
   * Fix possbile mysql invalid connnection error (#7051) (#7071)
   * Handle invalid administrator username on install page (#7060) (#7063)
@@ -1437,6 +1952,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix wrong init dependency on markup extensions (#7038) (#7074)
 
 ## [1.8.1](https://github.com/go-gitea/gitea/releases/tag/v1.8.1) - 2019-05-08
+
 * BUGFIXES
   * Fix 404 when sending pull requests in some situations (#6871) (#6873)
   * Enforce osusergo build tag for releases (#6862) (#6869)
@@ -1463,6 +1979,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix config ui error about cache ttl (#6861) (#6865)
 
 ## [1.8.0](https://github.com/go-gitea/gitea/releases/tag/v1.8.0) - 2019-04-20
+
 * SECURITY
   * Prevent remote code execution vulnerability with mirror repo URL settings (#6593) (#6594)
   * Resolve 2FA bypass on API (#6676) (#6674)
@@ -1697,18 +2214,21 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Migrate database if app.ini found (#5290)
 
 ## [1.7.6](https://github.com/go-gitea/gitea/releases/tag/v1.7.6) - 2019-04-12
+
 * SECURITY
   * Prevent remote code execution vulnerability with mirror repo URL settings (#6593) (#6595)
 * BUGFIXES
   * Allow resend of confirmation email when logged in (#6482) (#6487)
 
 ## [1.7.5](https://github.com/go-gitea/gitea/releases/tag/v1.7.5) - 2019-03-27
+
 * BUGFIXES
   * Fix unitTypeCode not being used in accessLevelUnit (#6419) (#6423)
   * Fix bug where manifest.json was being requested without cookies and continuously creating new sessions (#6372) (#6383)
   * Fix ParsePatch function to work with quoted diff --git strings (#6323) (#6332)
 
 ## [1.7.4](https://github.com/go-gitea/gitea/releases/tag/v1.7.4) - 2019-03-12
+
 * SECURITY
   * Fix potential XSS vulnerability in repository description. (#6306) (#6308)
 * BUGFIXES
@@ -1718,6 +2238,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix displaying dashboard even if required to change password (#6214) (#6215)
 
 ## [1.7.3](https://github.com/go-gitea/gitea/releases/tag/v1.7.3) - 2019-02-27
+
 * BUGFIXES
   * Fix server 500 when trying to migrate to an already existing repository (#6188) (#6197)
   * Load Issue attributes for API /repos/{owner}/{repo}/issues/{index} (#6122) (#6185)
@@ -1732,6 +2253,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Recover panic in orgmode.Render if bad orgfile (#4982) (#5903) (#6097)
 
 ## [1.7.2](https://github.com/go-gitea/gitea/releases/tag/v1.7.2) - 2019-02-14
+
 * BUGFIXES
   * Remove all CommitStatus when a repo is deleted (#5940) (#5941)
   * Fix notifications on pushing with deploy keys by setting hook environment variables (#5935) (#5944)
@@ -1748,6 +2270,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * In basic auth check for tokens before call UserSignIn (#5725) (#6083)
 
 ## [1.7.1](https://github.com/go-gitea/gitea/releases/tag/v1.7.1) - 2019-01-31
+
 * SECURITY
   * Disable redirect for i18n (#5910) (#5916)
   * Only allow local login if password is non-empty (#5906) (#5908)
@@ -1769,6 +2292,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Include Go toolchain to --version (#5832) (#5830)
 
 ## [1.7.0](https://github.com/go-gitea/gitea/releases/tag/v1.7.0) - 2019-01-22
+
 * SECURITY
   * Do not display the raw OpenID error in the UI (#5705) (#5712)
   * When redirecting clean the path to avoid redirecting to external site (#5669) (#5679)
@@ -1925,18 +2449,21 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Only chown directories during docker setup if necessary. Fix #4425 (#5064)
 
 ## [1.6.4](https://github.com/go-gitea/gitea/releases/tag/v1.6.4) - 2019-01-15
+
 * BUGFIX
   * Fix SSH key now can be reused as public key after deleting as deploy key (#5671) (#5685)
   * When redirecting clean the path to avoid redirecting to external site (#5669) (#5703)
   * Fix to use correct value for "MSpan Structures Obtained" (#5706) (#5715)
 
 ## [1.6.3](https://github.com/go-gitea/gitea/releases/tag/v1.6.3) - 2019-01-04
+
 * SECURITY
   * Prevent DeleteFilePost doing arbitrary deletion (#5631)
 * BUGFIX
   * Fix wrong text getting saved on editing second comment on an issue (#5608)
 
 ## [1.6.2](https://github.com/go-gitea/gitea/releases/tag/v1.6.2) - 2018-12-21
+
 * SECURITY
   * Sanitize uploaded file names (#5571) (#5573)
   * HTMLEncode user added text (#5570) (#5575)
@@ -1951,6 +2478,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix empty wiki (#5504) (#5508)
 
 ## [1.6.1](https://github.com/go-gitea/gitea/releases/tag/v1.6.1) - 2018-12-08
+
 * BUGFIXES
   * Fix dependent issue searching when gitea is run in subpath (#5392) (#5400)
   * API: '/orgs/:org/repos': return private repos with read access (#5393)
@@ -1961,6 +2489,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix topic name length on database (#5493) (#5495)
 
 ## [1.6.0](https://github.com/go-gitea/gitea/releases/tag/v1.6.0) - 2018-11-22
+
 * BREAKING
   * Respect email privacy option in user search via API (#4512)
   * Simply remove tidb and deps (#3993)
@@ -2114,10 +2643,12 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix translation (#4355)
 
 ## [1.5.3](https://github.com/go-gitea/gitea/releases/tag/v1.5.3) - 2018-10-31
+
 * SECURITY
   * Fix remote command execution vulnerability in upstream library (#5177) (#5196)
 
 ## [1.5.2](https://github.com/go-gitea/gitea/releases/tag/v1.5.2) - 2018-10-09
+
 * SECURITY
   * Enforce token on api routes (#4840) (#4905)
 * BUGFIXES
@@ -2134,6 +2665,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix trimming of markup section names (#4864)
 
 ## [1.5.1](https://github.com/go-gitea/gitea/releases/tag/v1.5.1) - 2018-09-03
+
 * SECURITY
   * Don't disclose emails of all users when sending out emails (#4784)
   * Improve URL validation for external wiki and external issues (#4710) (#4740)
@@ -2148,6 +2680,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix incorrect caption of webhook setting (#4701) (#4718)
 
 ## [1.5.0](https://github.com/go-gitea/gitea/releases/tag/v1.5.0) - 2018-08-10
+
 * SECURITY
   * Check that repositories can only be migrated to own user or organizations (#4366) (#4370)
   * Limit uploaded avatar image-size to 4096px x 3072px by default (#4353)
@@ -2211,6 +2744,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Sign release binaries (#4188)
 
 ## [1.4.3](https://github.com/go-gitea/gitea/releases/tag/v1.4.3) - 2018-06-26
+
 * SECURITY
   * HTML-escape plain-text READMEs (#4192) (#4214)
   * Fix open redirect vulnerability on login screen (#4312) (#4312)
@@ -2223,6 +2757,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix webhook type conflation (#4285) (#4285)
 
 ## [1.4.2](https://github.com/go-gitea/gitea/releases/tag/v1.4.2) - 2018-06-04
+
 * BUGFIXES
   * Adjust z-index for floating labels (#3939) (#3950)
   * Add missing token validation on application settings page (#3976) #3978
@@ -2238,6 +2773,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Respository's home page not updated after first push (#4075)
 
 ## [1.4.1](https://github.com/go-gitea/gitea/releases/tag/v1.4.1) - 2018-05-03
+
 * BREAKING
   * Add "error" as reserved username (#3882) (#3886)
 * SECURITY
@@ -2255,6 +2791,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Show clipboard button if disable HTTP of git protocol (#3773) (#3774)
 
 ## [1.4.0](https://github.com/go-gitea/gitea/releases/tag/v1.4.0) - 2018-03-25
+
 * BREAKING
   * Drop deprecated GOGS\_WORK\_DIR use (#2946)
   * Fix API status code for hook creation (#2814)
@@ -2374,6 +2911,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Add owner to delete repo message (#2886)
 
 ## [1.3.1](https://github.com/go-gitea/gitea/releases/tag/v1.3.1) - 2017-12-08
+
 * BUGFIXES
   * Sanitize logs for mirror sync (#3057, #3082) (#3078)
   * Fix missing branch in release bug (#3108) (#3117)
@@ -2384,6 +2922,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix missing password length check when change password (#3039) (#3071)
 
 ## [1.3.0](https://github.com/go-gitea/gitea/releases/tag/v1.3.0) - 2017-11-29
+
 * BREAKING
   * Make URL scheme unambiguous (#2408)
 * FEATURES
@@ -2611,11 +3150,13 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Added vendor dir for js/css libs; Documented sources (#1484) (#2241)
 
 ## [1.2.3](https://github.com/go-gitea/gitea/releases/tag/v1.2.3) - 2017-11-03
+
 * BUGFIXES
   * Only require one email when validating GPG key (#2266, #2467, #2663) (#2788)
   * Fix order of comments (#2835) (#2839)
 
 ## [1.2.2](https://github.com/go-gitea/gitea/releases/tag/v1.2.2) - 2017-10-26
+
 * BUGFIXES
   * Add checks for commits with missing author and time (#2771) (#2785)
   * Fix sending mail with a non-latin display name (#2559) (#2783)
@@ -2624,6 +3165,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix emojify image URL (#2769) (#2773)
 
 ## [1.2.1](https://github.com/go-gitea/gitea/releases/tag/v1.2.1) - 2017-10-16
+
 * BUGFIXES
   * Fix PR, milestone and label functionality if issue unit is disabled (#2710) (#2714)
   * Fix plain readme didn't render correctly on repo home page (#2705) (#2712)
@@ -2632,6 +3174,7 @@ WARNING: v1.10.5 is incorrectly tagged targeting 1.12-dev and should **not** be
   * Fix slice out of bounds error in mailer (#2479) (#2696)
 
 ## [1.2.0](https://github.com/go-gitea/gitea/releases/tag/v1.2.0) - 2017-10-10
+
 * SECURITY
   * Sanitation fix from Gogs (#1461)
 * BREAKING
diff --git a/Dockerfile b/Dockerfile
index 8093853605..2f2d67f2a6 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,6 +9,7 @@ ENV GOPROXY ${GOPROXY:-direct}
 ARG GITEA_VERSION
 ARG TAGS="sqlite sqlite_unlock_notify"
 ENV TAGS "bindata $TAGS"
+ARG CGO_EXTRA_CFLAGS
 
 #Build deps
 RUN apk --no-cache add build-base git nodejs npm
diff --git a/Makefile b/Makefile
index 37c9a46d81..04bb5b6c4b 100644
--- a/Makefile
+++ b/Makefile
@@ -33,12 +33,17 @@ MIN_NODE_VERSION := 010013000
 ifeq ($(HAS_GO), GO)
 	GOPATH ?= $(shell $(GO) env GOPATH)
 	export PATH := $(GOPATH)/bin:$(PATH)
+
+	CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
+	CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS)
 endif
 
 
 ifeq ($(OS), Windows_NT)
+	GOFLAGS := -v -buildmode=exe
 	EXECUTABLE ?= gitea.exe
 else
+	GOFLAGS := -v
 	EXECUTABLE ?= gitea
 	UNAME_S := $(shell uname -s)
 	ifeq ($(UNAME_S),Darwin)
@@ -51,7 +56,6 @@ endif
 
 GOFMT ?= gofmt -s
 
-GOFLAGS := -v
 EXTRA_GOFLAGS ?=
 
 MAKE_VERSION := $(shell $(MAKE) -v | head -n 1)
@@ -88,7 +92,7 @@ GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations/migration-test,$(fi
 WEBPACK_SOURCES := $(shell find web_src/js web_src/less -type f)
 WEBPACK_CONFIGS := webpack.config.js
 WEBPACK_DEST := public/js/index.js public/css/index.css
-WEBPACK_DEST_DIRS := public/js public/css public/fonts
+WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/serviceworker.js
 
 BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
 BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
@@ -194,7 +198,7 @@ node-check:
 
 .PHONY: clean-all
 clean-all: clean
-	rm -rf $(WEBPACK_DEST_DIRS) $(FOMANTIC_DEST_DIR)
+	rm -rf $(WEBPACK_DEST_ENTRIES) $(FOMANTIC_DEST_DIR)
 
 .PHONY: clean
 clean:
@@ -250,7 +254,7 @@ swagger-validate:
 .PHONY: errcheck
 errcheck:
 	@hash errcheck > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
-		$(GO) get -u github.com/kisielk/errcheck; \
+		GO111MODULE=off $(GO) get -u github.com/kisielk/errcheck; \
 	fi
 	errcheck $(GO_PACKAGES)
 
@@ -261,14 +265,14 @@ revive:
 .PHONY: misspell-check
 misspell-check:
 	@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
-		$(GO) get -u github.com/client9/misspell/cmd/misspell; \
+		GO111MODULE=off $(GO) get -u github.com/client9/misspell/cmd/misspell; \
 	fi
 	misspell -error -i unknwon,destory $(GO_SOURCES_OWN)
 
 .PHONY: misspell
 misspell:
 	@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
-		$(GO) get -u github.com/client9/misspell/cmd/misspell; \
+		GO111MODULE=off $(GO) get -u github.com/client9/misspell/cmd/misspell; \
 	fi
 	misspell -w -i unknwon $(GO_SOURCES_OWN)
 
@@ -295,6 +299,7 @@ lint-frontend: node_modules
 
 .PHONY: watch-frontend
 watch-frontend: node_modules
+	rm -rf $(WEBPACK_DEST_ENTRIES)
 	NODE_ENV=development npx webpack --hide-modules --display-entrypoints=false --watch --progress
 
 .PHONY: test
@@ -498,7 +503,7 @@ check: test
 
 .PHONY: install $(TAGS_PREREQ)
 install: $(wildcard *.go)
-	$(GO) install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
+	CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
 
 .PHONY: build
 build: frontend backend
@@ -514,7 +519,7 @@ generate: $(TAGS_PREREQ)
 	CC= GOOS= GOARCH= $(GO) generate -mod=vendor -tags '$(TAGS)' $(GO_PACKAGES)
 
 $(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
-	$(GO) build -mod=vendor $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
+	CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build -mod=vendor $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
 
 .PHONY: release
 release: frontend generate release-windows release-linux release-darwin release-copy release-compress release-sources release-check
@@ -525,9 +530,9 @@ $(DIST_DIRS):
 .PHONY: release-windows
 release-windows: | $(DIST_DIRS)
 	@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
-		$(GO) get -u src.techknowlogick.com/xgo; \
+		GO111MODULE=off $(GO) get -u src.techknowlogick.com/xgo; \
 	fi
-	GO111MODULE=off xgo -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
+	CGO_CFLAGS="$(CGO_CFLAGS)" GO111MODULE=off xgo -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
 ifeq ($(CI),drone)
 	cp /build/* $(DIST)/binaries
 endif
@@ -535,9 +540,9 @@ endif
 .PHONY: release-linux
 release-linux: | $(DIST_DIRS)
 	@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
-		$(GO) get -u src.techknowlogick.com/xgo; \
+		GO111MODULE=off $(GO) get -u src.techknowlogick.com/xgo; \
 	fi
-	GO111MODULE=off xgo -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/mips64le,linux/mips,linux/mipsle' -out gitea-$(VERSION) .
+	CGO_CFLAGS="$(CGO_CFLAGS)" GO111MODULE=off xgo -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/mips64le,linux/mips,linux/mipsle' -out gitea-$(VERSION) .
 ifeq ($(CI),drone)
 	cp /build/* $(DIST)/binaries
 endif
@@ -545,9 +550,9 @@ endif
 .PHONY: release-darwin
 release-darwin: | $(DIST_DIRS)
 	@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
-		$(GO) get -u src.techknowlogick.com/xgo; \
+		GO111MODULE=off $(GO) get -u src.techknowlogick.com/xgo; \
 	fi
-	GO111MODULE=off xgo -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin/*' -out gitea-$(VERSION) .
+	CGO_CFLAGS="$(CGO_CFLAGS)" GO111MODULE=off xgo -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin/*' -out gitea-$(VERSION) .
 ifeq ($(CI),drone)
 	cp /build/* $(DIST)/binaries
 endif
@@ -588,9 +593,9 @@ fomantic: $(FOMANTIC_DEST)
 
 $(FOMANTIC_DEST): $(FOMANTIC_CONFIGS) package-lock.json | node_modules
 	rm -rf $(FOMANTIC_DEST_DIR)
-	cp web_src/fomantic/theme.config.less node_modules/fomantic-ui/src/theme.config
-	cp -r web_src/fomantic/_site/* node_modules/fomantic-ui/src/_site/
-	cp web_src/fomantic/css.js node_modules/fomantic-ui/tasks/build/css.js
+	cp -f web_src/fomantic/theme.config.less node_modules/fomantic-ui/src/theme.config
+	cp -rf web_src/fomantic/_site/* node_modules/fomantic-ui/src/_site/
+	cp -f web_src/fomantic/css.js node_modules/fomantic-ui/tasks/build/css.js
 	npx gulp -f node_modules/fomantic-ui/gulpfile.js build
 	@touch $(FOMANTIC_DEST)
 
@@ -598,7 +603,7 @@ $(FOMANTIC_DEST): $(FOMANTIC_CONFIGS) package-lock.json | node_modules
 webpack: $(WEBPACK_DEST)
 
 $(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json | node_modules
-	rm -rf $(WEBPACK_DEST_DIRS)
+	rm -rf $(WEBPACK_DEST_ENTRIES)
 	npx webpack --hide-modules --display-entrypoints=false
 	@touch $(WEBPACK_DEST)
 
diff --git a/assets/emoji.json b/assets/emoji.json
index c31490c2c4..d28c33cff0 100644
--- a/assets/emoji.json
+++ b/assets/emoji.json
@@ -1 +1 @@
-[{"emoji":"๐Ÿ‘","aliases":["+1","thumbsup"]},{"emoji":"๐Ÿ‘Ž","aliases":["-1","thumbsdown"]},{"emoji":"๐Ÿ’ฏ","aliases":["100"]},{"emoji":"๐Ÿ”ข","aliases":["1234"]},{"emoji":"๐Ÿฅ‡","aliases":["1st_place_medal"]},{"emoji":"๐Ÿฅˆ","aliases":["2nd_place_medal"]},{"emoji":"๐Ÿฅ‰","aliases":["3rd_place_medal"]},{"emoji":"๐ŸŽฑ","aliases":["8ball"]},{"emoji":"๐Ÿ…ฐ๏ธ","aliases":["a"]},{"emoji":"๐Ÿ†Ž","aliases":["ab"]},{"emoji":"๐Ÿงฎ","aliases":["abacus"]},{"emoji":"๐Ÿ”ค","aliases":["abc"]},{"emoji":"๐Ÿ”ก","aliases":["abcd"]},{"emoji":"๐Ÿ‰‘","aliases":["accept"]},{"emoji":"๐Ÿฉน","aliases":["adhesive_bandage"]},{"emoji":"๐Ÿง‘","aliases":["adult"]},{"emoji":"๐Ÿšก","aliases":["aerial_tramway"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ซ","aliases":["afghanistan"]},{"emoji":"โœˆ๏ธ","aliases":["airplane"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฝ","aliases":["aland_islands"]},{"emoji":"โฐ","aliases":["alarm_clock"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฑ","aliases":["albania"]},{"emoji":"โš—๏ธ","aliases":["alembic"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ฟ","aliases":["algeria"]},{"emoji":"๐Ÿ‘ฝ","aliases":["alien"]},{"emoji":"๐Ÿš‘","aliases":["ambulance"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ธ","aliases":["american_samoa"]},{"emoji":"๐Ÿบ","aliases":["amphora"]},{"emoji":"โš“","aliases":["anchor"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฉ","aliases":["andorra"]},{"emoji":"๐Ÿ‘ผ","aliases":["angel"]},{"emoji":"๐Ÿ’ข","aliases":["anger"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ด","aliases":["angola"]},{"emoji":"๐Ÿ˜ ","aliases":["angry"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฎ","aliases":["anguilla"]},{"emoji":"๐Ÿ˜ง","aliases":["anguished"]},{"emoji":"๐Ÿœ","aliases":["ant"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ถ","aliases":["antarctica"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฌ","aliases":["antigua_barbuda"]},{"emoji":"๐ŸŽ","aliases":["apple"]},{"emoji":"โ™’","aliases":["aquarius"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ท","aliases":["argentina"]},{"emoji":"โ™ˆ","aliases":["aries"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฒ","aliases":["armenia"]},{"emoji":"โ—€๏ธ","aliases":["arrow_backward"]},{"emoji":"โฌ","aliases":["arrow_double_down"]},{"emoji":"โซ","aliases":["arrow_double_up"]},{"emoji":"โฌ‡๏ธ","aliases":["arrow_down"]},{"emoji":"๐Ÿ”ฝ","aliases":["arrow_down_small"]},{"emoji":"โ–ถ๏ธ","aliases":["arrow_forward"]},{"emoji":"โคต๏ธ","aliases":["arrow_heading_down"]},{"emoji":"โคด๏ธ","aliases":["arrow_heading_up"]},{"emoji":"โฌ…๏ธ","aliases":["arrow_left"]},{"emoji":"โ†™๏ธ","aliases":["arrow_lower_left"]},{"emoji":"โ†˜๏ธ","aliases":["arrow_lower_right"]},{"emoji":"โžก๏ธ","aliases":["arrow_right"]},{"emoji":"โ†ช๏ธ","aliases":["arrow_right_hook"]},{"emoji":"โฌ†๏ธ","aliases":["arrow_up"]},{"emoji":"โ†•๏ธ","aliases":["arrow_up_down"]},{"emoji":"๐Ÿ”ผ","aliases":["arrow_up_small"]},{"emoji":"โ†–๏ธ","aliases":["arrow_upper_left"]},{"emoji":"โ†—๏ธ","aliases":["arrow_upper_right"]},{"emoji":"๐Ÿ”ƒ","aliases":["arrows_clockwise"]},{"emoji":"๐Ÿ”„","aliases":["arrows_counterclockwise"]},{"emoji":"๐ŸŽจ","aliases":["art"]},{"emoji":"๐Ÿš›","aliases":["articulated_lorry"]},{"emoji":"๐Ÿ›ฐ๏ธ","aliases":["artificial_satellite"]},{"emoji":"๐Ÿง‘โ€๐ŸŽจ","aliases":["artist"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ผ","aliases":["aruba"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡จ","aliases":["ascension_island"]},{"emoji":"๐Ÿ˜ฒ","aliases":["astonished"]},{"emoji":"๐Ÿง‘โ€๐Ÿš€","aliases":["astronaut"]},{"emoji":"๐Ÿ‘Ÿ","aliases":["athletic_shoe"]},{"emoji":"๐Ÿง","aliases":["atm"]},{"emoji":"โš›๏ธ","aliases":["atom_symbol"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡บ","aliases":["australia"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡น","aliases":["austria"]},{"emoji":"๐Ÿ›บ","aliases":["auto_rickshaw"]},{"emoji":"๐Ÿฅ‘","aliases":["avocado"]},{"emoji":"๐Ÿช“","aliases":["axe"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฟ","aliases":["azerbaijan"]},{"emoji":"๐Ÿ…ฑ๏ธ","aliases":["b"]},{"emoji":"๐Ÿ‘ถ","aliases":["baby"]},{"emoji":"๐Ÿผ","aliases":["baby_bottle"]},{"emoji":"๐Ÿค","aliases":["baby_chick"]},{"emoji":"๐Ÿšผ","aliases":["baby_symbol"]},{"emoji":"๐Ÿ”™","aliases":["back"]},{"emoji":"๐Ÿฅ“","aliases":["bacon"]},{"emoji":"๐Ÿฆก","aliases":["badger"]},{"emoji":"๐Ÿธ","aliases":["badminton"]},{"emoji":"๐Ÿฅฏ","aliases":["bagel"]},{"emoji":"๐Ÿ›„","aliases":["baggage_claim"]},{"emoji":"๐Ÿฅ–","aliases":["baguette_bread"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ธ","aliases":["bahamas"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ญ","aliases":["bahrain"]},{"emoji":"โš–๏ธ","aliases":["balance_scale"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆฒ","aliases":["bald_man"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆฒ","aliases":["bald_woman"]},{"emoji":"๐Ÿฉฐ","aliases":["ballet_shoes"]},{"emoji":"๐ŸŽˆ","aliases":["balloon"]},{"emoji":"๐Ÿ—ณ๏ธ","aliases":["ballot_box"]},{"emoji":"โ˜‘๏ธ","aliases":["ballot_box_with_check"]},{"emoji":"๐ŸŽ","aliases":["bamboo"]},{"emoji":"๐ŸŒ","aliases":["banana"]},{"emoji":"โ€ผ๏ธ","aliases":["bangbang"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฉ","aliases":["bangladesh"]},{"emoji":"๐Ÿช•","aliases":["banjo"]},{"emoji":"๐Ÿฆ","aliases":["bank"]},{"emoji":"๐Ÿ“Š","aliases":["bar_chart"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ง","aliases":["barbados"]},{"emoji":"๐Ÿ’ˆ","aliases":["barber"]},{"emoji":"โšพ","aliases":["baseball"]},{"emoji":"๐Ÿงบ","aliases":["basket"]},{"emoji":"๐Ÿ€","aliases":["basketball"]},{"emoji":"๐Ÿฆ‡","aliases":["bat"]},{"emoji":"๐Ÿ›€","aliases":["bath"]},{"emoji":"๐Ÿ›","aliases":["bathtub"]},{"emoji":"๐Ÿ”‹","aliases":["battery"]},{"emoji":"๐Ÿ–๏ธ","aliases":["beach_umbrella"]},{"emoji":"๐Ÿป","aliases":["bear"]},{"emoji":"๐Ÿง”","aliases":["bearded_person"]},{"emoji":"๐Ÿ›๏ธ","aliases":["bed"]},{"emoji":"๐Ÿ","aliases":["bee","honeybee"]},{"emoji":"๐Ÿบ","aliases":["beer"]},{"emoji":"๐Ÿป","aliases":["beers"]},{"emoji":"๐Ÿ”ฐ","aliases":["beginner"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡พ","aliases":["belarus"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ช","aliases":["belgium"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฟ","aliases":["belize"]},{"emoji":"๐Ÿ””","aliases":["bell"]},{"emoji":"๐Ÿ›Ž๏ธ","aliases":["bellhop_bell"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฏ","aliases":["benin"]},{"emoji":"๐Ÿฑ","aliases":["bento"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฒ","aliases":["bermuda"]},{"emoji":"๐Ÿงƒ","aliases":["beverage_box"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡น","aliases":["bhutan"]},{"emoji":"๐Ÿšด","aliases":["bicyclist"]},{"emoji":"๐Ÿšฒ","aliases":["bike"]},{"emoji":"๐Ÿšดโ€โ™‚๏ธ","aliases":["biking_man"]},{"emoji":"๐Ÿšดโ€โ™€๏ธ","aliases":["biking_woman"]},{"emoji":"๐Ÿ‘™","aliases":["bikini"]},{"emoji":"๐Ÿงข","aliases":["billed_cap"]},{"emoji":"โ˜ฃ๏ธ","aliases":["biohazard"]},{"emoji":"๐Ÿฆ","aliases":["bird"]},{"emoji":"๐ŸŽ‚","aliases":["birthday"]},{"emoji":"โšซ","aliases":["black_circle"]},{"emoji":"๐Ÿด","aliases":["black_flag"]},{"emoji":"๐Ÿ–ค","aliases":["black_heart"]},{"emoji":"๐Ÿƒ","aliases":["black_joker"]},{"emoji":"โฌ›","aliases":["black_large_square"]},{"emoji":"โ—พ","aliases":["black_medium_small_square"]},{"emoji":"โ—ผ๏ธ","aliases":["black_medium_square"]},{"emoji":"โœ’๏ธ","aliases":["black_nib"]},{"emoji":"โ–ช๏ธ","aliases":["black_small_square"]},{"emoji":"๐Ÿ”ฒ","aliases":["black_square_button"]},{"emoji":"๐Ÿ‘ฑโ€โ™‚๏ธ","aliases":["blond_haired_man"]},{"emoji":"๐Ÿ‘ฑ","aliases":["blond_haired_person"]},{"emoji":"๐Ÿ‘ฑโ€โ™€๏ธ","aliases":["blond_haired_woman","blonde_woman"]},{"emoji":"๐ŸŒผ","aliases":["blossom"]},{"emoji":"๐Ÿก","aliases":["blowfish"]},{"emoji":"๐Ÿ“˜","aliases":["blue_book"]},{"emoji":"๐Ÿš™","aliases":["blue_car"]},{"emoji":"๐Ÿ’™","aliases":["blue_heart"]},{"emoji":"๐ŸŸฆ","aliases":["blue_square"]},{"emoji":"๐Ÿ˜Š","aliases":["blush"]},{"emoji":"๐Ÿ—","aliases":["boar"]},{"emoji":"โ›ต","aliases":["boat","sailboat"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ด","aliases":["bolivia"]},{"emoji":"๐Ÿ’ฃ","aliases":["bomb"]},{"emoji":"๐Ÿฆด","aliases":["bone"]},{"emoji":"๐Ÿ“–","aliases":["book","open_book"]},{"emoji":"๐Ÿ”–","aliases":["bookmark"]},{"emoji":"๐Ÿ“‘","aliases":["bookmark_tabs"]},{"emoji":"๐Ÿ“š","aliases":["books"]},{"emoji":"๐Ÿ’ฅ","aliases":["boom","collision"]},{"emoji":"๐Ÿ‘ข","aliases":["boot"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฆ","aliases":["bosnia_herzegovina"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ผ","aliases":["botswana"]},{"emoji":"โ›น๏ธโ€โ™‚๏ธ","aliases":["bouncing_ball_man","basketball_man"]},{"emoji":"โ›น๏ธ","aliases":["bouncing_ball_person"]},{"emoji":"โ›น๏ธโ€โ™€๏ธ","aliases":["bouncing_ball_woman","basketball_woman"]},{"emoji":"๐Ÿ’","aliases":["bouquet"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ป","aliases":["bouvet_island"]},{"emoji":"๐Ÿ™‡","aliases":["bow"]},{"emoji":"๐Ÿน","aliases":["bow_and_arrow"]},{"emoji":"๐Ÿ™‡โ€โ™‚๏ธ","aliases":["bowing_man"]},{"emoji":"๐Ÿ™‡โ€โ™€๏ธ","aliases":["bowing_woman"]},{"emoji":"๐Ÿฅฃ","aliases":["bowl_with_spoon"]},{"emoji":"๐ŸŽณ","aliases":["bowling"]},{"emoji":"๐ŸฅŠ","aliases":["boxing_glove"]},{"emoji":"๐Ÿ‘ฆ","aliases":["boy"]},{"emoji":"๐Ÿง ","aliases":["brain"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ท","aliases":["brazil"]},{"emoji":"๐Ÿž","aliases":["bread"]},{"emoji":"๐Ÿคฑ","aliases":["breast_feeding"]},{"emoji":"๐Ÿงฑ","aliases":["bricks"]},{"emoji":"๐ŸŒ‰","aliases":["bridge_at_night"]},{"emoji":"๐Ÿ’ผ","aliases":["briefcase"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ด","aliases":["british_indian_ocean_territory"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡ฌ","aliases":["british_virgin_islands"]},{"emoji":"๐Ÿฅฆ","aliases":["broccoli"]},{"emoji":"๐Ÿ’”","aliases":["broken_heart"]},{"emoji":"๐Ÿงน","aliases":["broom"]},{"emoji":"๐ŸŸค","aliases":["brown_circle"]},{"emoji":"๐ŸคŽ","aliases":["brown_heart"]},{"emoji":"๐ŸŸซ","aliases":["brown_square"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ณ","aliases":["brunei"]},{"emoji":"๐Ÿ›","aliases":["bug"]},{"emoji":"๐Ÿ—๏ธ","aliases":["building_construction"]},{"emoji":"๐Ÿ’ก","aliases":["bulb"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฌ","aliases":["bulgaria"]},{"emoji":"๐Ÿš…","aliases":["bullettrain_front"]},{"emoji":"๐Ÿš„","aliases":["bullettrain_side"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ซ","aliases":["burkina_faso"]},{"emoji":"๐ŸŒฏ","aliases":["burrito"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฎ","aliases":["burundi"]},{"emoji":"๐ŸšŒ","aliases":["bus"]},{"emoji":"๐Ÿ•ด๏ธ","aliases":["business_suit_levitating"]},{"emoji":"๐Ÿš","aliases":["busstop"]},{"emoji":"๐Ÿ‘ค","aliases":["bust_in_silhouette"]},{"emoji":"๐Ÿ‘ฅ","aliases":["busts_in_silhouette"]},{"emoji":"๐Ÿงˆ","aliases":["butter"]},{"emoji":"๐Ÿฆ‹","aliases":["butterfly"]},{"emoji":"๐ŸŒต","aliases":["cactus"]},{"emoji":"๐Ÿฐ","aliases":["cake"]},{"emoji":"๐Ÿ“†","aliases":["calendar"]},{"emoji":"๐Ÿค™","aliases":["call_me_hand"]},{"emoji":"๐Ÿ“ฒ","aliases":["calling"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ญ","aliases":["cambodia"]},{"emoji":"๐Ÿซ","aliases":["camel"]},{"emoji":"๐Ÿ“ท","aliases":["camera"]},{"emoji":"๐Ÿ“ธ","aliases":["camera_flash"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฒ","aliases":["cameroon"]},{"emoji":"๐Ÿ•๏ธ","aliases":["camping"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฆ","aliases":["canada"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡จ","aliases":["canary_islands"]},{"emoji":"โ™‹","aliases":["cancer"]},{"emoji":"๐Ÿ•ฏ๏ธ","aliases":["candle"]},{"emoji":"๐Ÿฌ","aliases":["candy"]},{"emoji":"๐Ÿฅซ","aliases":["canned_food"]},{"emoji":"๐Ÿ›ถ","aliases":["canoe"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ป","aliases":["cape_verde"]},{"emoji":"๐Ÿ” ","aliases":["capital_abcd"]},{"emoji":"โ™‘","aliases":["capricorn"]},{"emoji":"๐Ÿš—","aliases":["car","red_car"]},{"emoji":"๐Ÿ—ƒ๏ธ","aliases":["card_file_box"]},{"emoji":"๐Ÿ“‡","aliases":["card_index"]},{"emoji":"๐Ÿ—‚๏ธ","aliases":["card_index_dividers"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ถ","aliases":["caribbean_netherlands"]},{"emoji":"๐ŸŽ ","aliases":["carousel_horse"]},{"emoji":"๐Ÿฅ•","aliases":["carrot"]},{"emoji":"๐Ÿคธ","aliases":["cartwheeling"]},{"emoji":"๐Ÿฑ","aliases":["cat"]},{"emoji":"๐Ÿˆ","aliases":["cat2"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡พ","aliases":["cayman_islands"]},{"emoji":"๐Ÿ’ฟ","aliases":["cd"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ซ","aliases":["central_african_republic"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ฆ","aliases":["ceuta_melilla"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฉ","aliases":["chad"]},{"emoji":"โ›“๏ธ","aliases":["chains"]},{"emoji":"๐Ÿช‘","aliases":["chair"]},{"emoji":"๐Ÿพ","aliases":["champagne"]},{"emoji":"๐Ÿ’น","aliases":["chart"]},{"emoji":"๐Ÿ“‰","aliases":["chart_with_downwards_trend"]},{"emoji":"๐Ÿ“ˆ","aliases":["chart_with_upwards_trend"]},{"emoji":"๐Ÿ","aliases":["checkered_flag"]},{"emoji":"๐Ÿง€","aliases":["cheese"]},{"emoji":"๐Ÿ’","aliases":["cherries"]},{"emoji":"๐ŸŒธ","aliases":["cherry_blossom"]},{"emoji":"โ™Ÿ๏ธ","aliases":["chess_pawn"]},{"emoji":"๐ŸŒฐ","aliases":["chestnut"]},{"emoji":"๐Ÿ”","aliases":["chicken"]},{"emoji":"๐Ÿง’","aliases":["child"]},{"emoji":"๐Ÿšธ","aliases":["children_crossing"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฑ","aliases":["chile"]},{"emoji":"๐Ÿฟ๏ธ","aliases":["chipmunk"]},{"emoji":"๐Ÿซ","aliases":["chocolate_bar"]},{"emoji":"๐Ÿฅข","aliases":["chopsticks"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฝ","aliases":["christmas_island"]},{"emoji":"๐ŸŽ„","aliases":["christmas_tree"]},{"emoji":"โ›ช","aliases":["church"]},{"emoji":"๐ŸŽฆ","aliases":["cinema"]},{"emoji":"๐ŸŽช","aliases":["circus_tent"]},{"emoji":"๐ŸŒ‡","aliases":["city_sunrise"]},{"emoji":"๐ŸŒ†","aliases":["city_sunset"]},{"emoji":"๐Ÿ™๏ธ","aliases":["cityscape"]},{"emoji":"๐Ÿ†‘","aliases":["cl"]},{"emoji":"๐Ÿ—œ๏ธ","aliases":["clamp"]},{"emoji":"๐Ÿ‘","aliases":["clap"]},{"emoji":"๐ŸŽฌ","aliases":["clapper"]},{"emoji":"๐Ÿ›๏ธ","aliases":["classical_building"]},{"emoji":"๐Ÿง—","aliases":["climbing"]},{"emoji":"๐Ÿง—โ€โ™‚๏ธ","aliases":["climbing_man"]},{"emoji":"๐Ÿง—โ€โ™€๏ธ","aliases":["climbing_woman"]},{"emoji":"๐Ÿฅ‚","aliases":["clinking_glasses"]},{"emoji":"๐Ÿ“‹","aliases":["clipboard"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ต","aliases":["clipperton_island"]},{"emoji":"๐Ÿ•","aliases":["clock1"]},{"emoji":"๐Ÿ•™","aliases":["clock10"]},{"emoji":"๐Ÿ•ฅ","aliases":["clock1030"]},{"emoji":"๐Ÿ•š","aliases":["clock11"]},{"emoji":"๐Ÿ•ฆ","aliases":["clock1130"]},{"emoji":"๐Ÿ•›","aliases":["clock12"]},{"emoji":"๐Ÿ•ง","aliases":["clock1230"]},{"emoji":"๐Ÿ•œ","aliases":["clock130"]},{"emoji":"๐Ÿ•‘","aliases":["clock2"]},{"emoji":"๐Ÿ•","aliases":["clock230"]},{"emoji":"๐Ÿ•’","aliases":["clock3"]},{"emoji":"๐Ÿ•ž","aliases":["clock330"]},{"emoji":"๐Ÿ•“","aliases":["clock4"]},{"emoji":"๐Ÿ•Ÿ","aliases":["clock430"]},{"emoji":"๐Ÿ•”","aliases":["clock5"]},{"emoji":"๐Ÿ• ","aliases":["clock530"]},{"emoji":"๐Ÿ••","aliases":["clock6"]},{"emoji":"๐Ÿ•ก","aliases":["clock630"]},{"emoji":"๐Ÿ•–","aliases":["clock7"]},{"emoji":"๐Ÿ•ข","aliases":["clock730"]},{"emoji":"๐Ÿ•—","aliases":["clock8"]},{"emoji":"๐Ÿ•ฃ","aliases":["clock830"]},{"emoji":"๐Ÿ•˜","aliases":["clock9"]},{"emoji":"๐Ÿ•ค","aliases":["clock930"]},{"emoji":"๐Ÿ“•","aliases":["closed_book"]},{"emoji":"๐Ÿ”","aliases":["closed_lock_with_key"]},{"emoji":"๐ŸŒ‚","aliases":["closed_umbrella"]},{"emoji":"โ˜๏ธ","aliases":["cloud"]},{"emoji":"๐ŸŒฉ๏ธ","aliases":["cloud_with_lightning"]},{"emoji":"โ›ˆ๏ธ","aliases":["cloud_with_lightning_and_rain"]},{"emoji":"๐ŸŒง๏ธ","aliases":["cloud_with_rain"]},{"emoji":"๐ŸŒจ๏ธ","aliases":["cloud_with_snow"]},{"emoji":"๐Ÿคก","aliases":["clown_face"]},{"emoji":"โ™ฃ๏ธ","aliases":["clubs"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ณ","aliases":["cn"]},{"emoji":"๐Ÿงฅ","aliases":["coat"]},{"emoji":"๐Ÿธ","aliases":["cocktail"]},{"emoji":"๐Ÿฅฅ","aliases":["coconut"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡จ","aliases":["cocos_islands"]},{"emoji":"โ˜•","aliases":["coffee"]},{"emoji":"โšฐ๏ธ","aliases":["coffin"]},{"emoji":"๐Ÿฅถ","aliases":["cold_face"]},{"emoji":"๐Ÿ˜ฐ","aliases":["cold_sweat"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ด","aliases":["colombia"]},{"emoji":"โ˜„๏ธ","aliases":["comet"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ฒ","aliases":["comoros"]},{"emoji":"๐Ÿงญ","aliases":["compass"]},{"emoji":"๐Ÿ’ป","aliases":["computer"]},{"emoji":"๐Ÿ–ฑ๏ธ","aliases":["computer_mouse"]},{"emoji":"๐ŸŽŠ","aliases":["confetti_ball"]},{"emoji":"๐Ÿ˜–","aliases":["confounded"]},{"emoji":"๐Ÿ˜•","aliases":["confused"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฌ","aliases":["congo_brazzaville"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฉ","aliases":["congo_kinshasa"]},{"emoji":"ใŠ—๏ธ","aliases":["congratulations"]},{"emoji":"๐Ÿšง","aliases":["construction"]},{"emoji":"๐Ÿ‘ท","aliases":["construction_worker"]},{"emoji":"๐Ÿ‘ทโ€โ™‚๏ธ","aliases":["construction_worker_man"]},{"emoji":"๐Ÿ‘ทโ€โ™€๏ธ","aliases":["construction_worker_woman"]},{"emoji":"๐ŸŽ›๏ธ","aliases":["control_knobs"]},{"emoji":"๐Ÿช","aliases":["convenience_store"]},{"emoji":"๐Ÿง‘โ€๐Ÿณ","aliases":["cook"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฐ","aliases":["cook_islands"]},{"emoji":"๐Ÿช","aliases":["cookie"]},{"emoji":"๐Ÿ†’","aliases":["cool"]},{"emoji":"๐ŸŒฝ","aliases":["corn"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ท","aliases":["costa_rica"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฎ","aliases":["cote_divoire"]},{"emoji":"๐Ÿ›‹๏ธ","aliases":["couch_and_lamp"]},{"emoji":"๐Ÿ‘ซ","aliases":["couple"]},{"emoji":"๐Ÿ’‘","aliases":["couple_with_heart"]},{"emoji":"๐Ÿ‘จโ€โค๏ธโ€๐Ÿ‘จ","aliases":["couple_with_heart_man_man"]},{"emoji":"๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘จ","aliases":["couple_with_heart_woman_man"]},{"emoji":"๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘ฉ","aliases":["couple_with_heart_woman_woman"]},{"emoji":"๐Ÿ’","aliases":["couplekiss"]},{"emoji":"๐Ÿ‘จโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ","aliases":["couplekiss_man_man"]},{"emoji":"๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ","aliases":["couplekiss_man_woman"]},{"emoji":"๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘ฉ","aliases":["couplekiss_woman_woman"]},{"emoji":"๐Ÿฎ","aliases":["cow"]},{"emoji":"๐Ÿ„","aliases":["cow2"]},{"emoji":"๐Ÿค ","aliases":["cowboy_hat_face"]},{"emoji":"๐Ÿฆ€","aliases":["crab"]},{"emoji":"๐Ÿ–๏ธ","aliases":["crayon"]},{"emoji":"๐Ÿ’ณ","aliases":["credit_card"]},{"emoji":"๐ŸŒ™","aliases":["crescent_moon"]},{"emoji":"๐Ÿฆ—","aliases":["cricket"]},{"emoji":"๐Ÿ","aliases":["cricket_game"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡ท","aliases":["croatia"]},{"emoji":"๐ŸŠ","aliases":["crocodile"]},{"emoji":"๐Ÿฅ","aliases":["croissant"]},{"emoji":"๐Ÿคž","aliases":["crossed_fingers"]},{"emoji":"๐ŸŽŒ","aliases":["crossed_flags"]},{"emoji":"โš”๏ธ","aliases":["crossed_swords"]},{"emoji":"๐Ÿ‘‘","aliases":["crown"]},{"emoji":"๐Ÿ˜ข","aliases":["cry"]},{"emoji":"๐Ÿ˜ฟ","aliases":["crying_cat_face"]},{"emoji":"๐Ÿ”ฎ","aliases":["crystal_ball"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡บ","aliases":["cuba"]},{"emoji":"๐Ÿฅ’","aliases":["cucumber"]},{"emoji":"๐Ÿฅค","aliases":["cup_with_straw"]},{"emoji":"๐Ÿง","aliases":["cupcake"]},{"emoji":"๐Ÿ’˜","aliases":["cupid"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ผ","aliases":["curacao"]},{"emoji":"๐ŸฅŒ","aliases":["curling_stone"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆฑ","aliases":["curly_haired_man"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆฑ","aliases":["curly_haired_woman"]},{"emoji":"โžฐ","aliases":["curly_loop"]},{"emoji":"๐Ÿ’ฑ","aliases":["currency_exchange"]},{"emoji":"๐Ÿ›","aliases":["curry"]},{"emoji":"๐Ÿคฌ","aliases":["cursing_face"]},{"emoji":"๐Ÿฎ","aliases":["custard"]},{"emoji":"๐Ÿ›ƒ","aliases":["customs"]},{"emoji":"๐Ÿฅฉ","aliases":["cut_of_meat"]},{"emoji":"๐ŸŒ€","aliases":["cyclone"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡พ","aliases":["cyprus"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฟ","aliases":["czech_republic"]},{"emoji":"๐Ÿ—ก๏ธ","aliases":["dagger"]},{"emoji":"๐Ÿ‘ฏ","aliases":["dancers"]},{"emoji":"๐Ÿ‘ฏโ€โ™‚๏ธ","aliases":["dancing_men"]},{"emoji":"๐Ÿ‘ฏโ€โ™€๏ธ","aliases":["dancing_women"]},{"emoji":"๐Ÿก","aliases":["dango"]},{"emoji":"๐Ÿ•ถ๏ธ","aliases":["dark_sunglasses"]},{"emoji":"๐ŸŽฏ","aliases":["dart"]},{"emoji":"๐Ÿ’จ","aliases":["dash"]},{"emoji":"๐Ÿ“…","aliases":["date"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ช","aliases":["de"]},{"emoji":"๐Ÿงโ€โ™‚๏ธ","aliases":["deaf_man"]},{"emoji":"๐Ÿง","aliases":["deaf_person"]},{"emoji":"๐Ÿงโ€โ™€๏ธ","aliases":["deaf_woman"]},{"emoji":"๐ŸŒณ","aliases":["deciduous_tree"]},{"emoji":"๐ŸฆŒ","aliases":["deer"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ฐ","aliases":["denmark"]},{"emoji":"๐Ÿฌ","aliases":["department_store"]},{"emoji":"๐Ÿš๏ธ","aliases":["derelict_house"]},{"emoji":"๐Ÿœ๏ธ","aliases":["desert"]},{"emoji":"๐Ÿ๏ธ","aliases":["desert_island"]},{"emoji":"๐Ÿ–ฅ๏ธ","aliases":["desktop_computer"]},{"emoji":"๐Ÿ•ต๏ธ","aliases":["detective"]},{"emoji":"๐Ÿ’ ","aliases":["diamond_shape_with_a_dot_inside"]},{"emoji":"โ™ฆ๏ธ","aliases":["diamonds"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ฌ","aliases":["diego_garcia"]},{"emoji":"๐Ÿ˜ž","aliases":["disappointed"]},{"emoji":"๐Ÿ˜ฅ","aliases":["disappointed_relieved"]},{"emoji":"๐Ÿคฟ","aliases":["diving_mask"]},{"emoji":"๐Ÿช”","aliases":["diya_lamp"]},{"emoji":"๐Ÿ’ซ","aliases":["dizzy"]},{"emoji":"๐Ÿ˜ต","aliases":["dizzy_face"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ฏ","aliases":["djibouti"]},{"emoji":"๐Ÿงฌ","aliases":["dna"]},{"emoji":"๐Ÿšฏ","aliases":["do_not_litter"]},{"emoji":"๐Ÿถ","aliases":["dog"]},{"emoji":"๐Ÿ•","aliases":["dog2"]},{"emoji":"๐Ÿ’ต","aliases":["dollar"]},{"emoji":"๐ŸŽŽ","aliases":["dolls"]},{"emoji":"๐Ÿฌ","aliases":["dolphin","flipper"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ฒ","aliases":["dominica"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ด","aliases":["dominican_republic"]},{"emoji":"๐Ÿšช","aliases":["door"]},{"emoji":"๐Ÿฉ","aliases":["doughnut"]},{"emoji":"๐Ÿ•Š๏ธ","aliases":["dove"]},{"emoji":"๐Ÿ‰","aliases":["dragon"]},{"emoji":"๐Ÿฒ","aliases":["dragon_face"]},{"emoji":"๐Ÿ‘—","aliases":["dress"]},{"emoji":"๐Ÿช","aliases":["dromedary_camel"]},{"emoji":"๐Ÿคค","aliases":["drooling_face"]},{"emoji":"๐Ÿฉธ","aliases":["drop_of_blood"]},{"emoji":"๐Ÿ’ง","aliases":["droplet"]},{"emoji":"๐Ÿฅ","aliases":["drum"]},{"emoji":"๐Ÿฆ†","aliases":["duck"]},{"emoji":"๐ŸฅŸ","aliases":["dumpling"]},{"emoji":"๐Ÿ“€","aliases":["dvd"]},{"emoji":"๐Ÿ“ง","aliases":["e-mail"]},{"emoji":"๐Ÿฆ…","aliases":["eagle"]},{"emoji":"๐Ÿ‘‚","aliases":["ear"]},{"emoji":"๐ŸŒพ","aliases":["ear_of_rice"]},{"emoji":"๐Ÿฆป","aliases":["ear_with_hearing_aid"]},{"emoji":"๐ŸŒ","aliases":["earth_africa"]},{"emoji":"๐ŸŒŽ","aliases":["earth_americas"]},{"emoji":"๐ŸŒ","aliases":["earth_asia"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡จ","aliases":["ecuador"]},{"emoji":"๐Ÿฅš","aliases":["egg"]},{"emoji":"๐Ÿ†","aliases":["eggplant"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ฌ","aliases":["egypt"]},{"emoji":"โœด๏ธ","aliases":["eight_pointed_black_star"]},{"emoji":"โœณ๏ธ","aliases":["eight_spoked_asterisk"]},{"emoji":"โ๏ธ","aliases":["eject_button"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ป","aliases":["el_salvador"]},{"emoji":"๐Ÿ”Œ","aliases":["electric_plug"]},{"emoji":"๐Ÿ˜","aliases":["elephant"]},{"emoji":"๐Ÿง","aliases":["elf"]},{"emoji":"๐Ÿงโ€โ™‚๏ธ","aliases":["elf_man"]},{"emoji":"๐Ÿงโ€โ™€๏ธ","aliases":["elf_woman"]},{"emoji":"โœ‰๏ธ","aliases":["email","envelope"]},{"emoji":"๐Ÿ”š","aliases":["end"]},{"emoji":"๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ","aliases":["england"]},{"emoji":"๐Ÿ“ฉ","aliases":["envelope_with_arrow"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ถ","aliases":["equatorial_guinea"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ท","aliases":["eritrea"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ธ","aliases":["es"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ช","aliases":["estonia"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡น","aliases":["ethiopia"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡บ","aliases":["eu","european_union"]},{"emoji":"๐Ÿ’ถ","aliases":["euro"]},{"emoji":"๐Ÿฐ","aliases":["european_castle"]},{"emoji":"๐Ÿค","aliases":["european_post_office"]},{"emoji":"๐ŸŒฒ","aliases":["evergreen_tree"]},{"emoji":"โ—","aliases":["exclamation","heavy_exclamation_mark"]},{"emoji":"๐Ÿคฏ","aliases":["exploding_head"]},{"emoji":"๐Ÿ˜‘","aliases":["expressionless"]},{"emoji":"๐Ÿ‘๏ธ","aliases":["eye"]},{"emoji":"๐Ÿ‘๏ธโ€๐Ÿ—จ๏ธ","aliases":["eye_speech_bubble"]},{"emoji":"๐Ÿ‘“","aliases":["eyeglasses"]},{"emoji":"๐Ÿ‘€","aliases":["eyes"]},{"emoji":"๐Ÿค•","aliases":["face_with_head_bandage"]},{"emoji":"๐Ÿค’","aliases":["face_with_thermometer"]},{"emoji":"๐Ÿคฆ","aliases":["facepalm"]},{"emoji":"๐Ÿญ","aliases":["factory"]},{"emoji":"๐Ÿง‘โ€๐Ÿญ","aliases":["factory_worker"]},{"emoji":"๐Ÿงš","aliases":["fairy"]},{"emoji":"๐Ÿงšโ€โ™‚๏ธ","aliases":["fairy_man"]},{"emoji":"๐Ÿงšโ€โ™€๏ธ","aliases":["fairy_woman"]},{"emoji":"๐Ÿง†","aliases":["falafel"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ฐ","aliases":["falkland_islands"]},{"emoji":"๐Ÿ‚","aliases":["fallen_leaf"]},{"emoji":"๐Ÿ‘ช","aliases":["family"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฆ","aliases":["family_man_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","aliases":["family_man_boy_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ง","aliases":["family_man_girl"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","aliases":["family_man_girl_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง","aliases":["family_man_girl_girl"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆ","aliases":["family_man_man_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","aliases":["family_man_man_boy_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ง","aliases":["family_man_man_girl"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","aliases":["family_man_man_girl_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง","aliases":["family_man_man_girl_girl"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ","aliases":["family_man_woman_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","aliases":["family_man_woman_boy_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง","aliases":["family_man_woman_girl"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","aliases":["family_man_woman_girl_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง","aliases":["family_man_woman_girl_girl"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฆ","aliases":["family_woman_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","aliases":["family_woman_boy_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ง","aliases":["family_woman_girl"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","aliases":["family_woman_girl_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง","aliases":["family_woman_girl_girl"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ","aliases":["family_woman_woman_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","aliases":["family_woman_woman_boy_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง","aliases":["family_woman_woman_girl"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","aliases":["family_woman_woman_girl_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง","aliases":["family_woman_woman_girl_girl"]},{"emoji":"๐Ÿง‘โ€๐ŸŒพ","aliases":["farmer"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ด","aliases":["faroe_islands"]},{"emoji":"โฉ","aliases":["fast_forward"]},{"emoji":"๐Ÿ“ ","aliases":["fax"]},{"emoji":"๐Ÿ˜จ","aliases":["fearful"]},{"emoji":"๐Ÿพ","aliases":["feet","paw_prints"]},{"emoji":"๐Ÿ•ต๏ธโ€โ™€๏ธ","aliases":["female_detective"]},{"emoji":"โ™€๏ธ","aliases":["female_sign"]},{"emoji":"๐ŸŽก","aliases":["ferris_wheel"]},{"emoji":"โ›ด๏ธ","aliases":["ferry"]},{"emoji":"๐Ÿ‘","aliases":["field_hockey"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ฏ","aliases":["fiji"]},{"emoji":"๐Ÿ—„๏ธ","aliases":["file_cabinet"]},{"emoji":"๐Ÿ“","aliases":["file_folder"]},{"emoji":"๐Ÿ“ฝ๏ธ","aliases":["film_projector"]},{"emoji":"๐ŸŽž๏ธ","aliases":["film_strip"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ฎ","aliases":["finland"]},{"emoji":"๐Ÿ”ฅ","aliases":["fire"]},{"emoji":"๐Ÿš’","aliases":["fire_engine"]},{"emoji":"๐Ÿงฏ","aliases":["fire_extinguisher"]},{"emoji":"๐Ÿงจ","aliases":["firecracker"]},{"emoji":"๐Ÿง‘โ€๐Ÿš’","aliases":["firefighter"]},{"emoji":"๐ŸŽ†","aliases":["fireworks"]},{"emoji":"๐ŸŒ“","aliases":["first_quarter_moon"]},{"emoji":"๐ŸŒ›","aliases":["first_quarter_moon_with_face"]},{"emoji":"๐ŸŸ","aliases":["fish"]},{"emoji":"๐Ÿฅ","aliases":["fish_cake"]},{"emoji":"๐ŸŽฃ","aliases":["fishing_pole_and_fish"]},{"emoji":"๐Ÿค›","aliases":["fist_left"]},{"emoji":"๐Ÿ‘Š","aliases":["fist_oncoming","facepunch","punch"]},{"emoji":"โœŠ","aliases":["fist_raised","fist"]},{"emoji":"๐Ÿคœ","aliases":["fist_right"]},{"emoji":"๐ŸŽ","aliases":["flags"]},{"emoji":"๐Ÿฆฉ","aliases":["flamingo"]},{"emoji":"๐Ÿ”ฆ","aliases":["flashlight"]},{"emoji":"๐Ÿฅฟ","aliases":["flat_shoe"]},{"emoji":"โšœ๏ธ","aliases":["fleur_de_lis"]},{"emoji":"๐Ÿ›ฌ","aliases":["flight_arrival"]},{"emoji":"๐Ÿ›ซ","aliases":["flight_departure"]},{"emoji":"๐Ÿ’พ","aliases":["floppy_disk"]},{"emoji":"๐ŸŽด","aliases":["flower_playing_cards"]},{"emoji":"๐Ÿ˜ณ","aliases":["flushed"]},{"emoji":"๐Ÿฅ","aliases":["flying_disc"]},{"emoji":"๐Ÿ›ธ","aliases":["flying_saucer"]},{"emoji":"๐ŸŒซ๏ธ","aliases":["fog"]},{"emoji":"๐ŸŒ","aliases":["foggy"]},{"emoji":"๐Ÿฆถ","aliases":["foot"]},{"emoji":"๐Ÿˆ","aliases":["football"]},{"emoji":"๐Ÿ‘ฃ","aliases":["footprints"]},{"emoji":"๐Ÿด","aliases":["fork_and_knife"]},{"emoji":"๐Ÿฅ ","aliases":["fortune_cookie"]},{"emoji":"โ›ฒ","aliases":["fountain"]},{"emoji":"๐Ÿ–‹๏ธ","aliases":["fountain_pen"]},{"emoji":"๐Ÿ€","aliases":["four_leaf_clover"]},{"emoji":"๐ŸฆŠ","aliases":["fox_face"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ท","aliases":["fr"]},{"emoji":"๐Ÿ–ผ๏ธ","aliases":["framed_picture"]},{"emoji":"๐Ÿ†“","aliases":["free"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ซ","aliases":["french_guiana"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ซ","aliases":["french_polynesia"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ซ","aliases":["french_southern_territories"]},{"emoji":"๐Ÿณ","aliases":["fried_egg"]},{"emoji":"๐Ÿค","aliases":["fried_shrimp"]},{"emoji":"๐ŸŸ","aliases":["fries"]},{"emoji":"๐Ÿธ","aliases":["frog"]},{"emoji":"๐Ÿ˜ฆ","aliases":["frowning"]},{"emoji":"โ˜น๏ธ","aliases":["frowning_face"]},{"emoji":"๐Ÿ™โ€โ™‚๏ธ","aliases":["frowning_man"]},{"emoji":"๐Ÿ™","aliases":["frowning_person"]},{"emoji":"๐Ÿ™โ€โ™€๏ธ","aliases":["frowning_woman"]},{"emoji":"โ›ฝ","aliases":["fuelpump"]},{"emoji":"๐ŸŒ•","aliases":["full_moon"]},{"emoji":"๐ŸŒ","aliases":["full_moon_with_face"]},{"emoji":"โšฑ๏ธ","aliases":["funeral_urn"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฆ","aliases":["gabon"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฒ","aliases":["gambia"]},{"emoji":"๐ŸŽฒ","aliases":["game_die"]},{"emoji":"๐Ÿง„","aliases":["garlic"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ง","aliases":["gb","uk"]},{"emoji":"โš™๏ธ","aliases":["gear"]},{"emoji":"๐Ÿ’Ž","aliases":["gem"]},{"emoji":"โ™Š","aliases":["gemini"]},{"emoji":"๐Ÿงž","aliases":["genie"]},{"emoji":"๐Ÿงžโ€โ™‚๏ธ","aliases":["genie_man"]},{"emoji":"๐Ÿงžโ€โ™€๏ธ","aliases":["genie_woman"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ช","aliases":["georgia"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ญ","aliases":["ghana"]},{"emoji":"๐Ÿ‘ป","aliases":["ghost"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฎ","aliases":["gibraltar"]},{"emoji":"๐ŸŽ","aliases":["gift"]},{"emoji":"๐Ÿ’","aliases":["gift_heart"]},{"emoji":"๐Ÿฆ’","aliases":["giraffe"]},{"emoji":"๐Ÿ‘ง","aliases":["girl"]},{"emoji":"๐ŸŒ","aliases":["globe_with_meridians"]},{"emoji":"๐Ÿงค","aliases":["gloves"]},{"emoji":"๐Ÿฅ…","aliases":["goal_net"]},{"emoji":"๐Ÿ","aliases":["goat"]},{"emoji":"๐Ÿฅฝ","aliases":["goggles"]},{"emoji":"โ›ณ","aliases":["golf"]},{"emoji":"๐ŸŒ๏ธ","aliases":["golfing"]},{"emoji":"๐ŸŒ๏ธโ€โ™‚๏ธ","aliases":["golfing_man"]},{"emoji":"๐ŸŒ๏ธโ€โ™€๏ธ","aliases":["golfing_woman"]},{"emoji":"๐Ÿฆ","aliases":["gorilla"]},{"emoji":"๐Ÿ‡","aliases":["grapes"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ท","aliases":["greece"]},{"emoji":"๐Ÿ","aliases":["green_apple"]},{"emoji":"๐Ÿ“—","aliases":["green_book"]},{"emoji":"๐ŸŸข","aliases":["green_circle"]},{"emoji":"๐Ÿ’š","aliases":["green_heart"]},{"emoji":"๐Ÿฅ—","aliases":["green_salad"]},{"emoji":"๐ŸŸฉ","aliases":["green_square"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฑ","aliases":["greenland"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฉ","aliases":["grenada"]},{"emoji":"โ•","aliases":["grey_exclamation"]},{"emoji":"โ”","aliases":["grey_question"]},{"emoji":"๐Ÿ˜ฌ","aliases":["grimacing"]},{"emoji":"๐Ÿ˜","aliases":["grin"]},{"emoji":"๐Ÿ˜€","aliases":["grinning"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ต","aliases":["guadeloupe"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡บ","aliases":["guam"]},{"emoji":"๐Ÿ’‚","aliases":["guard"]},{"emoji":"๐Ÿ’‚โ€โ™‚๏ธ","aliases":["guardsman"]},{"emoji":"๐Ÿ’‚โ€โ™€๏ธ","aliases":["guardswoman"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡น","aliases":["guatemala"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฌ","aliases":["guernsey"]},{"emoji":"๐Ÿฆฎ","aliases":["guide_dog"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ณ","aliases":["guinea"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ผ","aliases":["guinea_bissau"]},{"emoji":"๐ŸŽธ","aliases":["guitar"]},{"emoji":"๐Ÿ”ซ","aliases":["gun"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡พ","aliases":["guyana"]},{"emoji":"๐Ÿ’‡","aliases":["haircut"]},{"emoji":"๐Ÿ’‡โ€โ™‚๏ธ","aliases":["haircut_man"]},{"emoji":"๐Ÿ’‡โ€โ™€๏ธ","aliases":["haircut_woman"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡น","aliases":["haiti"]},{"emoji":"๐Ÿ”","aliases":["hamburger"]},{"emoji":"๐Ÿ”จ","aliases":["hammer"]},{"emoji":"โš’๏ธ","aliases":["hammer_and_pick"]},{"emoji":"๐Ÿ› ๏ธ","aliases":["hammer_and_wrench"]},{"emoji":"๐Ÿน","aliases":["hamster"]},{"emoji":"โœ‹","aliases":["hand","raised_hand"]},{"emoji":"๐Ÿคญ","aliases":["hand_over_mouth"]},{"emoji":"๐Ÿ‘œ","aliases":["handbag"]},{"emoji":"๐Ÿคพ","aliases":["handball_person"]},{"emoji":"๐Ÿค","aliases":["handshake"]},{"emoji":"๐Ÿ’ฉ","aliases":["hankey","poop","shit"]},{"emoji":"๐Ÿฅ","aliases":["hatched_chick"]},{"emoji":"๐Ÿฃ","aliases":["hatching_chick"]},{"emoji":"๐ŸŽง","aliases":["headphones"]},{"emoji":"๐Ÿง‘โ€โš•๏ธ","aliases":["health_worker"]},{"emoji":"๐Ÿ™‰","aliases":["hear_no_evil"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡ฒ","aliases":["heard_mcdonald_islands"]},{"emoji":"โค๏ธ","aliases":["heart"]},{"emoji":"๐Ÿ’Ÿ","aliases":["heart_decoration"]},{"emoji":"๐Ÿ˜","aliases":["heart_eyes"]},{"emoji":"๐Ÿ˜ป","aliases":["heart_eyes_cat"]},{"emoji":"๐Ÿ’“","aliases":["heartbeat"]},{"emoji":"๐Ÿ’—","aliases":["heartpulse"]},{"emoji":"โ™ฅ๏ธ","aliases":["hearts"]},{"emoji":"โœ”๏ธ","aliases":["heavy_check_mark"]},{"emoji":"โž—","aliases":["heavy_division_sign"]},{"emoji":"๐Ÿ’ฒ","aliases":["heavy_dollar_sign"]},{"emoji":"โฃ๏ธ","aliases":["heavy_heart_exclamation"]},{"emoji":"โž–","aliases":["heavy_minus_sign"]},{"emoji":"โœ–๏ธ","aliases":["heavy_multiplication_x"]},{"emoji":"โž•","aliases":["heavy_plus_sign"]},{"emoji":"๐Ÿฆ”","aliases":["hedgehog"]},{"emoji":"๐Ÿš","aliases":["helicopter"]},{"emoji":"๐ŸŒฟ","aliases":["herb"]},{"emoji":"๐ŸŒบ","aliases":["hibiscus"]},{"emoji":"๐Ÿ”†","aliases":["high_brightness"]},{"emoji":"๐Ÿ‘ ","aliases":["high_heel"]},{"emoji":"๐Ÿฅพ","aliases":["hiking_boot"]},{"emoji":"๐Ÿ›•","aliases":["hindu_temple"]},{"emoji":"๐Ÿฆ›","aliases":["hippopotamus"]},{"emoji":"๐Ÿ”ช","aliases":["hocho","knife"]},{"emoji":"๐Ÿ•ณ๏ธ","aliases":["hole"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡ณ","aliases":["honduras"]},{"emoji":"๐Ÿฏ","aliases":["honey_pot"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡ฐ","aliases":["hong_kong"]},{"emoji":"๐Ÿด","aliases":["horse"]},{"emoji":"๐Ÿ‡","aliases":["horse_racing"]},{"emoji":"๐Ÿฅ","aliases":["hospital"]},{"emoji":"๐Ÿฅต","aliases":["hot_face"]},{"emoji":"๐ŸŒถ๏ธ","aliases":["hot_pepper"]},{"emoji":"๐ŸŒญ","aliases":["hotdog"]},{"emoji":"๐Ÿจ","aliases":["hotel"]},{"emoji":"โ™จ๏ธ","aliases":["hotsprings"]},{"emoji":"โŒ›","aliases":["hourglass"]},{"emoji":"โณ","aliases":["hourglass_flowing_sand"]},{"emoji":"๐Ÿ ","aliases":["house"]},{"emoji":"๐Ÿก","aliases":["house_with_garden"]},{"emoji":"๐Ÿ˜๏ธ","aliases":["houses"]},{"emoji":"๐Ÿค—","aliases":["hugs"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡บ","aliases":["hungary"]},{"emoji":"๐Ÿ˜ฏ","aliases":["hushed"]},{"emoji":"๐Ÿจ","aliases":["ice_cream"]},{"emoji":"๐ŸงŠ","aliases":["ice_cube"]},{"emoji":"๐Ÿ’","aliases":["ice_hockey"]},{"emoji":"โ›ธ๏ธ","aliases":["ice_skate"]},{"emoji":"๐Ÿฆ","aliases":["icecream"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ธ","aliases":["iceland"]},{"emoji":"๐Ÿ†”","aliases":["id"]},{"emoji":"๐Ÿ‰","aliases":["ideograph_advantage"]},{"emoji":"๐Ÿ‘ฟ","aliases":["imp"]},{"emoji":"๐Ÿ“ฅ","aliases":["inbox_tray"]},{"emoji":"๐Ÿ“จ","aliases":["incoming_envelope"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ณ","aliases":["india"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ฉ","aliases":["indonesia"]},{"emoji":"โ™พ๏ธ","aliases":["infinity"]},{"emoji":"โ„น๏ธ","aliases":["information_source"]},{"emoji":"๐Ÿ˜‡","aliases":["innocent"]},{"emoji":"โ‰๏ธ","aliases":["interrobang"]},{"emoji":"๐Ÿ“ฑ","aliases":["iphone"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ท","aliases":["iran"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ถ","aliases":["iraq"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ช","aliases":["ireland"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ฒ","aliases":["isle_of_man"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ฑ","aliases":["israel"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡น","aliases":["it"]},{"emoji":"๐Ÿฎ","aliases":["izakaya_lantern","lantern"]},{"emoji":"๐ŸŽƒ","aliases":["jack_o_lantern"]},{"emoji":"๐Ÿ‡ฏ๐Ÿ‡ฒ","aliases":["jamaica"]},{"emoji":"๐Ÿ—พ","aliases":["japan"]},{"emoji":"๐Ÿฏ","aliases":["japanese_castle"]},{"emoji":"๐Ÿ‘บ","aliases":["japanese_goblin"]},{"emoji":"๐Ÿ‘น","aliases":["japanese_ogre"]},{"emoji":"๐Ÿ‘–","aliases":["jeans"]},{"emoji":"๐Ÿ‡ฏ๐Ÿ‡ช","aliases":["jersey"]},{"emoji":"๐Ÿงฉ","aliases":["jigsaw"]},{"emoji":"๐Ÿ‡ฏ๐Ÿ‡ด","aliases":["jordan"]},{"emoji":"๐Ÿ˜‚","aliases":["joy"]},{"emoji":"๐Ÿ˜น","aliases":["joy_cat"]},{"emoji":"๐Ÿ•น๏ธ","aliases":["joystick"]},{"emoji":"๐Ÿ‡ฏ๐Ÿ‡ต","aliases":["jp"]},{"emoji":"๐Ÿง‘โ€โš–๏ธ","aliases":["judge"]},{"emoji":"๐Ÿคน","aliases":["juggling_person"]},{"emoji":"๐Ÿ•‹","aliases":["kaaba"]},{"emoji":"๐Ÿฆ˜","aliases":["kangaroo"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ฟ","aliases":["kazakhstan"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ช","aliases":["kenya"]},{"emoji":"๐Ÿ”‘","aliases":["key"]},{"emoji":"โŒจ๏ธ","aliases":["keyboard"]},{"emoji":"๐Ÿ›ด","aliases":["kick_scooter"]},{"emoji":"๐Ÿ‘˜","aliases":["kimono"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ฎ","aliases":["kiribati"]},{"emoji":"๐Ÿ’‹","aliases":["kiss"]},{"emoji":"๐Ÿ˜—","aliases":["kissing"]},{"emoji":"๐Ÿ˜ฝ","aliases":["kissing_cat"]},{"emoji":"๐Ÿ˜š","aliases":["kissing_closed_eyes"]},{"emoji":"๐Ÿ˜˜","aliases":["kissing_heart"]},{"emoji":"๐Ÿ˜™","aliases":["kissing_smiling_eyes"]},{"emoji":"๐Ÿช","aliases":["kite"]},{"emoji":"๐Ÿฅ","aliases":["kiwi_fruit"]},{"emoji":"๐ŸงŽโ€โ™‚๏ธ","aliases":["kneeling_man"]},{"emoji":"๐ŸงŽ","aliases":["kneeling_person"]},{"emoji":"๐ŸงŽโ€โ™€๏ธ","aliases":["kneeling_woman"]},{"emoji":"๐Ÿจ","aliases":["koala"]},{"emoji":"๐Ÿˆ","aliases":["koko"]},{"emoji":"๐Ÿ‡ฝ๐Ÿ‡ฐ","aliases":["kosovo"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ท","aliases":["kr"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ผ","aliases":["kuwait"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ฌ","aliases":["kyrgyzstan"]},{"emoji":"๐Ÿฅผ","aliases":["lab_coat"]},{"emoji":"๐Ÿท๏ธ","aliases":["label"]},{"emoji":"๐Ÿฅ","aliases":["lacrosse"]},{"emoji":"๐Ÿž","aliases":["lady_beetle"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ฆ","aliases":["laos"]},{"emoji":"๐Ÿ”ต","aliases":["large_blue_circle"]},{"emoji":"๐Ÿ”ท","aliases":["large_blue_diamond"]},{"emoji":"๐Ÿ”ถ","aliases":["large_orange_diamond"]},{"emoji":"๐ŸŒ—","aliases":["last_quarter_moon"]},{"emoji":"๐ŸŒœ","aliases":["last_quarter_moon_with_face"]},{"emoji":"โœ๏ธ","aliases":["latin_cross"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ป","aliases":["latvia"]},{"emoji":"๐Ÿ˜†","aliases":["laughing","satisfied","laugh"]},{"emoji":"๐Ÿฅฌ","aliases":["leafy_green"]},{"emoji":"๐Ÿƒ","aliases":["leaves"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ง","aliases":["lebanon"]},{"emoji":"๐Ÿ“’","aliases":["ledger"]},{"emoji":"๐Ÿ›…","aliases":["left_luggage"]},{"emoji":"โ†”๏ธ","aliases":["left_right_arrow"]},{"emoji":"๐Ÿ—จ๏ธ","aliases":["left_speech_bubble"]},{"emoji":"โ†ฉ๏ธ","aliases":["leftwards_arrow_with_hook"]},{"emoji":"๐Ÿฆต","aliases":["leg"]},{"emoji":"๐Ÿ‹","aliases":["lemon"]},{"emoji":"โ™Œ","aliases":["leo"]},{"emoji":"๐Ÿ†","aliases":["leopard"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ธ","aliases":["lesotho"]},{"emoji":"๐ŸŽš๏ธ","aliases":["level_slider"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ท","aliases":["liberia"]},{"emoji":"โ™Ž","aliases":["libra"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡พ","aliases":["libya"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ฎ","aliases":["liechtenstein"]},{"emoji":"๐Ÿšˆ","aliases":["light_rail"]},{"emoji":"๐Ÿ”—","aliases":["link"]},{"emoji":"๐Ÿฆ","aliases":["lion"]},{"emoji":"๐Ÿ‘„","aliases":["lips"]},{"emoji":"๐Ÿ’„","aliases":["lipstick"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡น","aliases":["lithuania"]},{"emoji":"๐ŸฆŽ","aliases":["lizard"]},{"emoji":"๐Ÿฆ™","aliases":["llama"]},{"emoji":"๐Ÿฆž","aliases":["lobster"]},{"emoji":"๐Ÿ”’","aliases":["lock"]},{"emoji":"๐Ÿ”","aliases":["lock_with_ink_pen"]},{"emoji":"๐Ÿญ","aliases":["lollipop"]},{"emoji":"โžฟ","aliases":["loop"]},{"emoji":"๐Ÿงด","aliases":["lotion_bottle"]},{"emoji":"๐Ÿง˜","aliases":["lotus_position"]},{"emoji":"๐Ÿง˜โ€โ™‚๏ธ","aliases":["lotus_position_man"]},{"emoji":"๐Ÿง˜โ€โ™€๏ธ","aliases":["lotus_position_woman"]},{"emoji":"๐Ÿ”Š","aliases":["loud_sound"]},{"emoji":"๐Ÿ“ข","aliases":["loudspeaker"]},{"emoji":"๐Ÿฉ","aliases":["love_hotel"]},{"emoji":"๐Ÿ’Œ","aliases":["love_letter"]},{"emoji":"๐ŸคŸ","aliases":["love_you_gesture"]},{"emoji":"๐Ÿ”…","aliases":["low_brightness"]},{"emoji":"๐Ÿงณ","aliases":["luggage"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡บ","aliases":["luxembourg"]},{"emoji":"๐Ÿคฅ","aliases":["lying_face"]},{"emoji":"โ“‚๏ธ","aliases":["m"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ด","aliases":["macau"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฐ","aliases":["macedonia"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฌ","aliases":["madagascar"]},{"emoji":"๐Ÿ”","aliases":["mag"]},{"emoji":"๐Ÿ”Ž","aliases":["mag_right"]},{"emoji":"๐Ÿง™","aliases":["mage"]},{"emoji":"๐Ÿง™โ€โ™‚๏ธ","aliases":["mage_man"]},{"emoji":"๐Ÿง™โ€โ™€๏ธ","aliases":["mage_woman"]},{"emoji":"๐Ÿงฒ","aliases":["magnet"]},{"emoji":"๐Ÿ€„","aliases":["mahjong"]},{"emoji":"๐Ÿ“ซ","aliases":["mailbox"]},{"emoji":"๐Ÿ“ช","aliases":["mailbox_closed"]},{"emoji":"๐Ÿ“ฌ","aliases":["mailbox_with_mail"]},{"emoji":"๐Ÿ“ญ","aliases":["mailbox_with_no_mail"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ผ","aliases":["malawi"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡พ","aliases":["malaysia"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ป","aliases":["maldives"]},{"emoji":"๐Ÿ•ต๏ธโ€โ™‚๏ธ","aliases":["male_detective"]},{"emoji":"โ™‚๏ธ","aliases":["male_sign"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฑ","aliases":["mali"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡น","aliases":["malta"]},{"emoji":"๐Ÿ‘จ","aliases":["man"]},{"emoji":"๐Ÿ‘จโ€๐ŸŽจ","aliases":["man_artist"]},{"emoji":"๐Ÿ‘จโ€๐Ÿš€","aliases":["man_astronaut"]},{"emoji":"๐Ÿคธโ€โ™‚๏ธ","aliases":["man_cartwheeling"]},{"emoji":"๐Ÿ‘จโ€๐Ÿณ","aliases":["man_cook"]},{"emoji":"๐Ÿ•บ","aliases":["man_dancing"]},{"emoji":"๐Ÿคฆโ€โ™‚๏ธ","aliases":["man_facepalming"]},{"emoji":"๐Ÿ‘จโ€๐Ÿญ","aliases":["man_factory_worker"]},{"emoji":"๐Ÿ‘จโ€๐ŸŒพ","aliases":["man_farmer"]},{"emoji":"๐Ÿ‘จโ€๐Ÿš’","aliases":["man_firefighter"]},{"emoji":"๐Ÿ‘จโ€โš•๏ธ","aliases":["man_health_worker"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆฝ","aliases":["man_in_manual_wheelchair"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆผ","aliases":["man_in_motorized_wheelchair"]},{"emoji":"๐Ÿ‘จโ€โš–๏ธ","aliases":["man_judge"]},{"emoji":"๐Ÿคนโ€โ™‚๏ธ","aliases":["man_juggling"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ”ง","aliases":["man_mechanic"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ’ผ","aliases":["man_office_worker"]},{"emoji":"๐Ÿ‘จโ€โœˆ๏ธ","aliases":["man_pilot"]},{"emoji":"๐Ÿคพโ€โ™‚๏ธ","aliases":["man_playing_handball"]},{"emoji":"๐Ÿคฝโ€โ™‚๏ธ","aliases":["man_playing_water_polo"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ”ฌ","aliases":["man_scientist"]},{"emoji":"๐Ÿคทโ€โ™‚๏ธ","aliases":["man_shrugging"]},{"emoji":"๐Ÿ‘จโ€๐ŸŽค","aliases":["man_singer"]},{"emoji":"๐Ÿ‘จโ€๐ŸŽ“","aliases":["man_student"]},{"emoji":"๐Ÿ‘จโ€๐Ÿซ","aliases":["man_teacher"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ’ป","aliases":["man_technologist"]},{"emoji":"๐Ÿ‘ฒ","aliases":["man_with_gua_pi_mao"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆฏ","aliases":["man_with_probing_cane"]},{"emoji":"๐Ÿ‘ณโ€โ™‚๏ธ","aliases":["man_with_turban"]},{"emoji":"๐Ÿฅญ","aliases":["mango"]},{"emoji":"๐Ÿ‘ž","aliases":["mans_shoe","shoe"]},{"emoji":"๐Ÿ•ฐ๏ธ","aliases":["mantelpiece_clock"]},{"emoji":"๐Ÿฆฝ","aliases":["manual_wheelchair"]},{"emoji":"๐Ÿ","aliases":["maple_leaf"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ญ","aliases":["marshall_islands"]},{"emoji":"๐Ÿฅ‹","aliases":["martial_arts_uniform"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ถ","aliases":["martinique"]},{"emoji":"๐Ÿ˜ท","aliases":["mask"]},{"emoji":"๐Ÿ’†","aliases":["massage"]},{"emoji":"๐Ÿ’†โ€โ™‚๏ธ","aliases":["massage_man"]},{"emoji":"๐Ÿ’†โ€โ™€๏ธ","aliases":["massage_woman"]},{"emoji":"๐Ÿง‰","aliases":["mate"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ท","aliases":["mauritania"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡บ","aliases":["mauritius"]},{"emoji":"๐Ÿ‡พ๐Ÿ‡น","aliases":["mayotte"]},{"emoji":"๐Ÿ–","aliases":["meat_on_bone"]},{"emoji":"๐Ÿง‘โ€๐Ÿ”ง","aliases":["mechanic"]},{"emoji":"๐Ÿฆพ","aliases":["mechanical_arm"]},{"emoji":"๐Ÿฆฟ","aliases":["mechanical_leg"]},{"emoji":"๐ŸŽ–๏ธ","aliases":["medal_military"]},{"emoji":"๐Ÿ…","aliases":["medal_sports"]},{"emoji":"โš•๏ธ","aliases":["medical_symbol"]},{"emoji":"๐Ÿ“ฃ","aliases":["mega"]},{"emoji":"๐Ÿˆ","aliases":["melon"]},{"emoji":"๐Ÿ“","aliases":["memo","pencil"]},{"emoji":"๐Ÿคผโ€โ™‚๏ธ","aliases":["men_wrestling"]},{"emoji":"๐Ÿ•Ž","aliases":["menorah"]},{"emoji":"๐Ÿšน","aliases":["mens"]},{"emoji":"๐Ÿงœโ€โ™€๏ธ","aliases":["mermaid"]},{"emoji":"๐Ÿงœโ€โ™‚๏ธ","aliases":["merman"]},{"emoji":"๐Ÿงœ","aliases":["merperson"]},{"emoji":"๐Ÿค˜","aliases":["metal"]},{"emoji":"๐Ÿš‡","aliases":["metro"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฝ","aliases":["mexico"]},{"emoji":"๐Ÿฆ ","aliases":["microbe"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ฒ","aliases":["micronesia"]},{"emoji":"๐ŸŽค","aliases":["microphone"]},{"emoji":"๐Ÿ”ฌ","aliases":["microscope"]},{"emoji":"๐Ÿ–•","aliases":["middle_finger","fu"]},{"emoji":"๐Ÿฅ›","aliases":["milk_glass"]},{"emoji":"๐ŸŒŒ","aliases":["milky_way"]},{"emoji":"๐Ÿš","aliases":["minibus"]},{"emoji":"๐Ÿ’ฝ","aliases":["minidisc"]},{"emoji":"๐Ÿ“ด","aliases":["mobile_phone_off"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฉ","aliases":["moldova"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡จ","aliases":["monaco"]},{"emoji":"๐Ÿค‘","aliases":["money_mouth_face"]},{"emoji":"๐Ÿ’ธ","aliases":["money_with_wings"]},{"emoji":"๐Ÿ’ฐ","aliases":["moneybag"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ณ","aliases":["mongolia"]},{"emoji":"๐Ÿ’","aliases":["monkey"]},{"emoji":"๐Ÿต","aliases":["monkey_face"]},{"emoji":"๐Ÿง","aliases":["monocle_face"]},{"emoji":"๐Ÿš","aliases":["monorail"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ช","aliases":["montenegro"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ธ","aliases":["montserrat"]},{"emoji":"๐ŸŒ”","aliases":["moon","waxing_gibbous_moon"]},{"emoji":"๐Ÿฅฎ","aliases":["moon_cake"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฆ","aliases":["morocco"]},{"emoji":"๐ŸŽ“","aliases":["mortar_board"]},{"emoji":"๐Ÿ•Œ","aliases":["mosque"]},{"emoji":"๐ŸฆŸ","aliases":["mosquito"]},{"emoji":"๐Ÿ›ฅ๏ธ","aliases":["motor_boat"]},{"emoji":"๐Ÿ›ต","aliases":["motor_scooter"]},{"emoji":"๐Ÿ๏ธ","aliases":["motorcycle"]},{"emoji":"๐Ÿฆผ","aliases":["motorized_wheelchair"]},{"emoji":"๐Ÿ›ฃ๏ธ","aliases":["motorway"]},{"emoji":"๐Ÿ—ป","aliases":["mount_fuji"]},{"emoji":"โ›ฐ๏ธ","aliases":["mountain"]},{"emoji":"๐Ÿšต","aliases":["mountain_bicyclist"]},{"emoji":"๐Ÿšตโ€โ™‚๏ธ","aliases":["mountain_biking_man"]},{"emoji":"๐Ÿšตโ€โ™€๏ธ","aliases":["mountain_biking_woman"]},{"emoji":"๐Ÿš ","aliases":["mountain_cableway"]},{"emoji":"๐Ÿšž","aliases":["mountain_railway"]},{"emoji":"๐Ÿ”๏ธ","aliases":["mountain_snow"]},{"emoji":"๐Ÿญ","aliases":["mouse"]},{"emoji":"๐Ÿ","aliases":["mouse2"]},{"emoji":"๐ŸŽฅ","aliases":["movie_camera"]},{"emoji":"๐Ÿ—ฟ","aliases":["moyai"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฟ","aliases":["mozambique"]},{"emoji":"๐Ÿคถ","aliases":["mrs_claus"]},{"emoji":"๐Ÿ’ช","aliases":["muscle"]},{"emoji":"๐Ÿ„","aliases":["mushroom"]},{"emoji":"๐ŸŽน","aliases":["musical_keyboard"]},{"emoji":"๐ŸŽต","aliases":["musical_note"]},{"emoji":"๐ŸŽผ","aliases":["musical_score"]},{"emoji":"๐Ÿ”‡","aliases":["mute"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฒ","aliases":["myanmar"]},{"emoji":"๐Ÿ’…","aliases":["nail_care"]},{"emoji":"๐Ÿ“›","aliases":["name_badge"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ฆ","aliases":["namibia"]},{"emoji":"๐Ÿž๏ธ","aliases":["national_park"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ท","aliases":["nauru"]},{"emoji":"๐Ÿคข","aliases":["nauseated_face"]},{"emoji":"๐Ÿงฟ","aliases":["nazar_amulet"]},{"emoji":"๐Ÿ‘”","aliases":["necktie"]},{"emoji":"โŽ","aliases":["negative_squared_cross_mark"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ต","aliases":["nepal"]},{"emoji":"๐Ÿค“","aliases":["nerd_face"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ฑ","aliases":["netherlands"]},{"emoji":"๐Ÿ˜","aliases":["neutral_face"]},{"emoji":"๐Ÿ†•","aliases":["new"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡จ","aliases":["new_caledonia"]},{"emoji":"๐ŸŒ‘","aliases":["new_moon"]},{"emoji":"๐ŸŒš","aliases":["new_moon_with_face"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ฟ","aliases":["new_zealand"]},{"emoji":"๐Ÿ“ฐ","aliases":["newspaper"]},{"emoji":"๐Ÿ—ž๏ธ","aliases":["newspaper_roll"]},{"emoji":"โญ๏ธ","aliases":["next_track_button"]},{"emoji":"๐Ÿ†–","aliases":["ng"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ฎ","aliases":["nicaragua"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ช","aliases":["niger"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ฌ","aliases":["nigeria"]},{"emoji":"๐ŸŒƒ","aliases":["night_with_stars"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡บ","aliases":["niue"]},{"emoji":"๐Ÿ”•","aliases":["no_bell"]},{"emoji":"๐Ÿšณ","aliases":["no_bicycles"]},{"emoji":"โ›”","aliases":["no_entry"]},{"emoji":"๐Ÿšซ","aliases":["no_entry_sign"]},{"emoji":"๐Ÿ™…","aliases":["no_good"]},{"emoji":"๐Ÿ™…โ€โ™‚๏ธ","aliases":["no_good_man","ng_man"]},{"emoji":"๐Ÿ™…โ€โ™€๏ธ","aliases":["no_good_woman","ng_woman"]},{"emoji":"๐Ÿ“ต","aliases":["no_mobile_phones"]},{"emoji":"๐Ÿ˜ถ","aliases":["no_mouth"]},{"emoji":"๐Ÿšท","aliases":["no_pedestrians"]},{"emoji":"๐Ÿšญ","aliases":["no_smoking"]},{"emoji":"๐Ÿšฑ","aliases":["non-potable_water"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ซ","aliases":["norfolk_island"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ต","aliases":["north_korea"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ต","aliases":["northern_mariana_islands"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ด","aliases":["norway"]},{"emoji":"๐Ÿ‘ƒ","aliases":["nose"]},{"emoji":"๐Ÿ““","aliases":["notebook"]},{"emoji":"๐Ÿ“”","aliases":["notebook_with_decorative_cover"]},{"emoji":"๐ŸŽถ","aliases":["notes"]},{"emoji":"๐Ÿ”ฉ","aliases":["nut_and_bolt"]},{"emoji":"โญ•","aliases":["o"]},{"emoji":"๐Ÿ…พ๏ธ","aliases":["o2"]},{"emoji":"๐ŸŒŠ","aliases":["ocean"]},{"emoji":"๐Ÿ™","aliases":["octopus"]},{"emoji":"๐Ÿข","aliases":["oden"]},{"emoji":"๐Ÿข","aliases":["office"]},{"emoji":"๐Ÿง‘โ€๐Ÿ’ผ","aliases":["office_worker"]},{"emoji":"๐Ÿ›ข๏ธ","aliases":["oil_drum"]},{"emoji":"๐Ÿ†—","aliases":["ok"]},{"emoji":"๐Ÿ‘Œ","aliases":["ok_hand"]},{"emoji":"๐Ÿ™†โ€โ™‚๏ธ","aliases":["ok_man"]},{"emoji":"๐Ÿ™†","aliases":["ok_person"]},{"emoji":"๐Ÿ™†โ€โ™€๏ธ","aliases":["ok_woman"]},{"emoji":"๐Ÿ—๏ธ","aliases":["old_key"]},{"emoji":"๐Ÿง“","aliases":["older_adult"]},{"emoji":"๐Ÿ‘ด","aliases":["older_man"]},{"emoji":"๐Ÿ‘ต","aliases":["older_woman"]},{"emoji":"๐Ÿ•‰๏ธ","aliases":["om"]},{"emoji":"๐Ÿ‡ด๐Ÿ‡ฒ","aliases":["oman"]},{"emoji":"๐Ÿ”›","aliases":["on"]},{"emoji":"๐Ÿš˜","aliases":["oncoming_automobile"]},{"emoji":"๐Ÿš","aliases":["oncoming_bus"]},{"emoji":"๐Ÿš”","aliases":["oncoming_police_car"]},{"emoji":"๐Ÿš–","aliases":["oncoming_taxi"]},{"emoji":"๐Ÿฉฑ","aliases":["one_piece_swimsuit"]},{"emoji":"๐Ÿง…","aliases":["onion"]},{"emoji":"๐Ÿ“‚","aliases":["open_file_folder"]},{"emoji":"๐Ÿ‘","aliases":["open_hands"]},{"emoji":"๐Ÿ˜ฎ","aliases":["open_mouth"]},{"emoji":"โ˜‚๏ธ","aliases":["open_umbrella"]},{"emoji":"โ›Ž","aliases":["ophiuchus"]},{"emoji":"๐Ÿ“™","aliases":["orange_book"]},{"emoji":"๐ŸŸ ","aliases":["orange_circle"]},{"emoji":"๐Ÿงก","aliases":["orange_heart"]},{"emoji":"๐ŸŸง","aliases":["orange_square"]},{"emoji":"๐Ÿฆง","aliases":["orangutan"]},{"emoji":"โ˜ฆ๏ธ","aliases":["orthodox_cross"]},{"emoji":"๐Ÿฆฆ","aliases":["otter"]},{"emoji":"๐Ÿ“ค","aliases":["outbox_tray"]},{"emoji":"๐Ÿฆ‰","aliases":["owl"]},{"emoji":"๐Ÿ‚","aliases":["ox"]},{"emoji":"๐Ÿฆช","aliases":["oyster"]},{"emoji":"๐Ÿ“ฆ","aliases":["package"]},{"emoji":"๐Ÿ“„","aliases":["page_facing_up"]},{"emoji":"๐Ÿ“ƒ","aliases":["page_with_curl"]},{"emoji":"๐Ÿ“Ÿ","aliases":["pager"]},{"emoji":"๐Ÿ–Œ๏ธ","aliases":["paintbrush"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ฐ","aliases":["pakistan"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ผ","aliases":["palau"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ธ","aliases":["palestinian_territories"]},{"emoji":"๐ŸŒด","aliases":["palm_tree"]},{"emoji":"๐Ÿคฒ","aliases":["palms_up_together"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ฆ","aliases":["panama"]},{"emoji":"๐Ÿฅž","aliases":["pancakes"]},{"emoji":"๐Ÿผ","aliases":["panda_face"]},{"emoji":"๐Ÿ“Ž","aliases":["paperclip"]},{"emoji":"๐Ÿ–‡๏ธ","aliases":["paperclips"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ฌ","aliases":["papua_new_guinea"]},{"emoji":"๐Ÿช‚","aliases":["parachute"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡พ","aliases":["paraguay"]},{"emoji":"โ›ฑ๏ธ","aliases":["parasol_on_ground"]},{"emoji":"๐Ÿ…ฟ๏ธ","aliases":["parking"]},{"emoji":"๐Ÿฆœ","aliases":["parrot"]},{"emoji":"ใ€ฝ๏ธ","aliases":["part_alternation_mark"]},{"emoji":"โ›…","aliases":["partly_sunny"]},{"emoji":"๐Ÿฅณ","aliases":["partying_face"]},{"emoji":"๐Ÿ›ณ๏ธ","aliases":["passenger_ship"]},{"emoji":"๐Ÿ›‚","aliases":["passport_control"]},{"emoji":"โธ๏ธ","aliases":["pause_button"]},{"emoji":"โ˜ฎ๏ธ","aliases":["peace_symbol"]},{"emoji":"๐Ÿ‘","aliases":["peach"]},{"emoji":"๐Ÿฆš","aliases":["peacock"]},{"emoji":"๐Ÿฅœ","aliases":["peanuts"]},{"emoji":"๐Ÿ","aliases":["pear"]},{"emoji":"๐Ÿ–Š๏ธ","aliases":["pen"]},{"emoji":"โœ๏ธ","aliases":["pencil2"]},{"emoji":"๐Ÿง","aliases":["penguin"]},{"emoji":"๐Ÿ˜”","aliases":["pensive"]},{"emoji":"๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘","aliases":["people_holding_hands"]},{"emoji":"๐ŸŽญ","aliases":["performing_arts"]},{"emoji":"๐Ÿ˜ฃ","aliases":["persevere"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆฒ","aliases":["person_bald"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆฑ","aliases":["person_curly_hair"]},{"emoji":"๐Ÿคบ","aliases":["person_fencing"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆฝ","aliases":["person_in_manual_wheelchair"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆผ","aliases":["person_in_motorized_wheelchair"]},{"emoji":"๐Ÿคต","aliases":["person_in_tuxedo"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆฐ","aliases":["person_red_hair"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆณ","aliases":["person_white_hair"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆฏ","aliases":["person_with_probing_cane"]},{"emoji":"๐Ÿ‘ณ","aliases":["person_with_turban"]},{"emoji":"๐Ÿ‘ฐ","aliases":["person_with_veil"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ช","aliases":["peru"]},{"emoji":"๐Ÿงซ","aliases":["petri_dish"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ญ","aliases":["philippines"]},{"emoji":"โ˜Ž๏ธ","aliases":["phone","telephone"]},{"emoji":"โ›๏ธ","aliases":["pick"]},{"emoji":"๐Ÿฅง","aliases":["pie"]},{"emoji":"๐Ÿท","aliases":["pig"]},{"emoji":"๐Ÿ–","aliases":["pig2"]},{"emoji":"๐Ÿฝ","aliases":["pig_nose"]},{"emoji":"๐Ÿ’Š","aliases":["pill"]},{"emoji":"๐Ÿง‘โ€โœˆ๏ธ","aliases":["pilot"]},{"emoji":"๐Ÿค","aliases":["pinching_hand"]},{"emoji":"๐Ÿ","aliases":["pineapple"]},{"emoji":"๐Ÿ“","aliases":["ping_pong"]},{"emoji":"๐Ÿดโ€โ˜ ๏ธ","aliases":["pirate_flag"]},{"emoji":"โ™“","aliases":["pisces"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ณ","aliases":["pitcairn_islands"]},{"emoji":"๐Ÿ•","aliases":["pizza"]},{"emoji":"๐Ÿ›","aliases":["place_of_worship"]},{"emoji":"๐Ÿฝ๏ธ","aliases":["plate_with_cutlery"]},{"emoji":"โฏ๏ธ","aliases":["play_or_pause_button"]},{"emoji":"๐Ÿฅบ","aliases":["pleading_face"]},{"emoji":"๐Ÿ‘‡","aliases":["point_down"]},{"emoji":"๐Ÿ‘ˆ","aliases":["point_left"]},{"emoji":"๐Ÿ‘‰","aliases":["point_right"]},{"emoji":"โ˜๏ธ","aliases":["point_up"]},{"emoji":"๐Ÿ‘†","aliases":["point_up_2"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ฑ","aliases":["poland"]},{"emoji":"๐Ÿš“","aliases":["police_car"]},{"emoji":"๐Ÿ‘ฎ","aliases":["police_officer","cop"]},{"emoji":"๐Ÿ‘ฎโ€โ™‚๏ธ","aliases":["policeman"]},{"emoji":"๐Ÿ‘ฎโ€โ™€๏ธ","aliases":["policewoman"]},{"emoji":"๐Ÿฉ","aliases":["poodle"]},{"emoji":"๐Ÿฟ","aliases":["popcorn"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡น","aliases":["portugal"]},{"emoji":"๐Ÿฃ","aliases":["post_office"]},{"emoji":"๐Ÿ“ฏ","aliases":["postal_horn"]},{"emoji":"๐Ÿ“ฎ","aliases":["postbox"]},{"emoji":"๐Ÿšฐ","aliases":["potable_water"]},{"emoji":"๐Ÿฅ”","aliases":["potato"]},{"emoji":"๐Ÿ‘","aliases":["pouch"]},{"emoji":"๐Ÿ—","aliases":["poultry_leg"]},{"emoji":"๐Ÿ’ท","aliases":["pound"]},{"emoji":"๐Ÿ˜พ","aliases":["pouting_cat"]},{"emoji":"๐Ÿ™Ž","aliases":["pouting_face"]},{"emoji":"๐Ÿ™Žโ€โ™‚๏ธ","aliases":["pouting_man"]},{"emoji":"๐Ÿ™Žโ€โ™€๏ธ","aliases":["pouting_woman"]},{"emoji":"๐Ÿ™","aliases":["pray"]},{"emoji":"๐Ÿ“ฟ","aliases":["prayer_beads"]},{"emoji":"๐Ÿคฐ","aliases":["pregnant_woman"]},{"emoji":"๐Ÿฅจ","aliases":["pretzel"]},{"emoji":"โฎ๏ธ","aliases":["previous_track_button"]},{"emoji":"๐Ÿคด","aliases":["prince"]},{"emoji":"๐Ÿ‘ธ","aliases":["princess"]},{"emoji":"๐Ÿ–จ๏ธ","aliases":["printer"]},{"emoji":"๐Ÿฆฏ","aliases":["probing_cane"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ท","aliases":["puerto_rico"]},{"emoji":"๐ŸŸฃ","aliases":["purple_circle"]},{"emoji":"๐Ÿ’œ","aliases":["purple_heart"]},{"emoji":"๐ŸŸช","aliases":["purple_square"]},{"emoji":"๐Ÿ‘›","aliases":["purse"]},{"emoji":"๐Ÿ“Œ","aliases":["pushpin"]},{"emoji":"๐Ÿšฎ","aliases":["put_litter_in_its_place"]},{"emoji":"๐Ÿ‡ถ๐Ÿ‡ฆ","aliases":["qatar"]},{"emoji":"โ“","aliases":["question"]},{"emoji":"๐Ÿฐ","aliases":["rabbit"]},{"emoji":"๐Ÿ‡","aliases":["rabbit2"]},{"emoji":"๐Ÿฆ","aliases":["raccoon"]},{"emoji":"๐ŸŽ","aliases":["racehorse"]},{"emoji":"๐ŸŽ๏ธ","aliases":["racing_car"]},{"emoji":"๐Ÿ“ป","aliases":["radio"]},{"emoji":"๐Ÿ”˜","aliases":["radio_button"]},{"emoji":"โ˜ข๏ธ","aliases":["radioactive"]},{"emoji":"๐Ÿ˜ก","aliases":["rage","pout"]},{"emoji":"๐Ÿšƒ","aliases":["railway_car"]},{"emoji":"๐Ÿ›ค๏ธ","aliases":["railway_track"]},{"emoji":"๐ŸŒˆ","aliases":["rainbow"]},{"emoji":"๐Ÿณ๏ธโ€๐ŸŒˆ","aliases":["rainbow_flag"]},{"emoji":"๐Ÿคš","aliases":["raised_back_of_hand"]},{"emoji":"๐Ÿคจ","aliases":["raised_eyebrow"]},{"emoji":"๐Ÿ–๏ธ","aliases":["raised_hand_with_fingers_splayed"]},{"emoji":"๐Ÿ™Œ","aliases":["raised_hands"]},{"emoji":"๐Ÿ™‹","aliases":["raising_hand"]},{"emoji":"๐Ÿ™‹โ€โ™‚๏ธ","aliases":["raising_hand_man"]},{"emoji":"๐Ÿ™‹โ€โ™€๏ธ","aliases":["raising_hand_woman"]},{"emoji":"๐Ÿ","aliases":["ram"]},{"emoji":"๐Ÿœ","aliases":["ramen"]},{"emoji":"๐Ÿ€","aliases":["rat"]},{"emoji":"๐Ÿช’","aliases":["razor"]},{"emoji":"๐Ÿงพ","aliases":["receipt"]},{"emoji":"โบ๏ธ","aliases":["record_button"]},{"emoji":"โ™ป๏ธ","aliases":["recycle"]},{"emoji":"๐Ÿ”ด","aliases":["red_circle"]},{"emoji":"๐Ÿงง","aliases":["red_envelope"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆฐ","aliases":["red_haired_man"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆฐ","aliases":["red_haired_woman"]},{"emoji":"๐ŸŸฅ","aliases":["red_square"]},{"emoji":"โ˜บ๏ธ","aliases":["relaxed"]},{"emoji":"๐Ÿ˜Œ","aliases":["relieved"]},{"emoji":"๐ŸŽ—๏ธ","aliases":["reminder_ribbon"]},{"emoji":"๐Ÿ”","aliases":["repeat"]},{"emoji":"๐Ÿ”‚","aliases":["repeat_one"]},{"emoji":"โ›‘๏ธ","aliases":["rescue_worker_helmet"]},{"emoji":"๐Ÿšป","aliases":["restroom"]},{"emoji":"๐Ÿ‡ท๐Ÿ‡ช","aliases":["reunion"]},{"emoji":"๐Ÿ’ž","aliases":["revolving_hearts"]},{"emoji":"โช","aliases":["rewind"]},{"emoji":"๐Ÿฆ","aliases":["rhinoceros"]},{"emoji":"๐ŸŽ€","aliases":["ribbon"]},{"emoji":"๐Ÿš","aliases":["rice"]},{"emoji":"๐Ÿ™","aliases":["rice_ball"]},{"emoji":"๐Ÿ˜","aliases":["rice_cracker"]},{"emoji":"๐ŸŽ‘","aliases":["rice_scene"]},{"emoji":"๐Ÿ—ฏ๏ธ","aliases":["right_anger_bubble"]},{"emoji":"๐Ÿ’","aliases":["ring"]},{"emoji":"๐Ÿช","aliases":["ringed_planet"]},{"emoji":"๐Ÿค–","aliases":["robot"]},{"emoji":"๐Ÿš€","aliases":["rocket"]},{"emoji":"๐Ÿคฃ","aliases":["rofl"]},{"emoji":"๐Ÿ™„","aliases":["roll_eyes"]},{"emoji":"๐Ÿงป","aliases":["roll_of_paper"]},{"emoji":"๐ŸŽข","aliases":["roller_coaster"]},{"emoji":"๐Ÿ‡ท๐Ÿ‡ด","aliases":["romania"]},{"emoji":"๐Ÿ“","aliases":["rooster"]},{"emoji":"๐ŸŒน","aliases":["rose"]},{"emoji":"๐Ÿต๏ธ","aliases":["rosette"]},{"emoji":"๐Ÿšจ","aliases":["rotating_light"]},{"emoji":"๐Ÿ“","aliases":["round_pushpin"]},{"emoji":"๐Ÿšฃ","aliases":["rowboat"]},{"emoji":"๐Ÿšฃโ€โ™‚๏ธ","aliases":["rowing_man"]},{"emoji":"๐Ÿšฃโ€โ™€๏ธ","aliases":["rowing_woman"]},{"emoji":"๐Ÿ‡ท๐Ÿ‡บ","aliases":["ru"]},{"emoji":"๐Ÿ‰","aliases":["rugby_football"]},{"emoji":"๐Ÿƒ","aliases":["runner","running"]},{"emoji":"๐Ÿƒโ€โ™‚๏ธ","aliases":["running_man"]},{"emoji":"๐ŸŽฝ","aliases":["running_shirt_with_sash"]},{"emoji":"๐Ÿƒโ€โ™€๏ธ","aliases":["running_woman"]},{"emoji":"๐Ÿ‡ท๐Ÿ‡ผ","aliases":["rwanda"]},{"emoji":"๐Ÿˆ‚๏ธ","aliases":["sa"]},{"emoji":"๐Ÿงท","aliases":["safety_pin"]},{"emoji":"๐Ÿฆบ","aliases":["safety_vest"]},{"emoji":"โ™","aliases":["sagittarius"]},{"emoji":"๐Ÿถ","aliases":["sake"]},{"emoji":"๐Ÿง‚","aliases":["salt"]},{"emoji":"๐Ÿ‡ผ๐Ÿ‡ธ","aliases":["samoa"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฒ","aliases":["san_marino"]},{"emoji":"๐Ÿ‘ก","aliases":["sandal"]},{"emoji":"๐Ÿฅช","aliases":["sandwich"]},{"emoji":"๐ŸŽ…","aliases":["santa"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡น","aliases":["sao_tome_principe"]},{"emoji":"๐Ÿฅป","aliases":["sari"]},{"emoji":"๐Ÿ“ก","aliases":["satellite"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฆ","aliases":["saudi_arabia"]},{"emoji":"๐Ÿง–โ€โ™‚๏ธ","aliases":["sauna_man"]},{"emoji":"๐Ÿง–","aliases":["sauna_person"]},{"emoji":"๐Ÿง–โ€โ™€๏ธ","aliases":["sauna_woman"]},{"emoji":"๐Ÿฆ•","aliases":["sauropod"]},{"emoji":"๐ŸŽท","aliases":["saxophone"]},{"emoji":"๐Ÿงฃ","aliases":["scarf"]},{"emoji":"๐Ÿซ","aliases":["school"]},{"emoji":"๐ŸŽ’","aliases":["school_satchel"]},{"emoji":"๐Ÿง‘โ€๐Ÿ”ฌ","aliases":["scientist"]},{"emoji":"โœ‚๏ธ","aliases":["scissors"]},{"emoji":"๐Ÿฆ‚","aliases":["scorpion"]},{"emoji":"โ™","aliases":["scorpius"]},{"emoji":"๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ","aliases":["scotland"]},{"emoji":"๐Ÿ˜ฑ","aliases":["scream"]},{"emoji":"๐Ÿ™€","aliases":["scream_cat"]},{"emoji":"๐Ÿ“œ","aliases":["scroll"]},{"emoji":"๐Ÿ’บ","aliases":["seat"]},{"emoji":"ใŠ™๏ธ","aliases":["secret"]},{"emoji":"๐Ÿ™ˆ","aliases":["see_no_evil"]},{"emoji":"๐ŸŒฑ","aliases":["seedling"]},{"emoji":"๐Ÿคณ","aliases":["selfie"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ณ","aliases":["senegal"]},{"emoji":"๐Ÿ‡ท๐Ÿ‡ธ","aliases":["serbia"]},{"emoji":"๐Ÿ•โ€๐Ÿฆบ","aliases":["service_dog"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡จ","aliases":["seychelles"]},{"emoji":"๐Ÿฅ˜","aliases":["shallow_pan_of_food"]},{"emoji":"โ˜˜๏ธ","aliases":["shamrock"]},{"emoji":"๐Ÿฆˆ","aliases":["shark"]},{"emoji":"๐Ÿง","aliases":["shaved_ice"]},{"emoji":"๐Ÿ‘","aliases":["sheep"]},{"emoji":"๐Ÿš","aliases":["shell"]},{"emoji":"๐Ÿ›ก๏ธ","aliases":["shield"]},{"emoji":"โ›ฉ๏ธ","aliases":["shinto_shrine"]},{"emoji":"๐Ÿšข","aliases":["ship"]},{"emoji":"๐Ÿ‘•","aliases":["shirt","tshirt"]},{"emoji":"๐Ÿ›๏ธ","aliases":["shopping"]},{"emoji":"๐Ÿ›’","aliases":["shopping_cart"]},{"emoji":"๐Ÿฉณ","aliases":["shorts"]},{"emoji":"๐Ÿšฟ","aliases":["shower"]},{"emoji":"๐Ÿฆ","aliases":["shrimp"]},{"emoji":"๐Ÿคท","aliases":["shrug"]},{"emoji":"๐Ÿคซ","aliases":["shushing_face"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฑ","aliases":["sierra_leone"]},{"emoji":"๐Ÿ“ถ","aliases":["signal_strength"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฌ","aliases":["singapore"]},{"emoji":"๐Ÿง‘โ€๐ŸŽค","aliases":["singer"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฝ","aliases":["sint_maarten"]},{"emoji":"๐Ÿ”ฏ","aliases":["six_pointed_star"]},{"emoji":"๐Ÿ›น","aliases":["skateboard"]},{"emoji":"๐ŸŽฟ","aliases":["ski"]},{"emoji":"โ›ท๏ธ","aliases":["skier"]},{"emoji":"๐Ÿ’€","aliases":["skull"]},{"emoji":"โ˜ ๏ธ","aliases":["skull_and_crossbones"]},{"emoji":"๐Ÿฆจ","aliases":["skunk"]},{"emoji":"๐Ÿ›ท","aliases":["sled"]},{"emoji":"๐Ÿ˜ด","aliases":["sleeping"]},{"emoji":"๐Ÿ›Œ","aliases":["sleeping_bed"]},{"emoji":"๐Ÿ˜ช","aliases":["sleepy"]},{"emoji":"๐Ÿ™","aliases":["slightly_frowning_face"]},{"emoji":"๐Ÿ™‚","aliases":["slightly_smiling_face"]},{"emoji":"๐ŸŽฐ","aliases":["slot_machine"]},{"emoji":"๐Ÿฆฅ","aliases":["sloth"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฐ","aliases":["slovakia"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฎ","aliases":["slovenia"]},{"emoji":"๐Ÿ›ฉ๏ธ","aliases":["small_airplane"]},{"emoji":"๐Ÿ”น","aliases":["small_blue_diamond"]},{"emoji":"๐Ÿ”ธ","aliases":["small_orange_diamond"]},{"emoji":"๐Ÿ”บ","aliases":["small_red_triangle"]},{"emoji":"๐Ÿ”ป","aliases":["small_red_triangle_down"]},{"emoji":"๐Ÿ˜„","aliases":["smile"]},{"emoji":"๐Ÿ˜ธ","aliases":["smile_cat"]},{"emoji":"๐Ÿ˜ƒ","aliases":["smiley"]},{"emoji":"๐Ÿ˜บ","aliases":["smiley_cat"]},{"emoji":"๐Ÿฅฐ","aliases":["smiling_face_with_three_hearts"]},{"emoji":"๐Ÿ˜ˆ","aliases":["smiling_imp"]},{"emoji":"๐Ÿ˜","aliases":["smirk"]},{"emoji":"๐Ÿ˜ผ","aliases":["smirk_cat"]},{"emoji":"๐Ÿšฌ","aliases":["smoking"]},{"emoji":"๐ŸŒ","aliases":["snail"]},{"emoji":"๐Ÿ","aliases":["snake"]},{"emoji":"๐Ÿคง","aliases":["sneezing_face"]},{"emoji":"๐Ÿ‚","aliases":["snowboarder"]},{"emoji":"โ„๏ธ","aliases":["snowflake"]},{"emoji":"โ›„","aliases":["snowman"]},{"emoji":"โ˜ƒ๏ธ","aliases":["snowman_with_snow"]},{"emoji":"๐Ÿงผ","aliases":["soap"]},{"emoji":"๐Ÿ˜ญ","aliases":["sob"]},{"emoji":"โšฝ","aliases":["soccer"]},{"emoji":"๐Ÿงฆ","aliases":["socks"]},{"emoji":"๐ŸฅŽ","aliases":["softball"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ง","aliases":["solomon_islands"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ด","aliases":["somalia"]},{"emoji":"๐Ÿ”œ","aliases":["soon"]},{"emoji":"๐Ÿ†˜","aliases":["sos"]},{"emoji":"๐Ÿ”‰","aliases":["sound"]},{"emoji":"๐Ÿ‡ฟ๐Ÿ‡ฆ","aliases":["south_africa"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ธ","aliases":["south_georgia_south_sandwich_islands"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ธ","aliases":["south_sudan"]},{"emoji":"๐Ÿ‘พ","aliases":["space_invader"]},{"emoji":"โ™ ๏ธ","aliases":["spades"]},{"emoji":"๐Ÿ","aliases":["spaghetti"]},{"emoji":"โ‡๏ธ","aliases":["sparkle"]},{"emoji":"๐ŸŽ‡","aliases":["sparkler"]},{"emoji":"โœจ","aliases":["sparkles"]},{"emoji":"๐Ÿ’–","aliases":["sparkling_heart"]},{"emoji":"๐Ÿ™Š","aliases":["speak_no_evil"]},{"emoji":"๐Ÿ”ˆ","aliases":["speaker"]},{"emoji":"๐Ÿ—ฃ๏ธ","aliases":["speaking_head"]},{"emoji":"๐Ÿ’ฌ","aliases":["speech_balloon"]},{"emoji":"๐Ÿšค","aliases":["speedboat"]},{"emoji":"๐Ÿ•ท๏ธ","aliases":["spider"]},{"emoji":"๐Ÿ•ธ๏ธ","aliases":["spider_web"]},{"emoji":"๐Ÿ—“๏ธ","aliases":["spiral_calendar"]},{"emoji":"๐Ÿ—’๏ธ","aliases":["spiral_notepad"]},{"emoji":"๐Ÿงฝ","aliases":["sponge"]},{"emoji":"๐Ÿฅ„","aliases":["spoon"]},{"emoji":"๐Ÿฆ‘","aliases":["squid"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ฐ","aliases":["sri_lanka"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฑ","aliases":["st_barthelemy"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ญ","aliases":["st_helena"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ณ","aliases":["st_kitts_nevis"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡จ","aliases":["st_lucia"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ซ","aliases":["st_martin"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ฒ","aliases":["st_pierre_miquelon"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡จ","aliases":["st_vincent_grenadines"]},{"emoji":"๐ŸŸ๏ธ","aliases":["stadium"]},{"emoji":"๐Ÿงโ€โ™‚๏ธ","aliases":["standing_man"]},{"emoji":"๐Ÿง","aliases":["standing_person"]},{"emoji":"๐Ÿงโ€โ™€๏ธ","aliases":["standing_woman"]},{"emoji":"โญ","aliases":["star"]},{"emoji":"๐ŸŒŸ","aliases":["star2"]},{"emoji":"โ˜ช๏ธ","aliases":["star_and_crescent"]},{"emoji":"โœก๏ธ","aliases":["star_of_david"]},{"emoji":"๐Ÿคฉ","aliases":["star_struck"]},{"emoji":"๐ŸŒ ","aliases":["stars"]},{"emoji":"๐Ÿš‰","aliases":["station"]},{"emoji":"๐Ÿ—ฝ","aliases":["statue_of_liberty"]},{"emoji":"๐Ÿš‚","aliases":["steam_locomotive"]},{"emoji":"๐Ÿฉบ","aliases":["stethoscope"]},{"emoji":"๐Ÿฒ","aliases":["stew"]},{"emoji":"โน๏ธ","aliases":["stop_button"]},{"emoji":"๐Ÿ›‘","aliases":["stop_sign"]},{"emoji":"โฑ๏ธ","aliases":["stopwatch"]},{"emoji":"๐Ÿ“","aliases":["straight_ruler"]},{"emoji":"๐Ÿ“","aliases":["strawberry"]},{"emoji":"๐Ÿ˜›","aliases":["stuck_out_tongue"]},{"emoji":"๐Ÿ˜","aliases":["stuck_out_tongue_closed_eyes"]},{"emoji":"๐Ÿ˜œ","aliases":["stuck_out_tongue_winking_eye"]},{"emoji":"๐Ÿง‘โ€๐ŸŽ“","aliases":["student"]},{"emoji":"๐ŸŽ™๏ธ","aliases":["studio_microphone"]},{"emoji":"๐Ÿฅ™","aliases":["stuffed_flatbread"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฉ","aliases":["sudan"]},{"emoji":"๐ŸŒฅ๏ธ","aliases":["sun_behind_large_cloud"]},{"emoji":"๐ŸŒฆ๏ธ","aliases":["sun_behind_rain_cloud"]},{"emoji":"๐ŸŒค๏ธ","aliases":["sun_behind_small_cloud"]},{"emoji":"๐ŸŒž","aliases":["sun_with_face"]},{"emoji":"๐ŸŒป","aliases":["sunflower"]},{"emoji":"๐Ÿ˜Ž","aliases":["sunglasses"]},{"emoji":"โ˜€๏ธ","aliases":["sunny"]},{"emoji":"๐ŸŒ…","aliases":["sunrise"]},{"emoji":"๐ŸŒ„","aliases":["sunrise_over_mountains"]},{"emoji":"๐Ÿฆธ","aliases":["superhero"]},{"emoji":"๐Ÿฆธโ€โ™‚๏ธ","aliases":["superhero_man"]},{"emoji":"๐Ÿฆธโ€โ™€๏ธ","aliases":["superhero_woman"]},{"emoji":"๐Ÿฆน","aliases":["supervillain"]},{"emoji":"๐Ÿฆนโ€โ™‚๏ธ","aliases":["supervillain_man"]},{"emoji":"๐Ÿฆนโ€โ™€๏ธ","aliases":["supervillain_woman"]},{"emoji":"๐Ÿ„","aliases":["surfer"]},{"emoji":"๐Ÿ„โ€โ™‚๏ธ","aliases":["surfing_man"]},{"emoji":"๐Ÿ„โ€โ™€๏ธ","aliases":["surfing_woman"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ท","aliases":["suriname"]},{"emoji":"๐Ÿฃ","aliases":["sushi"]},{"emoji":"๐ŸšŸ","aliases":["suspension_railway"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฏ","aliases":["svalbard_jan_mayen"]},{"emoji":"๐Ÿฆข","aliases":["swan"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฟ","aliases":["swaziland"]},{"emoji":"๐Ÿ˜“","aliases":["sweat"]},{"emoji":"๐Ÿ’ฆ","aliases":["sweat_drops"]},{"emoji":"๐Ÿ˜…","aliases":["sweat_smile"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ช","aliases":["sweden"]},{"emoji":"๐Ÿ ","aliases":["sweet_potato"]},{"emoji":"๐Ÿฉฒ","aliases":["swim_brief"]},{"emoji":"๐ŸŠ","aliases":["swimmer"]},{"emoji":"๐ŸŠโ€โ™‚๏ธ","aliases":["swimming_man"]},{"emoji":"๐ŸŠโ€โ™€๏ธ","aliases":["swimming_woman"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ญ","aliases":["switzerland"]},{"emoji":"๐Ÿ”ฃ","aliases":["symbols"]},{"emoji":"๐Ÿ•","aliases":["synagogue"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡พ","aliases":["syria"]},{"emoji":"๐Ÿ’‰","aliases":["syringe"]},{"emoji":"๐Ÿฆ–","aliases":["t-rex"]},{"emoji":"๐ŸŒฎ","aliases":["taco"]},{"emoji":"๐ŸŽ‰","aliases":["tada","hooray"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ผ","aliases":["taiwan"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฏ","aliases":["tajikistan"]},{"emoji":"๐Ÿฅก","aliases":["takeout_box"]},{"emoji":"๐ŸŽ‹","aliases":["tanabata_tree"]},{"emoji":"๐ŸŠ","aliases":["tangerine","orange","mandarin"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฟ","aliases":["tanzania"]},{"emoji":"โ™‰","aliases":["taurus"]},{"emoji":"๐Ÿš•","aliases":["taxi"]},{"emoji":"๐Ÿต","aliases":["tea"]},{"emoji":"๐Ÿง‘โ€๐Ÿซ","aliases":["teacher"]},{"emoji":"๐Ÿง‘โ€๐Ÿ’ป","aliases":["technologist"]},{"emoji":"๐Ÿงธ","aliases":["teddy_bear"]},{"emoji":"๐Ÿ“ž","aliases":["telephone_receiver"]},{"emoji":"๐Ÿ”ญ","aliases":["telescope"]},{"emoji":"๐ŸŽพ","aliases":["tennis"]},{"emoji":"โ›บ","aliases":["tent"]},{"emoji":"๐Ÿงช","aliases":["test_tube"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ญ","aliases":["thailand"]},{"emoji":"๐ŸŒก๏ธ","aliases":["thermometer"]},{"emoji":"๐Ÿค”","aliases":["thinking"]},{"emoji":"๐Ÿ’ญ","aliases":["thought_balloon"]},{"emoji":"๐Ÿงต","aliases":["thread"]},{"emoji":"๐ŸŽซ","aliases":["ticket"]},{"emoji":"๐ŸŽŸ๏ธ","aliases":["tickets"]},{"emoji":"๐Ÿฏ","aliases":["tiger"]},{"emoji":"๐Ÿ…","aliases":["tiger2"]},{"emoji":"โฒ๏ธ","aliases":["timer_clock"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฑ","aliases":["timor_leste"]},{"emoji":"๐Ÿ’โ€โ™‚๏ธ","aliases":["tipping_hand_man","sassy_man"]},{"emoji":"๐Ÿ’","aliases":["tipping_hand_person","information_desk_person"]},{"emoji":"๐Ÿ’โ€โ™€๏ธ","aliases":["tipping_hand_woman","sassy_woman"]},{"emoji":"๐Ÿ˜ซ","aliases":["tired_face"]},{"emoji":"โ„ข๏ธ","aliases":["tm"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฌ","aliases":["togo"]},{"emoji":"๐Ÿšฝ","aliases":["toilet"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฐ","aliases":["tokelau"]},{"emoji":"๐Ÿ—ผ","aliases":["tokyo_tower"]},{"emoji":"๐Ÿ…","aliases":["tomato"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ด","aliases":["tonga"]},{"emoji":"๐Ÿ‘…","aliases":["tongue"]},{"emoji":"๐Ÿงฐ","aliases":["toolbox"]},{"emoji":"๐Ÿฆท","aliases":["tooth"]},{"emoji":"๐Ÿ”","aliases":["top"]},{"emoji":"๐ŸŽฉ","aliases":["tophat"]},{"emoji":"๐ŸŒช๏ธ","aliases":["tornado"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ท","aliases":["tr"]},{"emoji":"๐Ÿ–ฒ๏ธ","aliases":["trackball"]},{"emoji":"๐Ÿšœ","aliases":["tractor"]},{"emoji":"๐Ÿšฅ","aliases":["traffic_light"]},{"emoji":"๐Ÿš‹","aliases":["train"]},{"emoji":"๐Ÿš†","aliases":["train2"]},{"emoji":"๐ŸšŠ","aliases":["tram"]},{"emoji":"๐Ÿšฉ","aliases":["triangular_flag_on_post"]},{"emoji":"๐Ÿ“","aliases":["triangular_ruler"]},{"emoji":"๐Ÿ”ฑ","aliases":["trident"]},{"emoji":"๐Ÿ‡น๐Ÿ‡น","aliases":["trinidad_tobago"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฆ","aliases":["tristan_da_cunha"]},{"emoji":"๐Ÿ˜ค","aliases":["triumph"]},{"emoji":"๐ŸšŽ","aliases":["trolleybus"]},{"emoji":"๐Ÿ†","aliases":["trophy"]},{"emoji":"๐Ÿน","aliases":["tropical_drink"]},{"emoji":"๐Ÿ ","aliases":["tropical_fish"]},{"emoji":"๐Ÿšš","aliases":["truck"]},{"emoji":"๐ŸŽบ","aliases":["trumpet"]},{"emoji":"๐ŸŒท","aliases":["tulip"]},{"emoji":"๐Ÿฅƒ","aliases":["tumbler_glass"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ณ","aliases":["tunisia"]},{"emoji":"๐Ÿฆƒ","aliases":["turkey"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฒ","aliases":["turkmenistan"]},{"emoji":"๐Ÿ‡น๐Ÿ‡จ","aliases":["turks_caicos_islands"]},{"emoji":"๐Ÿข","aliases":["turtle"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ป","aliases":["tuvalu"]},{"emoji":"๐Ÿ“บ","aliases":["tv"]},{"emoji":"๐Ÿ”€","aliases":["twisted_rightwards_arrows"]},{"emoji":"๐Ÿ’•","aliases":["two_hearts"]},{"emoji":"๐Ÿ‘ฌ","aliases":["two_men_holding_hands"]},{"emoji":"๐Ÿ‘ญ","aliases":["two_women_holding_hands"]},{"emoji":"๐Ÿˆน","aliases":["u5272"]},{"emoji":"๐Ÿˆด","aliases":["u5408"]},{"emoji":"๐Ÿˆบ","aliases":["u55b6"]},{"emoji":"๐Ÿˆฏ","aliases":["u6307"]},{"emoji":"๐Ÿˆท๏ธ","aliases":["u6708"]},{"emoji":"๐Ÿˆถ","aliases":["u6709"]},{"emoji":"๐Ÿˆต","aliases":["u6e80"]},{"emoji":"๐Ÿˆš","aliases":["u7121"]},{"emoji":"๐Ÿˆธ","aliases":["u7533"]},{"emoji":"๐Ÿˆฒ","aliases":["u7981"]},{"emoji":"๐Ÿˆณ","aliases":["u7a7a"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ฌ","aliases":["uganda"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ฆ","aliases":["ukraine"]},{"emoji":"โ˜”","aliases":["umbrella"]},{"emoji":"๐Ÿ˜’","aliases":["unamused"]},{"emoji":"๐Ÿ”ž","aliases":["underage"]},{"emoji":"๐Ÿฆ„","aliases":["unicorn"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ช","aliases":["united_arab_emirates"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ณ","aliases":["united_nations"]},{"emoji":"๐Ÿ”“","aliases":["unlock"]},{"emoji":"๐Ÿ†™","aliases":["up"]},{"emoji":"๐Ÿ™ƒ","aliases":["upside_down_face"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡พ","aliases":["uruguay"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ธ","aliases":["us"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ฒ","aliases":["us_outlying_islands"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡ฎ","aliases":["us_virgin_islands"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ฟ","aliases":["uzbekistan"]},{"emoji":"โœŒ๏ธ","aliases":["v"]},{"emoji":"๐Ÿง›","aliases":["vampire"]},{"emoji":"๐Ÿง›โ€โ™‚๏ธ","aliases":["vampire_man"]},{"emoji":"๐Ÿง›โ€โ™€๏ธ","aliases":["vampire_woman"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡บ","aliases":["vanuatu"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡ฆ","aliases":["vatican_city"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡ช","aliases":["venezuela"]},{"emoji":"๐Ÿšฆ","aliases":["vertical_traffic_light"]},{"emoji":"๐Ÿ“ผ","aliases":["vhs"]},{"emoji":"๐Ÿ“ณ","aliases":["vibration_mode"]},{"emoji":"๐Ÿ“น","aliases":["video_camera"]},{"emoji":"๐ŸŽฎ","aliases":["video_game"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡ณ","aliases":["vietnam"]},{"emoji":"๐ŸŽป","aliases":["violin"]},{"emoji":"โ™","aliases":["virgo"]},{"emoji":"๐ŸŒ‹","aliases":["volcano"]},{"emoji":"๐Ÿ","aliases":["volleyball"]},{"emoji":"๐Ÿคฎ","aliases":["vomiting_face"]},{"emoji":"๐Ÿ†š","aliases":["vs"]},{"emoji":"๐Ÿ––","aliases":["vulcan_salute"]},{"emoji":"๐Ÿง‡","aliases":["waffle"]},{"emoji":"๐Ÿด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ","aliases":["wales"]},{"emoji":"๐Ÿšถ","aliases":["walking"]},{"emoji":"๐Ÿšถโ€โ™‚๏ธ","aliases":["walking_man"]},{"emoji":"๐Ÿšถโ€โ™€๏ธ","aliases":["walking_woman"]},{"emoji":"๐Ÿ‡ผ๐Ÿ‡ซ","aliases":["wallis_futuna"]},{"emoji":"๐ŸŒ˜","aliases":["waning_crescent_moon"]},{"emoji":"๐ŸŒ–","aliases":["waning_gibbous_moon"]},{"emoji":"โš ๏ธ","aliases":["warning"]},{"emoji":"๐Ÿ—‘๏ธ","aliases":["wastebasket"]},{"emoji":"โŒš","aliases":["watch"]},{"emoji":"๐Ÿƒ","aliases":["water_buffalo"]},{"emoji":"๐Ÿคฝ","aliases":["water_polo"]},{"emoji":"๐Ÿ‰","aliases":["watermelon"]},{"emoji":"๐Ÿ‘‹","aliases":["wave"]},{"emoji":"ใ€ฐ๏ธ","aliases":["wavy_dash"]},{"emoji":"๐ŸŒ’","aliases":["waxing_crescent_moon"]},{"emoji":"๐Ÿšพ","aliases":["wc"]},{"emoji":"๐Ÿ˜ฉ","aliases":["weary"]},{"emoji":"๐Ÿ’’","aliases":["wedding"]},{"emoji":"๐Ÿ‹๏ธ","aliases":["weight_lifting"]},{"emoji":"๐Ÿ‹๏ธโ€โ™‚๏ธ","aliases":["weight_lifting_man"]},{"emoji":"๐Ÿ‹๏ธโ€โ™€๏ธ","aliases":["weight_lifting_woman"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ญ","aliases":["western_sahara"]},{"emoji":"๐Ÿณ","aliases":["whale"]},{"emoji":"๐Ÿ‹","aliases":["whale2"]},{"emoji":"โ˜ธ๏ธ","aliases":["wheel_of_dharma"]},{"emoji":"โ™ฟ","aliases":["wheelchair"]},{"emoji":"โœ…","aliases":["white_check_mark"]},{"emoji":"โšช","aliases":["white_circle"]},{"emoji":"๐Ÿณ๏ธ","aliases":["white_flag"]},{"emoji":"๐Ÿ’ฎ","aliases":["white_flower"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆณ","aliases":["white_haired_man"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆณ","aliases":["white_haired_woman"]},{"emoji":"๐Ÿค","aliases":["white_heart"]},{"emoji":"โฌœ","aliases":["white_large_square"]},{"emoji":"โ—ฝ","aliases":["white_medium_small_square"]},{"emoji":"โ—ป๏ธ","aliases":["white_medium_square"]},{"emoji":"โ–ซ๏ธ","aliases":["white_small_square"]},{"emoji":"๐Ÿ”ณ","aliases":["white_square_button"]},{"emoji":"๐Ÿฅ€","aliases":["wilted_flower"]},{"emoji":"๐ŸŽ","aliases":["wind_chime"]},{"emoji":"๐ŸŒฌ๏ธ","aliases":["wind_face"]},{"emoji":"๐Ÿท","aliases":["wine_glass"]},{"emoji":"๐Ÿ˜‰","aliases":["wink"]},{"emoji":"๐Ÿบ","aliases":["wolf"]},{"emoji":"๐Ÿ‘ฉ","aliases":["woman"]},{"emoji":"๐Ÿ‘ฉโ€๐ŸŽจ","aliases":["woman_artist"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿš€","aliases":["woman_astronaut"]},{"emoji":"๐Ÿคธโ€โ™€๏ธ","aliases":["woman_cartwheeling"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿณ","aliases":["woman_cook"]},{"emoji":"๐Ÿ’ƒ","aliases":["woman_dancing","dancer"]},{"emoji":"๐Ÿคฆโ€โ™€๏ธ","aliases":["woman_facepalming"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿญ","aliases":["woman_factory_worker"]},{"emoji":"๐Ÿ‘ฉโ€๐ŸŒพ","aliases":["woman_farmer"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿš’","aliases":["woman_firefighter"]},{"emoji":"๐Ÿ‘ฉโ€โš•๏ธ","aliases":["woman_health_worker"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆฝ","aliases":["woman_in_manual_wheelchair"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆผ","aliases":["woman_in_motorized_wheelchair"]},{"emoji":"๐Ÿ‘ฉโ€โš–๏ธ","aliases":["woman_judge"]},{"emoji":"๐Ÿคนโ€โ™€๏ธ","aliases":["woman_juggling"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ”ง","aliases":["woman_mechanic"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ’ผ","aliases":["woman_office_worker"]},{"emoji":"๐Ÿ‘ฉโ€โœˆ๏ธ","aliases":["woman_pilot"]},{"emoji":"๐Ÿคพโ€โ™€๏ธ","aliases":["woman_playing_handball"]},{"emoji":"๐Ÿคฝโ€โ™€๏ธ","aliases":["woman_playing_water_polo"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ”ฌ","aliases":["woman_scientist"]},{"emoji":"๐Ÿคทโ€โ™€๏ธ","aliases":["woman_shrugging"]},{"emoji":"๐Ÿ‘ฉโ€๐ŸŽค","aliases":["woman_singer"]},{"emoji":"๐Ÿ‘ฉโ€๐ŸŽ“","aliases":["woman_student"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿซ","aliases":["woman_teacher"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ’ป","aliases":["woman_technologist"]},{"emoji":"๐Ÿง•","aliases":["woman_with_headscarf"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆฏ","aliases":["woman_with_probing_cane"]},{"emoji":"๐Ÿ‘ณโ€โ™€๏ธ","aliases":["woman_with_turban"]},{"emoji":"๐Ÿ‘š","aliases":["womans_clothes"]},{"emoji":"๐Ÿ‘’","aliases":["womans_hat"]},{"emoji":"๐Ÿคผโ€โ™€๏ธ","aliases":["women_wrestling"]},{"emoji":"๐Ÿšบ","aliases":["womens"]},{"emoji":"๐Ÿฅด","aliases":["woozy_face"]},{"emoji":"๐Ÿ—บ๏ธ","aliases":["world_map"]},{"emoji":"๐Ÿ˜Ÿ","aliases":["worried"]},{"emoji":"๐Ÿ”ง","aliases":["wrench"]},{"emoji":"๐Ÿคผ","aliases":["wrestling"]},{"emoji":"โœ๏ธ","aliases":["writing_hand"]},{"emoji":"โŒ","aliases":["x"]},{"emoji":"๐Ÿงถ","aliases":["yarn"]},{"emoji":"๐Ÿฅฑ","aliases":["yawning_face"]},{"emoji":"๐ŸŸก","aliases":["yellow_circle"]},{"emoji":"๐Ÿ’›","aliases":["yellow_heart"]},{"emoji":"๐ŸŸจ","aliases":["yellow_square"]},{"emoji":"๐Ÿ‡พ๐Ÿ‡ช","aliases":["yemen"]},{"emoji":"๐Ÿ’ด","aliases":["yen"]},{"emoji":"โ˜ฏ๏ธ","aliases":["yin_yang"]},{"emoji":"๐Ÿช€","aliases":["yo_yo"]},{"emoji":"๐Ÿ˜‹","aliases":["yum"]},{"emoji":"๐Ÿ‡ฟ๐Ÿ‡ฒ","aliases":["zambia"]},{"emoji":"๐Ÿคช","aliases":["zany_face"]},{"emoji":"โšก","aliases":["zap"]},{"emoji":"๐Ÿฆ“","aliases":["zebra"]},{"emoji":"๐Ÿ‡ฟ๐Ÿ‡ผ","aliases":["zimbabwe"]},{"emoji":"๐Ÿค","aliases":["zipper_mouth_face"]},{"emoji":"๐ŸงŸ","aliases":["zombie"]},{"emoji":"๐ŸงŸโ€โ™‚๏ธ","aliases":["zombie_man"]},{"emoji":"๐ŸงŸโ€โ™€๏ธ","aliases":["zombie_woman"]},{"emoji":"๐Ÿ’ค","aliases":["zzz"]}]
\ No newline at end of file
+[{"emoji":"๐Ÿ‘","aliases":["+1","thumbsup"]},{"emoji":"๐Ÿ‘Ž","aliases":["-1","thumbsdown"]},{"emoji":"๐Ÿ’ฏ","aliases":["100"]},{"emoji":"๐Ÿ”ข","aliases":["1234"]},{"emoji":"๐Ÿฅ‡","aliases":["1st_place_medal"]},{"emoji":"๐Ÿฅˆ","aliases":["2nd_place_medal"]},{"emoji":"๐Ÿฅ‰","aliases":["3rd_place_medal"]},{"emoji":"๐ŸŽฑ","aliases":["8ball"]},{"emoji":"๐Ÿ…ฐ๏ธ","aliases":["a"]},{"emoji":"๐Ÿ†Ž","aliases":["ab"]},{"emoji":"๐Ÿงฎ","aliases":["abacus"]},{"emoji":"๐Ÿ”ค","aliases":["abc"]},{"emoji":"๐Ÿ”ก","aliases":["abcd"]},{"emoji":"๐Ÿ‰‘","aliases":["accept"]},{"emoji":"๐Ÿฉน","aliases":["adhesive_bandage"]},{"emoji":"๐Ÿง‘","aliases":["adult"]},{"emoji":"๐Ÿšก","aliases":["aerial_tramway"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ซ","aliases":["afghanistan"]},{"emoji":"โœˆ๏ธ","aliases":["airplane"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฝ","aliases":["aland_islands"]},{"emoji":"โฐ","aliases":["alarm_clock"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฑ","aliases":["albania"]},{"emoji":"โš—๏ธ","aliases":["alembic"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ฟ","aliases":["algeria"]},{"emoji":"๐Ÿ‘ฝ","aliases":["alien"]},{"emoji":"๐Ÿš‘","aliases":["ambulance"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ธ","aliases":["american_samoa"]},{"emoji":"๐Ÿบ","aliases":["amphora"]},{"emoji":"โš“","aliases":["anchor"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฉ","aliases":["andorra"]},{"emoji":"๐Ÿ‘ผ","aliases":["angel"]},{"emoji":"๐Ÿ’ข","aliases":["anger"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ด","aliases":["angola"]},{"emoji":"๐Ÿ˜ ","aliases":["angry"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฎ","aliases":["anguilla"]},{"emoji":"๐Ÿ˜ง","aliases":["anguished"]},{"emoji":"๐Ÿœ","aliases":["ant"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ถ","aliases":["antarctica"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฌ","aliases":["antigua_barbuda"]},{"emoji":"๐ŸŽ","aliases":["apple"]},{"emoji":"โ™’","aliases":["aquarius"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ท","aliases":["argentina"]},{"emoji":"โ™ˆ","aliases":["aries"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฒ","aliases":["armenia"]},{"emoji":"โ—€๏ธ","aliases":["arrow_backward"]},{"emoji":"โฌ","aliases":["arrow_double_down"]},{"emoji":"โซ","aliases":["arrow_double_up"]},{"emoji":"โฌ‡๏ธ","aliases":["arrow_down"]},{"emoji":"๐Ÿ”ฝ","aliases":["arrow_down_small"]},{"emoji":"โ–ถ๏ธ","aliases":["arrow_forward"]},{"emoji":"โคต๏ธ","aliases":["arrow_heading_down"]},{"emoji":"โคด๏ธ","aliases":["arrow_heading_up"]},{"emoji":"โฌ…๏ธ","aliases":["arrow_left"]},{"emoji":"โ†™๏ธ","aliases":["arrow_lower_left"]},{"emoji":"โ†˜๏ธ","aliases":["arrow_lower_right"]},{"emoji":"โžก๏ธ","aliases":["arrow_right"]},{"emoji":"โ†ช๏ธ","aliases":["arrow_right_hook"]},{"emoji":"โฌ†๏ธ","aliases":["arrow_up"]},{"emoji":"โ†•๏ธ","aliases":["arrow_up_down"]},{"emoji":"๐Ÿ”ผ","aliases":["arrow_up_small"]},{"emoji":"โ†–๏ธ","aliases":["arrow_upper_left"]},{"emoji":"โ†—๏ธ","aliases":["arrow_upper_right"]},{"emoji":"๐Ÿ”ƒ","aliases":["arrows_clockwise"]},{"emoji":"๐Ÿ”„","aliases":["arrows_counterclockwise"]},{"emoji":"๐ŸŽจ","aliases":["art"]},{"emoji":"๐Ÿš›","aliases":["articulated_lorry"]},{"emoji":"๐Ÿ›ฐ๏ธ","aliases":["artificial_satellite"]},{"emoji":"๐Ÿง‘โ€๐ŸŽจ","aliases":["artist"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ผ","aliases":["aruba"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡จ","aliases":["ascension_island"]},{"emoji":"*๏ธโƒฃ","aliases":["asterisk"]},{"emoji":"๐Ÿ˜ฒ","aliases":["astonished"]},{"emoji":"๐Ÿง‘โ€๐Ÿš€","aliases":["astronaut"]},{"emoji":"๐Ÿ‘Ÿ","aliases":["athletic_shoe"]},{"emoji":"๐Ÿง","aliases":["atm"]},{"emoji":"โš›๏ธ","aliases":["atom_symbol"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡บ","aliases":["australia"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡น","aliases":["austria"]},{"emoji":"๐Ÿ›บ","aliases":["auto_rickshaw"]},{"emoji":"๐Ÿฅ‘","aliases":["avocado"]},{"emoji":"๐Ÿช“","aliases":["axe"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ฟ","aliases":["azerbaijan"]},{"emoji":"๐Ÿ…ฑ๏ธ","aliases":["b"]},{"emoji":"๐Ÿ‘ถ","aliases":["baby"]},{"emoji":"๐Ÿผ","aliases":["baby_bottle"]},{"emoji":"๐Ÿค","aliases":["baby_chick"]},{"emoji":"๐Ÿšผ","aliases":["baby_symbol"]},{"emoji":"๐Ÿ”™","aliases":["back"]},{"emoji":"๐Ÿฅ“","aliases":["bacon"]},{"emoji":"๐Ÿฆก","aliases":["badger"]},{"emoji":"๐Ÿธ","aliases":["badminton"]},{"emoji":"๐Ÿฅฏ","aliases":["bagel"]},{"emoji":"๐Ÿ›„","aliases":["baggage_claim"]},{"emoji":"๐Ÿฅ–","aliases":["baguette_bread"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ธ","aliases":["bahamas"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ญ","aliases":["bahrain"]},{"emoji":"โš–๏ธ","aliases":["balance_scale"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆฒ","aliases":["bald_man"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆฒ","aliases":["bald_woman"]},{"emoji":"๐Ÿฉฐ","aliases":["ballet_shoes"]},{"emoji":"๐ŸŽˆ","aliases":["balloon"]},{"emoji":"๐Ÿ—ณ๏ธ","aliases":["ballot_box"]},{"emoji":"โ˜‘๏ธ","aliases":["ballot_box_with_check"]},{"emoji":"๐ŸŽ","aliases":["bamboo"]},{"emoji":"๐ŸŒ","aliases":["banana"]},{"emoji":"โ€ผ๏ธ","aliases":["bangbang"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฉ","aliases":["bangladesh"]},{"emoji":"๐Ÿช•","aliases":["banjo"]},{"emoji":"๐Ÿฆ","aliases":["bank"]},{"emoji":"๐Ÿ“Š","aliases":["bar_chart"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ง","aliases":["barbados"]},{"emoji":"๐Ÿ’ˆ","aliases":["barber"]},{"emoji":"โšพ","aliases":["baseball"]},{"emoji":"๐Ÿงบ","aliases":["basket"]},{"emoji":"๐Ÿ€","aliases":["basketball"]},{"emoji":"๐Ÿฆ‡","aliases":["bat"]},{"emoji":"๐Ÿ›€","aliases":["bath"]},{"emoji":"๐Ÿ›","aliases":["bathtub"]},{"emoji":"๐Ÿ”‹","aliases":["battery"]},{"emoji":"๐Ÿ–๏ธ","aliases":["beach_umbrella"]},{"emoji":"๐Ÿป","aliases":["bear"]},{"emoji":"๐Ÿง”","aliases":["bearded_person"]},{"emoji":"๐Ÿ›๏ธ","aliases":["bed"]},{"emoji":"๐Ÿ","aliases":["bee","honeybee"]},{"emoji":"๐Ÿบ","aliases":["beer"]},{"emoji":"๐Ÿป","aliases":["beers"]},{"emoji":"๐Ÿ”ฐ","aliases":["beginner"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡พ","aliases":["belarus"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ช","aliases":["belgium"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฟ","aliases":["belize"]},{"emoji":"๐Ÿ””","aliases":["bell"]},{"emoji":"๐Ÿ›Ž๏ธ","aliases":["bellhop_bell"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฏ","aliases":["benin"]},{"emoji":"๐Ÿฑ","aliases":["bento"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฒ","aliases":["bermuda"]},{"emoji":"๐Ÿงƒ","aliases":["beverage_box"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡น","aliases":["bhutan"]},{"emoji":"๐Ÿšด","aliases":["bicyclist"]},{"emoji":"๐Ÿšฒ","aliases":["bike"]},{"emoji":"๐Ÿšดโ€โ™‚๏ธ","aliases":["biking_man"]},{"emoji":"๐Ÿšดโ€โ™€๏ธ","aliases":["biking_woman"]},{"emoji":"๐Ÿ‘™","aliases":["bikini"]},{"emoji":"๐Ÿงข","aliases":["billed_cap"]},{"emoji":"โ˜ฃ๏ธ","aliases":["biohazard"]},{"emoji":"๐Ÿฆ","aliases":["bird"]},{"emoji":"๐ŸŽ‚","aliases":["birthday"]},{"emoji":"โšซ","aliases":["black_circle"]},{"emoji":"๐Ÿด","aliases":["black_flag"]},{"emoji":"๐Ÿ–ค","aliases":["black_heart"]},{"emoji":"๐Ÿƒ","aliases":["black_joker"]},{"emoji":"โฌ›","aliases":["black_large_square"]},{"emoji":"โ—พ","aliases":["black_medium_small_square"]},{"emoji":"โ—ผ๏ธ","aliases":["black_medium_square"]},{"emoji":"โœ’๏ธ","aliases":["black_nib"]},{"emoji":"โ–ช๏ธ","aliases":["black_small_square"]},{"emoji":"๐Ÿ”ฒ","aliases":["black_square_button"]},{"emoji":"๐Ÿ‘ฑโ€โ™‚๏ธ","aliases":["blond_haired_man"]},{"emoji":"๐Ÿ‘ฑ","aliases":["blond_haired_person"]},{"emoji":"๐Ÿ‘ฑโ€โ™€๏ธ","aliases":["blond_haired_woman","blonde_woman"]},{"emoji":"๐ŸŒผ","aliases":["blossom"]},{"emoji":"๐Ÿก","aliases":["blowfish"]},{"emoji":"๐Ÿ“˜","aliases":["blue_book"]},{"emoji":"๐Ÿš™","aliases":["blue_car"]},{"emoji":"๐Ÿ’™","aliases":["blue_heart"]},{"emoji":"๐ŸŸฆ","aliases":["blue_square"]},{"emoji":"๐Ÿ˜Š","aliases":["blush"]},{"emoji":"๐Ÿ—","aliases":["boar"]},{"emoji":"โ›ต","aliases":["boat","sailboat"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ด","aliases":["bolivia"]},{"emoji":"๐Ÿ’ฃ","aliases":["bomb"]},{"emoji":"๐Ÿฆด","aliases":["bone"]},{"emoji":"๐Ÿ“–","aliases":["book","open_book"]},{"emoji":"๐Ÿ”–","aliases":["bookmark"]},{"emoji":"๐Ÿ“‘","aliases":["bookmark_tabs"]},{"emoji":"๐Ÿ“š","aliases":["books"]},{"emoji":"๐Ÿ’ฅ","aliases":["boom","collision"]},{"emoji":"๐Ÿ‘ข","aliases":["boot"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฆ","aliases":["bosnia_herzegovina"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ผ","aliases":["botswana"]},{"emoji":"โ›น๏ธโ€โ™‚๏ธ","aliases":["bouncing_ball_man","basketball_man"]},{"emoji":"โ›น๏ธ","aliases":["bouncing_ball_person"]},{"emoji":"โ›น๏ธโ€โ™€๏ธ","aliases":["bouncing_ball_woman","basketball_woman"]},{"emoji":"๐Ÿ’","aliases":["bouquet"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ป","aliases":["bouvet_island"]},{"emoji":"๐Ÿ™‡","aliases":["bow"]},{"emoji":"๐Ÿน","aliases":["bow_and_arrow"]},{"emoji":"๐Ÿ™‡โ€โ™‚๏ธ","aliases":["bowing_man"]},{"emoji":"๐Ÿ™‡โ€โ™€๏ธ","aliases":["bowing_woman"]},{"emoji":"๐Ÿฅฃ","aliases":["bowl_with_spoon"]},{"emoji":"๐ŸŽณ","aliases":["bowling"]},{"emoji":"๐ŸฅŠ","aliases":["boxing_glove"]},{"emoji":"๐Ÿ‘ฆ","aliases":["boy"]},{"emoji":"๐Ÿง ","aliases":["brain"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ท","aliases":["brazil"]},{"emoji":"๐Ÿž","aliases":["bread"]},{"emoji":"๐Ÿคฑ","aliases":["breast_feeding"]},{"emoji":"๐Ÿงฑ","aliases":["bricks"]},{"emoji":"๐ŸŒ‰","aliases":["bridge_at_night"]},{"emoji":"๐Ÿ’ผ","aliases":["briefcase"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ด","aliases":["british_indian_ocean_territory"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡ฌ","aliases":["british_virgin_islands"]},{"emoji":"๐Ÿฅฆ","aliases":["broccoli"]},{"emoji":"๐Ÿ’”","aliases":["broken_heart"]},{"emoji":"๐Ÿงน","aliases":["broom"]},{"emoji":"๐ŸŸค","aliases":["brown_circle"]},{"emoji":"๐ŸคŽ","aliases":["brown_heart"]},{"emoji":"๐ŸŸซ","aliases":["brown_square"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ณ","aliases":["brunei"]},{"emoji":"๐Ÿ›","aliases":["bug"]},{"emoji":"๐Ÿ—๏ธ","aliases":["building_construction"]},{"emoji":"๐Ÿ’ก","aliases":["bulb"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฌ","aliases":["bulgaria"]},{"emoji":"๐Ÿš…","aliases":["bullettrain_front"]},{"emoji":"๐Ÿš„","aliases":["bullettrain_side"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ซ","aliases":["burkina_faso"]},{"emoji":"๐ŸŒฏ","aliases":["burrito"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฎ","aliases":["burundi"]},{"emoji":"๐ŸšŒ","aliases":["bus"]},{"emoji":"๐Ÿ•ด๏ธ","aliases":["business_suit_levitating"]},{"emoji":"๐Ÿš","aliases":["busstop"]},{"emoji":"๐Ÿ‘ค","aliases":["bust_in_silhouette"]},{"emoji":"๐Ÿ‘ฅ","aliases":["busts_in_silhouette"]},{"emoji":"๐Ÿงˆ","aliases":["butter"]},{"emoji":"๐Ÿฆ‹","aliases":["butterfly"]},{"emoji":"๐ŸŒต","aliases":["cactus"]},{"emoji":"๐Ÿฐ","aliases":["cake"]},{"emoji":"๐Ÿ“†","aliases":["calendar"]},{"emoji":"๐Ÿค™","aliases":["call_me_hand"]},{"emoji":"๐Ÿ“ฒ","aliases":["calling"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ญ","aliases":["cambodia"]},{"emoji":"๐Ÿซ","aliases":["camel"]},{"emoji":"๐Ÿ“ท","aliases":["camera"]},{"emoji":"๐Ÿ“ธ","aliases":["camera_flash"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฒ","aliases":["cameroon"]},{"emoji":"๐Ÿ•๏ธ","aliases":["camping"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฆ","aliases":["canada"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡จ","aliases":["canary_islands"]},{"emoji":"โ™‹","aliases":["cancer"]},{"emoji":"๐Ÿ•ฏ๏ธ","aliases":["candle"]},{"emoji":"๐Ÿฌ","aliases":["candy"]},{"emoji":"๐Ÿฅซ","aliases":["canned_food"]},{"emoji":"๐Ÿ›ถ","aliases":["canoe"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ป","aliases":["cape_verde"]},{"emoji":"๐Ÿ” ","aliases":["capital_abcd"]},{"emoji":"โ™‘","aliases":["capricorn"]},{"emoji":"๐Ÿš—","aliases":["car","red_car"]},{"emoji":"๐Ÿ—ƒ๏ธ","aliases":["card_file_box"]},{"emoji":"๐Ÿ“‡","aliases":["card_index"]},{"emoji":"๐Ÿ—‚๏ธ","aliases":["card_index_dividers"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ถ","aliases":["caribbean_netherlands"]},{"emoji":"๐ŸŽ ","aliases":["carousel_horse"]},{"emoji":"๐Ÿฅ•","aliases":["carrot"]},{"emoji":"๐Ÿคธ","aliases":["cartwheeling"]},{"emoji":"๐Ÿฑ","aliases":["cat"]},{"emoji":"๐Ÿˆ","aliases":["cat2"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡พ","aliases":["cayman_islands"]},{"emoji":"๐Ÿ’ฟ","aliases":["cd"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ซ","aliases":["central_african_republic"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ฆ","aliases":["ceuta_melilla"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฉ","aliases":["chad"]},{"emoji":"โ›“๏ธ","aliases":["chains"]},{"emoji":"๐Ÿช‘","aliases":["chair"]},{"emoji":"๐Ÿพ","aliases":["champagne"]},{"emoji":"๐Ÿ’น","aliases":["chart"]},{"emoji":"๐Ÿ“‰","aliases":["chart_with_downwards_trend"]},{"emoji":"๐Ÿ“ˆ","aliases":["chart_with_upwards_trend"]},{"emoji":"๐Ÿ","aliases":["checkered_flag"]},{"emoji":"๐Ÿง€","aliases":["cheese"]},{"emoji":"๐Ÿ’","aliases":["cherries"]},{"emoji":"๐ŸŒธ","aliases":["cherry_blossom"]},{"emoji":"โ™Ÿ๏ธ","aliases":["chess_pawn"]},{"emoji":"๐ŸŒฐ","aliases":["chestnut"]},{"emoji":"๐Ÿ”","aliases":["chicken"]},{"emoji":"๐Ÿง’","aliases":["child"]},{"emoji":"๐Ÿšธ","aliases":["children_crossing"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฑ","aliases":["chile"]},{"emoji":"๐Ÿฟ๏ธ","aliases":["chipmunk"]},{"emoji":"๐Ÿซ","aliases":["chocolate_bar"]},{"emoji":"๐Ÿฅข","aliases":["chopsticks"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฝ","aliases":["christmas_island"]},{"emoji":"๐ŸŽ„","aliases":["christmas_tree"]},{"emoji":"โ›ช","aliases":["church"]},{"emoji":"๐ŸŽฆ","aliases":["cinema"]},{"emoji":"๐ŸŽช","aliases":["circus_tent"]},{"emoji":"๐ŸŒ‡","aliases":["city_sunrise"]},{"emoji":"๐ŸŒ†","aliases":["city_sunset"]},{"emoji":"๐Ÿ™๏ธ","aliases":["cityscape"]},{"emoji":"๐Ÿ†‘","aliases":["cl"]},{"emoji":"๐Ÿ—œ๏ธ","aliases":["clamp"]},{"emoji":"๐Ÿ‘","aliases":["clap"]},{"emoji":"๐ŸŽฌ","aliases":["clapper"]},{"emoji":"๐Ÿ›๏ธ","aliases":["classical_building"]},{"emoji":"๐Ÿง—","aliases":["climbing"]},{"emoji":"๐Ÿง—โ€โ™‚๏ธ","aliases":["climbing_man"]},{"emoji":"๐Ÿง—โ€โ™€๏ธ","aliases":["climbing_woman"]},{"emoji":"๐Ÿฅ‚","aliases":["clinking_glasses"]},{"emoji":"๐Ÿ“‹","aliases":["clipboard"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ต","aliases":["clipperton_island"]},{"emoji":"๐Ÿ•","aliases":["clock1"]},{"emoji":"๐Ÿ•™","aliases":["clock10"]},{"emoji":"๐Ÿ•ฅ","aliases":["clock1030"]},{"emoji":"๐Ÿ•š","aliases":["clock11"]},{"emoji":"๐Ÿ•ฆ","aliases":["clock1130"]},{"emoji":"๐Ÿ•›","aliases":["clock12"]},{"emoji":"๐Ÿ•ง","aliases":["clock1230"]},{"emoji":"๐Ÿ•œ","aliases":["clock130"]},{"emoji":"๐Ÿ•‘","aliases":["clock2"]},{"emoji":"๐Ÿ•","aliases":["clock230"]},{"emoji":"๐Ÿ•’","aliases":["clock3"]},{"emoji":"๐Ÿ•ž","aliases":["clock330"]},{"emoji":"๐Ÿ•“","aliases":["clock4"]},{"emoji":"๐Ÿ•Ÿ","aliases":["clock430"]},{"emoji":"๐Ÿ•”","aliases":["clock5"]},{"emoji":"๐Ÿ• ","aliases":["clock530"]},{"emoji":"๐Ÿ••","aliases":["clock6"]},{"emoji":"๐Ÿ•ก","aliases":["clock630"]},{"emoji":"๐Ÿ•–","aliases":["clock7"]},{"emoji":"๐Ÿ•ข","aliases":["clock730"]},{"emoji":"๐Ÿ•—","aliases":["clock8"]},{"emoji":"๐Ÿ•ฃ","aliases":["clock830"]},{"emoji":"๐Ÿ•˜","aliases":["clock9"]},{"emoji":"๐Ÿ•ค","aliases":["clock930"]},{"emoji":"๐Ÿ“•","aliases":["closed_book"]},{"emoji":"๐Ÿ”","aliases":["closed_lock_with_key"]},{"emoji":"๐ŸŒ‚","aliases":["closed_umbrella"]},{"emoji":"โ˜๏ธ","aliases":["cloud"]},{"emoji":"๐ŸŒฉ๏ธ","aliases":["cloud_with_lightning"]},{"emoji":"โ›ˆ๏ธ","aliases":["cloud_with_lightning_and_rain"]},{"emoji":"๐ŸŒง๏ธ","aliases":["cloud_with_rain"]},{"emoji":"๐ŸŒจ๏ธ","aliases":["cloud_with_snow"]},{"emoji":"๐Ÿคก","aliases":["clown_face"]},{"emoji":"โ™ฃ๏ธ","aliases":["clubs"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ณ","aliases":["cn"]},{"emoji":"๐Ÿงฅ","aliases":["coat"]},{"emoji":"๐Ÿธ","aliases":["cocktail"]},{"emoji":"๐Ÿฅฅ","aliases":["coconut"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡จ","aliases":["cocos_islands"]},{"emoji":"โ˜•","aliases":["coffee"]},{"emoji":"โšฐ๏ธ","aliases":["coffin"]},{"emoji":"๐Ÿฅถ","aliases":["cold_face"]},{"emoji":"๐Ÿ˜ฐ","aliases":["cold_sweat"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ด","aliases":["colombia"]},{"emoji":"โ˜„๏ธ","aliases":["comet"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ฒ","aliases":["comoros"]},{"emoji":"๐Ÿงญ","aliases":["compass"]},{"emoji":"๐Ÿ’ป","aliases":["computer"]},{"emoji":"๐Ÿ–ฑ๏ธ","aliases":["computer_mouse"]},{"emoji":"๐ŸŽŠ","aliases":["confetti_ball"]},{"emoji":"๐Ÿ˜–","aliases":["confounded"]},{"emoji":"๐Ÿ˜•","aliases":["confused"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฌ","aliases":["congo_brazzaville"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฉ","aliases":["congo_kinshasa"]},{"emoji":"ใŠ—๏ธ","aliases":["congratulations"]},{"emoji":"๐Ÿšง","aliases":["construction"]},{"emoji":"๐Ÿ‘ท","aliases":["construction_worker"]},{"emoji":"๐Ÿ‘ทโ€โ™‚๏ธ","aliases":["construction_worker_man"]},{"emoji":"๐Ÿ‘ทโ€โ™€๏ธ","aliases":["construction_worker_woman"]},{"emoji":"๐ŸŽ›๏ธ","aliases":["control_knobs"]},{"emoji":"๐Ÿช","aliases":["convenience_store"]},{"emoji":"๐Ÿง‘โ€๐Ÿณ","aliases":["cook"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฐ","aliases":["cook_islands"]},{"emoji":"๐Ÿช","aliases":["cookie"]},{"emoji":"๐Ÿ†’","aliases":["cool"]},{"emoji":"ยฉ๏ธ","aliases":["copyright"]},{"emoji":"๐ŸŒฝ","aliases":["corn"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ท","aliases":["costa_rica"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฎ","aliases":["cote_divoire"]},{"emoji":"๐Ÿ›‹๏ธ","aliases":["couch_and_lamp"]},{"emoji":"๐Ÿ‘ซ","aliases":["couple"]},{"emoji":"๐Ÿ’‘","aliases":["couple_with_heart"]},{"emoji":"๐Ÿ‘จโ€โค๏ธโ€๐Ÿ‘จ","aliases":["couple_with_heart_man_man"]},{"emoji":"๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘จ","aliases":["couple_with_heart_woman_man"]},{"emoji":"๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘ฉ","aliases":["couple_with_heart_woman_woman"]},{"emoji":"๐Ÿ’","aliases":["couplekiss"]},{"emoji":"๐Ÿ‘จโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ","aliases":["couplekiss_man_man"]},{"emoji":"๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ","aliases":["couplekiss_man_woman"]},{"emoji":"๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘ฉ","aliases":["couplekiss_woman_woman"]},{"emoji":"๐Ÿฎ","aliases":["cow"]},{"emoji":"๐Ÿ„","aliases":["cow2"]},{"emoji":"๐Ÿค ","aliases":["cowboy_hat_face"]},{"emoji":"๐Ÿฆ€","aliases":["crab"]},{"emoji":"๐Ÿ–๏ธ","aliases":["crayon"]},{"emoji":"๐Ÿ’ณ","aliases":["credit_card"]},{"emoji":"๐ŸŒ™","aliases":["crescent_moon"]},{"emoji":"๐Ÿฆ—","aliases":["cricket"]},{"emoji":"๐Ÿ","aliases":["cricket_game"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡ท","aliases":["croatia"]},{"emoji":"๐ŸŠ","aliases":["crocodile"]},{"emoji":"๐Ÿฅ","aliases":["croissant"]},{"emoji":"๐Ÿคž","aliases":["crossed_fingers"]},{"emoji":"๐ŸŽŒ","aliases":["crossed_flags"]},{"emoji":"โš”๏ธ","aliases":["crossed_swords"]},{"emoji":"๐Ÿ‘‘","aliases":["crown"]},{"emoji":"๐Ÿ˜ข","aliases":["cry"]},{"emoji":"๐Ÿ˜ฟ","aliases":["crying_cat_face"]},{"emoji":"๐Ÿ”ฎ","aliases":["crystal_ball"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡บ","aliases":["cuba"]},{"emoji":"๐Ÿฅ’","aliases":["cucumber"]},{"emoji":"๐Ÿฅค","aliases":["cup_with_straw"]},{"emoji":"๐Ÿง","aliases":["cupcake"]},{"emoji":"๐Ÿ’˜","aliases":["cupid"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ผ","aliases":["curacao"]},{"emoji":"๐ŸฅŒ","aliases":["curling_stone"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆฑ","aliases":["curly_haired_man"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆฑ","aliases":["curly_haired_woman"]},{"emoji":"โžฐ","aliases":["curly_loop"]},{"emoji":"๐Ÿ’ฑ","aliases":["currency_exchange"]},{"emoji":"๐Ÿ›","aliases":["curry"]},{"emoji":"๐Ÿคฌ","aliases":["cursing_face"]},{"emoji":"๐Ÿฎ","aliases":["custard"]},{"emoji":"๐Ÿ›ƒ","aliases":["customs"]},{"emoji":"๐Ÿฅฉ","aliases":["cut_of_meat"]},{"emoji":"๐ŸŒ€","aliases":["cyclone"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡พ","aliases":["cyprus"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ฟ","aliases":["czech_republic"]},{"emoji":"๐Ÿ—ก๏ธ","aliases":["dagger"]},{"emoji":"๐Ÿ‘ฏ","aliases":["dancers"]},{"emoji":"๐Ÿ‘ฏโ€โ™‚๏ธ","aliases":["dancing_men"]},{"emoji":"๐Ÿ‘ฏโ€โ™€๏ธ","aliases":["dancing_women"]},{"emoji":"๐Ÿก","aliases":["dango"]},{"emoji":"๐Ÿ•ถ๏ธ","aliases":["dark_sunglasses"]},{"emoji":"๐ŸŽฏ","aliases":["dart"]},{"emoji":"๐Ÿ’จ","aliases":["dash"]},{"emoji":"๐Ÿ“…","aliases":["date"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ช","aliases":["de"]},{"emoji":"๐Ÿงโ€โ™‚๏ธ","aliases":["deaf_man"]},{"emoji":"๐Ÿง","aliases":["deaf_person"]},{"emoji":"๐Ÿงโ€โ™€๏ธ","aliases":["deaf_woman"]},{"emoji":"๐ŸŒณ","aliases":["deciduous_tree"]},{"emoji":"๐ŸฆŒ","aliases":["deer"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ฐ","aliases":["denmark"]},{"emoji":"๐Ÿฌ","aliases":["department_store"]},{"emoji":"๐Ÿš๏ธ","aliases":["derelict_house"]},{"emoji":"๐Ÿœ๏ธ","aliases":["desert"]},{"emoji":"๐Ÿ๏ธ","aliases":["desert_island"]},{"emoji":"๐Ÿ–ฅ๏ธ","aliases":["desktop_computer"]},{"emoji":"๐Ÿ•ต๏ธ","aliases":["detective"]},{"emoji":"๐Ÿ’ ","aliases":["diamond_shape_with_a_dot_inside"]},{"emoji":"โ™ฆ๏ธ","aliases":["diamonds"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ฌ","aliases":["diego_garcia"]},{"emoji":"๐Ÿ˜ž","aliases":["disappointed"]},{"emoji":"๐Ÿ˜ฅ","aliases":["disappointed_relieved"]},{"emoji":"๐Ÿคฟ","aliases":["diving_mask"]},{"emoji":"๐Ÿช”","aliases":["diya_lamp"]},{"emoji":"๐Ÿ’ซ","aliases":["dizzy"]},{"emoji":"๐Ÿ˜ต","aliases":["dizzy_face"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ฏ","aliases":["djibouti"]},{"emoji":"๐Ÿงฌ","aliases":["dna"]},{"emoji":"๐Ÿšฏ","aliases":["do_not_litter"]},{"emoji":"๐Ÿถ","aliases":["dog"]},{"emoji":"๐Ÿ•","aliases":["dog2"]},{"emoji":"๐Ÿ’ต","aliases":["dollar"]},{"emoji":"๐ŸŽŽ","aliases":["dolls"]},{"emoji":"๐Ÿฌ","aliases":["dolphin","flipper"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ฒ","aliases":["dominica"]},{"emoji":"๐Ÿ‡ฉ๐Ÿ‡ด","aliases":["dominican_republic"]},{"emoji":"๐Ÿšช","aliases":["door"]},{"emoji":"๐Ÿฉ","aliases":["doughnut"]},{"emoji":"๐Ÿ•Š๏ธ","aliases":["dove"]},{"emoji":"๐Ÿ‰","aliases":["dragon"]},{"emoji":"๐Ÿฒ","aliases":["dragon_face"]},{"emoji":"๐Ÿ‘—","aliases":["dress"]},{"emoji":"๐Ÿช","aliases":["dromedary_camel"]},{"emoji":"๐Ÿคค","aliases":["drooling_face"]},{"emoji":"๐Ÿฉธ","aliases":["drop_of_blood"]},{"emoji":"๐Ÿ’ง","aliases":["droplet"]},{"emoji":"๐Ÿฅ","aliases":["drum"]},{"emoji":"๐Ÿฆ†","aliases":["duck"]},{"emoji":"๐ŸฅŸ","aliases":["dumpling"]},{"emoji":"๐Ÿ“€","aliases":["dvd"]},{"emoji":"๐Ÿ“ง","aliases":["e-mail"]},{"emoji":"๐Ÿฆ…","aliases":["eagle"]},{"emoji":"๐Ÿ‘‚","aliases":["ear"]},{"emoji":"๐ŸŒพ","aliases":["ear_of_rice"]},{"emoji":"๐Ÿฆป","aliases":["ear_with_hearing_aid"]},{"emoji":"๐ŸŒ","aliases":["earth_africa"]},{"emoji":"๐ŸŒŽ","aliases":["earth_americas"]},{"emoji":"๐ŸŒ","aliases":["earth_asia"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡จ","aliases":["ecuador"]},{"emoji":"๐Ÿฅš","aliases":["egg"]},{"emoji":"๐Ÿ†","aliases":["eggplant"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ฌ","aliases":["egypt"]},{"emoji":"8๏ธโƒฃ","aliases":["eight"]},{"emoji":"โœด๏ธ","aliases":["eight_pointed_black_star"]},{"emoji":"โœณ๏ธ","aliases":["eight_spoked_asterisk"]},{"emoji":"โ๏ธ","aliases":["eject_button"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ป","aliases":["el_salvador"]},{"emoji":"๐Ÿ”Œ","aliases":["electric_plug"]},{"emoji":"๐Ÿ˜","aliases":["elephant"]},{"emoji":"๐Ÿง","aliases":["elf"]},{"emoji":"๐Ÿงโ€โ™‚๏ธ","aliases":["elf_man"]},{"emoji":"๐Ÿงโ€โ™€๏ธ","aliases":["elf_woman"]},{"emoji":"โœ‰๏ธ","aliases":["email","envelope"]},{"emoji":"๐Ÿ”š","aliases":["end"]},{"emoji":"๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ","aliases":["england"]},{"emoji":"๐Ÿ“ฉ","aliases":["envelope_with_arrow"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ถ","aliases":["equatorial_guinea"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ท","aliases":["eritrea"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ธ","aliases":["es"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ช","aliases":["estonia"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡น","aliases":["ethiopia"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡บ","aliases":["eu","european_union"]},{"emoji":"๐Ÿ’ถ","aliases":["euro"]},{"emoji":"๐Ÿฐ","aliases":["european_castle"]},{"emoji":"๐Ÿค","aliases":["european_post_office"]},{"emoji":"๐ŸŒฒ","aliases":["evergreen_tree"]},{"emoji":"โ—","aliases":["exclamation","heavy_exclamation_mark"]},{"emoji":"๐Ÿคฏ","aliases":["exploding_head"]},{"emoji":"๐Ÿ˜‘","aliases":["expressionless"]},{"emoji":"๐Ÿ‘๏ธ","aliases":["eye"]},{"emoji":"๐Ÿ‘๏ธโ€๐Ÿ—จ๏ธ","aliases":["eye_speech_bubble"]},{"emoji":"๐Ÿ‘“","aliases":["eyeglasses"]},{"emoji":"๐Ÿ‘€","aliases":["eyes"]},{"emoji":"๐Ÿค•","aliases":["face_with_head_bandage"]},{"emoji":"๐Ÿค’","aliases":["face_with_thermometer"]},{"emoji":"๐Ÿคฆ","aliases":["facepalm"]},{"emoji":"๐Ÿญ","aliases":["factory"]},{"emoji":"๐Ÿง‘โ€๐Ÿญ","aliases":["factory_worker"]},{"emoji":"๐Ÿงš","aliases":["fairy"]},{"emoji":"๐Ÿงšโ€โ™‚๏ธ","aliases":["fairy_man"]},{"emoji":"๐Ÿงšโ€โ™€๏ธ","aliases":["fairy_woman"]},{"emoji":"๐Ÿง†","aliases":["falafel"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ฐ","aliases":["falkland_islands"]},{"emoji":"๐Ÿ‚","aliases":["fallen_leaf"]},{"emoji":"๐Ÿ‘ช","aliases":["family"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฆ","aliases":["family_man_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","aliases":["family_man_boy_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ง","aliases":["family_man_girl"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","aliases":["family_man_girl_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง","aliases":["family_man_girl_girl"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆ","aliases":["family_man_man_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","aliases":["family_man_man_boy_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ง","aliases":["family_man_man_girl"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","aliases":["family_man_man_girl_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง","aliases":["family_man_man_girl_girl"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ","aliases":["family_man_woman_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","aliases":["family_man_woman_boy_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง","aliases":["family_man_woman_girl"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","aliases":["family_man_woman_girl_boy"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง","aliases":["family_man_woman_girl_girl"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฆ","aliases":["family_woman_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","aliases":["family_woman_boy_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ง","aliases":["family_woman_girl"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","aliases":["family_woman_girl_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง","aliases":["family_woman_girl_girl"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ","aliases":["family_woman_woman_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ","aliases":["family_woman_woman_boy_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง","aliases":["family_woman_woman_girl"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ","aliases":["family_woman_woman_girl_boy"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง","aliases":["family_woman_woman_girl_girl"]},{"emoji":"๐Ÿง‘โ€๐ŸŒพ","aliases":["farmer"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ด","aliases":["faroe_islands"]},{"emoji":"โฉ","aliases":["fast_forward"]},{"emoji":"๐Ÿ“ ","aliases":["fax"]},{"emoji":"๐Ÿ˜จ","aliases":["fearful"]},{"emoji":"๐Ÿพ","aliases":["feet","paw_prints"]},{"emoji":"๐Ÿ•ต๏ธโ€โ™€๏ธ","aliases":["female_detective"]},{"emoji":"โ™€๏ธ","aliases":["female_sign"]},{"emoji":"๐ŸŽก","aliases":["ferris_wheel"]},{"emoji":"โ›ด๏ธ","aliases":["ferry"]},{"emoji":"๐Ÿ‘","aliases":["field_hockey"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ฏ","aliases":["fiji"]},{"emoji":"๐Ÿ—„๏ธ","aliases":["file_cabinet"]},{"emoji":"๐Ÿ“","aliases":["file_folder"]},{"emoji":"๐Ÿ“ฝ๏ธ","aliases":["film_projector"]},{"emoji":"๐ŸŽž๏ธ","aliases":["film_strip"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ฎ","aliases":["finland"]},{"emoji":"๐Ÿ”ฅ","aliases":["fire"]},{"emoji":"๐Ÿš’","aliases":["fire_engine"]},{"emoji":"๐Ÿงฏ","aliases":["fire_extinguisher"]},{"emoji":"๐Ÿงจ","aliases":["firecracker"]},{"emoji":"๐Ÿง‘โ€๐Ÿš’","aliases":["firefighter"]},{"emoji":"๐ŸŽ†","aliases":["fireworks"]},{"emoji":"๐ŸŒ“","aliases":["first_quarter_moon"]},{"emoji":"๐ŸŒ›","aliases":["first_quarter_moon_with_face"]},{"emoji":"๐ŸŸ","aliases":["fish"]},{"emoji":"๐Ÿฅ","aliases":["fish_cake"]},{"emoji":"๐ŸŽฃ","aliases":["fishing_pole_and_fish"]},{"emoji":"๐Ÿค›","aliases":["fist_left"]},{"emoji":"๐Ÿ‘Š","aliases":["fist_oncoming","facepunch","punch"]},{"emoji":"โœŠ","aliases":["fist_raised","fist"]},{"emoji":"๐Ÿคœ","aliases":["fist_right"]},{"emoji":"5๏ธโƒฃ","aliases":["five"]},{"emoji":"๐ŸŽ","aliases":["flags"]},{"emoji":"๐Ÿฆฉ","aliases":["flamingo"]},{"emoji":"๐Ÿ”ฆ","aliases":["flashlight"]},{"emoji":"๐Ÿฅฟ","aliases":["flat_shoe"]},{"emoji":"โšœ๏ธ","aliases":["fleur_de_lis"]},{"emoji":"๐Ÿ›ฌ","aliases":["flight_arrival"]},{"emoji":"๐Ÿ›ซ","aliases":["flight_departure"]},{"emoji":"๐Ÿ’พ","aliases":["floppy_disk"]},{"emoji":"๐ŸŽด","aliases":["flower_playing_cards"]},{"emoji":"๐Ÿ˜ณ","aliases":["flushed"]},{"emoji":"๐Ÿฅ","aliases":["flying_disc"]},{"emoji":"๐Ÿ›ธ","aliases":["flying_saucer"]},{"emoji":"๐ŸŒซ๏ธ","aliases":["fog"]},{"emoji":"๐ŸŒ","aliases":["foggy"]},{"emoji":"๐Ÿฆถ","aliases":["foot"]},{"emoji":"๐Ÿˆ","aliases":["football"]},{"emoji":"๐Ÿ‘ฃ","aliases":["footprints"]},{"emoji":"๐Ÿด","aliases":["fork_and_knife"]},{"emoji":"๐Ÿฅ ","aliases":["fortune_cookie"]},{"emoji":"โ›ฒ","aliases":["fountain"]},{"emoji":"๐Ÿ–‹๏ธ","aliases":["fountain_pen"]},{"emoji":"4๏ธโƒฃ","aliases":["four"]},{"emoji":"๐Ÿ€","aliases":["four_leaf_clover"]},{"emoji":"๐ŸฆŠ","aliases":["fox_face"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ท","aliases":["fr"]},{"emoji":"๐Ÿ–ผ๏ธ","aliases":["framed_picture"]},{"emoji":"๐Ÿ†“","aliases":["free"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ซ","aliases":["french_guiana"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ซ","aliases":["french_polynesia"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ซ","aliases":["french_southern_territories"]},{"emoji":"๐Ÿณ","aliases":["fried_egg"]},{"emoji":"๐Ÿค","aliases":["fried_shrimp"]},{"emoji":"๐ŸŸ","aliases":["fries"]},{"emoji":"๐Ÿธ","aliases":["frog"]},{"emoji":"๐Ÿ˜ฆ","aliases":["frowning"]},{"emoji":"โ˜น๏ธ","aliases":["frowning_face"]},{"emoji":"๐Ÿ™โ€โ™‚๏ธ","aliases":["frowning_man"]},{"emoji":"๐Ÿ™","aliases":["frowning_person"]},{"emoji":"๐Ÿ™โ€โ™€๏ธ","aliases":["frowning_woman"]},{"emoji":"โ›ฝ","aliases":["fuelpump"]},{"emoji":"๐ŸŒ•","aliases":["full_moon"]},{"emoji":"๐ŸŒ","aliases":["full_moon_with_face"]},{"emoji":"โšฑ๏ธ","aliases":["funeral_urn"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฆ","aliases":["gabon"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฒ","aliases":["gambia"]},{"emoji":"๐ŸŽฒ","aliases":["game_die"]},{"emoji":"๐Ÿง„","aliases":["garlic"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ง","aliases":["gb","uk"]},{"emoji":"โš™๏ธ","aliases":["gear"]},{"emoji":"๐Ÿ’Ž","aliases":["gem"]},{"emoji":"โ™Š","aliases":["gemini"]},{"emoji":"๐Ÿงž","aliases":["genie"]},{"emoji":"๐Ÿงžโ€โ™‚๏ธ","aliases":["genie_man"]},{"emoji":"๐Ÿงžโ€โ™€๏ธ","aliases":["genie_woman"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ช","aliases":["georgia"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ญ","aliases":["ghana"]},{"emoji":"๐Ÿ‘ป","aliases":["ghost"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฎ","aliases":["gibraltar"]},{"emoji":"๐ŸŽ","aliases":["gift"]},{"emoji":"๐Ÿ’","aliases":["gift_heart"]},{"emoji":"๐Ÿฆ’","aliases":["giraffe"]},{"emoji":"๐Ÿ‘ง","aliases":["girl"]},{"emoji":"๐ŸŒ","aliases":["globe_with_meridians"]},{"emoji":"๐Ÿงค","aliases":["gloves"]},{"emoji":"๐Ÿฅ…","aliases":["goal_net"]},{"emoji":"๐Ÿ","aliases":["goat"]},{"emoji":"๐Ÿฅฝ","aliases":["goggles"]},{"emoji":"โ›ณ","aliases":["golf"]},{"emoji":"๐ŸŒ๏ธ","aliases":["golfing"]},{"emoji":"๐ŸŒ๏ธโ€โ™‚๏ธ","aliases":["golfing_man"]},{"emoji":"๐ŸŒ๏ธโ€โ™€๏ธ","aliases":["golfing_woman"]},{"emoji":"๐Ÿฆ","aliases":["gorilla"]},{"emoji":"๐Ÿ‡","aliases":["grapes"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ท","aliases":["greece"]},{"emoji":"๐Ÿ","aliases":["green_apple"]},{"emoji":"๐Ÿ“—","aliases":["green_book"]},{"emoji":"๐ŸŸข","aliases":["green_circle"]},{"emoji":"๐Ÿ’š","aliases":["green_heart"]},{"emoji":"๐Ÿฅ—","aliases":["green_salad"]},{"emoji":"๐ŸŸฉ","aliases":["green_square"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฑ","aliases":["greenland"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฉ","aliases":["grenada"]},{"emoji":"โ•","aliases":["grey_exclamation"]},{"emoji":"โ”","aliases":["grey_question"]},{"emoji":"๐Ÿ˜ฌ","aliases":["grimacing"]},{"emoji":"๐Ÿ˜","aliases":["grin"]},{"emoji":"๐Ÿ˜€","aliases":["grinning"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ต","aliases":["guadeloupe"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡บ","aliases":["guam"]},{"emoji":"๐Ÿ’‚","aliases":["guard"]},{"emoji":"๐Ÿ’‚โ€โ™‚๏ธ","aliases":["guardsman"]},{"emoji":"๐Ÿ’‚โ€โ™€๏ธ","aliases":["guardswoman"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡น","aliases":["guatemala"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ฌ","aliases":["guernsey"]},{"emoji":"๐Ÿฆฎ","aliases":["guide_dog"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ณ","aliases":["guinea"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ผ","aliases":["guinea_bissau"]},{"emoji":"๐ŸŽธ","aliases":["guitar"]},{"emoji":"๐Ÿ”ซ","aliases":["gun"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡พ","aliases":["guyana"]},{"emoji":"๐Ÿ’‡","aliases":["haircut"]},{"emoji":"๐Ÿ’‡โ€โ™‚๏ธ","aliases":["haircut_man"]},{"emoji":"๐Ÿ’‡โ€โ™€๏ธ","aliases":["haircut_woman"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡น","aliases":["haiti"]},{"emoji":"๐Ÿ”","aliases":["hamburger"]},{"emoji":"๐Ÿ”จ","aliases":["hammer"]},{"emoji":"โš’๏ธ","aliases":["hammer_and_pick"]},{"emoji":"๐Ÿ› ๏ธ","aliases":["hammer_and_wrench"]},{"emoji":"๐Ÿน","aliases":["hamster"]},{"emoji":"โœ‹","aliases":["hand","raised_hand"]},{"emoji":"๐Ÿคญ","aliases":["hand_over_mouth"]},{"emoji":"๐Ÿ‘œ","aliases":["handbag"]},{"emoji":"๐Ÿคพ","aliases":["handball_person"]},{"emoji":"๐Ÿค","aliases":["handshake"]},{"emoji":"๐Ÿ’ฉ","aliases":["hankey","poop","shit"]},{"emoji":"#๏ธโƒฃ","aliases":["hash"]},{"emoji":"๐Ÿฅ","aliases":["hatched_chick"]},{"emoji":"๐Ÿฃ","aliases":["hatching_chick"]},{"emoji":"๐ŸŽง","aliases":["headphones"]},{"emoji":"๐Ÿง‘โ€โš•๏ธ","aliases":["health_worker"]},{"emoji":"๐Ÿ™‰","aliases":["hear_no_evil"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡ฒ","aliases":["heard_mcdonald_islands"]},{"emoji":"โค๏ธ","aliases":["heart"]},{"emoji":"๐Ÿ’Ÿ","aliases":["heart_decoration"]},{"emoji":"๐Ÿ˜","aliases":["heart_eyes"]},{"emoji":"๐Ÿ˜ป","aliases":["heart_eyes_cat"]},{"emoji":"๐Ÿ’“","aliases":["heartbeat"]},{"emoji":"๐Ÿ’—","aliases":["heartpulse"]},{"emoji":"โ™ฅ๏ธ","aliases":["hearts"]},{"emoji":"โœ”๏ธ","aliases":["heavy_check_mark"]},{"emoji":"โž—","aliases":["heavy_division_sign"]},{"emoji":"๐Ÿ’ฒ","aliases":["heavy_dollar_sign"]},{"emoji":"โฃ๏ธ","aliases":["heavy_heart_exclamation"]},{"emoji":"โž–","aliases":["heavy_minus_sign"]},{"emoji":"โœ–๏ธ","aliases":["heavy_multiplication_x"]},{"emoji":"โž•","aliases":["heavy_plus_sign"]},{"emoji":"๐Ÿฆ”","aliases":["hedgehog"]},{"emoji":"๐Ÿš","aliases":["helicopter"]},{"emoji":"๐ŸŒฟ","aliases":["herb"]},{"emoji":"๐ŸŒบ","aliases":["hibiscus"]},{"emoji":"๐Ÿ”†","aliases":["high_brightness"]},{"emoji":"๐Ÿ‘ ","aliases":["high_heel"]},{"emoji":"๐Ÿฅพ","aliases":["hiking_boot"]},{"emoji":"๐Ÿ›•","aliases":["hindu_temple"]},{"emoji":"๐Ÿฆ›","aliases":["hippopotamus"]},{"emoji":"๐Ÿ”ช","aliases":["hocho","knife"]},{"emoji":"๐Ÿ•ณ๏ธ","aliases":["hole"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡ณ","aliases":["honduras"]},{"emoji":"๐Ÿฏ","aliases":["honey_pot"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡ฐ","aliases":["hong_kong"]},{"emoji":"๐Ÿด","aliases":["horse"]},{"emoji":"๐Ÿ‡","aliases":["horse_racing"]},{"emoji":"๐Ÿฅ","aliases":["hospital"]},{"emoji":"๐Ÿฅต","aliases":["hot_face"]},{"emoji":"๐ŸŒถ๏ธ","aliases":["hot_pepper"]},{"emoji":"๐ŸŒญ","aliases":["hotdog"]},{"emoji":"๐Ÿจ","aliases":["hotel"]},{"emoji":"โ™จ๏ธ","aliases":["hotsprings"]},{"emoji":"โŒ›","aliases":["hourglass"]},{"emoji":"โณ","aliases":["hourglass_flowing_sand"]},{"emoji":"๐Ÿ ","aliases":["house"]},{"emoji":"๐Ÿก","aliases":["house_with_garden"]},{"emoji":"๐Ÿ˜๏ธ","aliases":["houses"]},{"emoji":"๐Ÿค—","aliases":["hugs"]},{"emoji":"๐Ÿ‡ญ๐Ÿ‡บ","aliases":["hungary"]},{"emoji":"๐Ÿ˜ฏ","aliases":["hushed"]},{"emoji":"๐Ÿจ","aliases":["ice_cream"]},{"emoji":"๐ŸงŠ","aliases":["ice_cube"]},{"emoji":"๐Ÿ’","aliases":["ice_hockey"]},{"emoji":"โ›ธ๏ธ","aliases":["ice_skate"]},{"emoji":"๐Ÿฆ","aliases":["icecream"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ธ","aliases":["iceland"]},{"emoji":"๐Ÿ†”","aliases":["id"]},{"emoji":"๐Ÿ‰","aliases":["ideograph_advantage"]},{"emoji":"๐Ÿ‘ฟ","aliases":["imp"]},{"emoji":"๐Ÿ“ฅ","aliases":["inbox_tray"]},{"emoji":"๐Ÿ“จ","aliases":["incoming_envelope"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ณ","aliases":["india"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ฉ","aliases":["indonesia"]},{"emoji":"โ™พ๏ธ","aliases":["infinity"]},{"emoji":"โ„น๏ธ","aliases":["information_source"]},{"emoji":"๐Ÿ˜‡","aliases":["innocent"]},{"emoji":"โ‰๏ธ","aliases":["interrobang"]},{"emoji":"๐Ÿ“ฑ","aliases":["iphone"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ท","aliases":["iran"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ถ","aliases":["iraq"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ช","aliases":["ireland"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ฒ","aliases":["isle_of_man"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡ฑ","aliases":["israel"]},{"emoji":"๐Ÿ‡ฎ๐Ÿ‡น","aliases":["it"]},{"emoji":"๐Ÿฎ","aliases":["izakaya_lantern","lantern"]},{"emoji":"๐ŸŽƒ","aliases":["jack_o_lantern"]},{"emoji":"๐Ÿ‡ฏ๐Ÿ‡ฒ","aliases":["jamaica"]},{"emoji":"๐Ÿ—พ","aliases":["japan"]},{"emoji":"๐Ÿฏ","aliases":["japanese_castle"]},{"emoji":"๐Ÿ‘บ","aliases":["japanese_goblin"]},{"emoji":"๐Ÿ‘น","aliases":["japanese_ogre"]},{"emoji":"๐Ÿ‘–","aliases":["jeans"]},{"emoji":"๐Ÿ‡ฏ๐Ÿ‡ช","aliases":["jersey"]},{"emoji":"๐Ÿงฉ","aliases":["jigsaw"]},{"emoji":"๐Ÿ‡ฏ๐Ÿ‡ด","aliases":["jordan"]},{"emoji":"๐Ÿ˜‚","aliases":["joy"]},{"emoji":"๐Ÿ˜น","aliases":["joy_cat"]},{"emoji":"๐Ÿ•น๏ธ","aliases":["joystick"]},{"emoji":"๐Ÿ‡ฏ๐Ÿ‡ต","aliases":["jp"]},{"emoji":"๐Ÿง‘โ€โš–๏ธ","aliases":["judge"]},{"emoji":"๐Ÿคน","aliases":["juggling_person"]},{"emoji":"๐Ÿ•‹","aliases":["kaaba"]},{"emoji":"๐Ÿฆ˜","aliases":["kangaroo"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ฟ","aliases":["kazakhstan"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ช","aliases":["kenya"]},{"emoji":"๐Ÿ”‘","aliases":["key"]},{"emoji":"โŒจ๏ธ","aliases":["keyboard"]},{"emoji":"๐Ÿ”Ÿ","aliases":["keycap_ten"]},{"emoji":"๐Ÿ›ด","aliases":["kick_scooter"]},{"emoji":"๐Ÿ‘˜","aliases":["kimono"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ฎ","aliases":["kiribati"]},{"emoji":"๐Ÿ’‹","aliases":["kiss"]},{"emoji":"๐Ÿ˜—","aliases":["kissing"]},{"emoji":"๐Ÿ˜ฝ","aliases":["kissing_cat"]},{"emoji":"๐Ÿ˜š","aliases":["kissing_closed_eyes"]},{"emoji":"๐Ÿ˜˜","aliases":["kissing_heart"]},{"emoji":"๐Ÿ˜™","aliases":["kissing_smiling_eyes"]},{"emoji":"๐Ÿช","aliases":["kite"]},{"emoji":"๐Ÿฅ","aliases":["kiwi_fruit"]},{"emoji":"๐ŸงŽโ€โ™‚๏ธ","aliases":["kneeling_man"]},{"emoji":"๐ŸงŽ","aliases":["kneeling_person"]},{"emoji":"๐ŸงŽโ€โ™€๏ธ","aliases":["kneeling_woman"]},{"emoji":"๐Ÿจ","aliases":["koala"]},{"emoji":"๐Ÿˆ","aliases":["koko"]},{"emoji":"๐Ÿ‡ฝ๐Ÿ‡ฐ","aliases":["kosovo"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ท","aliases":["kr"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ผ","aliases":["kuwait"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ฌ","aliases":["kyrgyzstan"]},{"emoji":"๐Ÿฅผ","aliases":["lab_coat"]},{"emoji":"๐Ÿท๏ธ","aliases":["label"]},{"emoji":"๐Ÿฅ","aliases":["lacrosse"]},{"emoji":"๐Ÿž","aliases":["lady_beetle"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ฆ","aliases":["laos"]},{"emoji":"๐Ÿ”ต","aliases":["large_blue_circle"]},{"emoji":"๐Ÿ”ท","aliases":["large_blue_diamond"]},{"emoji":"๐Ÿ”ถ","aliases":["large_orange_diamond"]},{"emoji":"๐ŸŒ—","aliases":["last_quarter_moon"]},{"emoji":"๐ŸŒœ","aliases":["last_quarter_moon_with_face"]},{"emoji":"โœ๏ธ","aliases":["latin_cross"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ป","aliases":["latvia"]},{"emoji":"๐Ÿ˜†","aliases":["laughing","satisfied","laugh"]},{"emoji":"๐Ÿฅฌ","aliases":["leafy_green"]},{"emoji":"๐Ÿƒ","aliases":["leaves"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ง","aliases":["lebanon"]},{"emoji":"๐Ÿ“’","aliases":["ledger"]},{"emoji":"๐Ÿ›…","aliases":["left_luggage"]},{"emoji":"โ†”๏ธ","aliases":["left_right_arrow"]},{"emoji":"๐Ÿ—จ๏ธ","aliases":["left_speech_bubble"]},{"emoji":"โ†ฉ๏ธ","aliases":["leftwards_arrow_with_hook"]},{"emoji":"๐Ÿฆต","aliases":["leg"]},{"emoji":"๐Ÿ‹","aliases":["lemon"]},{"emoji":"โ™Œ","aliases":["leo"]},{"emoji":"๐Ÿ†","aliases":["leopard"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ธ","aliases":["lesotho"]},{"emoji":"๐ŸŽš๏ธ","aliases":["level_slider"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ท","aliases":["liberia"]},{"emoji":"โ™Ž","aliases":["libra"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡พ","aliases":["libya"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ฎ","aliases":["liechtenstein"]},{"emoji":"๐Ÿšˆ","aliases":["light_rail"]},{"emoji":"๐Ÿ”—","aliases":["link"]},{"emoji":"๐Ÿฆ","aliases":["lion"]},{"emoji":"๐Ÿ‘„","aliases":["lips"]},{"emoji":"๐Ÿ’„","aliases":["lipstick"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡น","aliases":["lithuania"]},{"emoji":"๐ŸฆŽ","aliases":["lizard"]},{"emoji":"๐Ÿฆ™","aliases":["llama"]},{"emoji":"๐Ÿฆž","aliases":["lobster"]},{"emoji":"๐Ÿ”’","aliases":["lock"]},{"emoji":"๐Ÿ”","aliases":["lock_with_ink_pen"]},{"emoji":"๐Ÿญ","aliases":["lollipop"]},{"emoji":"โžฟ","aliases":["loop"]},{"emoji":"๐Ÿงด","aliases":["lotion_bottle"]},{"emoji":"๐Ÿง˜","aliases":["lotus_position"]},{"emoji":"๐Ÿง˜โ€โ™‚๏ธ","aliases":["lotus_position_man"]},{"emoji":"๐Ÿง˜โ€โ™€๏ธ","aliases":["lotus_position_woman"]},{"emoji":"๐Ÿ”Š","aliases":["loud_sound"]},{"emoji":"๐Ÿ“ข","aliases":["loudspeaker"]},{"emoji":"๐Ÿฉ","aliases":["love_hotel"]},{"emoji":"๐Ÿ’Œ","aliases":["love_letter"]},{"emoji":"๐ŸคŸ","aliases":["love_you_gesture"]},{"emoji":"๐Ÿ”…","aliases":["low_brightness"]},{"emoji":"๐Ÿงณ","aliases":["luggage"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡บ","aliases":["luxembourg"]},{"emoji":"๐Ÿคฅ","aliases":["lying_face"]},{"emoji":"โ“‚๏ธ","aliases":["m"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ด","aliases":["macau"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฐ","aliases":["macedonia"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฌ","aliases":["madagascar"]},{"emoji":"๐Ÿ”","aliases":["mag"]},{"emoji":"๐Ÿ”Ž","aliases":["mag_right"]},{"emoji":"๐Ÿง™","aliases":["mage"]},{"emoji":"๐Ÿง™โ€โ™‚๏ธ","aliases":["mage_man"]},{"emoji":"๐Ÿง™โ€โ™€๏ธ","aliases":["mage_woman"]},{"emoji":"๐Ÿงฒ","aliases":["magnet"]},{"emoji":"๐Ÿ€„","aliases":["mahjong"]},{"emoji":"๐Ÿ“ซ","aliases":["mailbox"]},{"emoji":"๐Ÿ“ช","aliases":["mailbox_closed"]},{"emoji":"๐Ÿ“ฌ","aliases":["mailbox_with_mail"]},{"emoji":"๐Ÿ“ญ","aliases":["mailbox_with_no_mail"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ผ","aliases":["malawi"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡พ","aliases":["malaysia"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ป","aliases":["maldives"]},{"emoji":"๐Ÿ•ต๏ธโ€โ™‚๏ธ","aliases":["male_detective"]},{"emoji":"โ™‚๏ธ","aliases":["male_sign"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฑ","aliases":["mali"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡น","aliases":["malta"]},{"emoji":"๐Ÿ‘จ","aliases":["man"]},{"emoji":"๐Ÿ‘จโ€๐ŸŽจ","aliases":["man_artist"]},{"emoji":"๐Ÿ‘จโ€๐Ÿš€","aliases":["man_astronaut"]},{"emoji":"๐Ÿคธโ€โ™‚๏ธ","aliases":["man_cartwheeling"]},{"emoji":"๐Ÿ‘จโ€๐Ÿณ","aliases":["man_cook"]},{"emoji":"๐Ÿ•บ","aliases":["man_dancing"]},{"emoji":"๐Ÿคฆโ€โ™‚๏ธ","aliases":["man_facepalming"]},{"emoji":"๐Ÿ‘จโ€๐Ÿญ","aliases":["man_factory_worker"]},{"emoji":"๐Ÿ‘จโ€๐ŸŒพ","aliases":["man_farmer"]},{"emoji":"๐Ÿ‘จโ€๐Ÿš’","aliases":["man_firefighter"]},{"emoji":"๐Ÿ‘จโ€โš•๏ธ","aliases":["man_health_worker"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆฝ","aliases":["man_in_manual_wheelchair"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆผ","aliases":["man_in_motorized_wheelchair"]},{"emoji":"๐Ÿ‘จโ€โš–๏ธ","aliases":["man_judge"]},{"emoji":"๐Ÿคนโ€โ™‚๏ธ","aliases":["man_juggling"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ”ง","aliases":["man_mechanic"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ’ผ","aliases":["man_office_worker"]},{"emoji":"๐Ÿ‘จโ€โœˆ๏ธ","aliases":["man_pilot"]},{"emoji":"๐Ÿคพโ€โ™‚๏ธ","aliases":["man_playing_handball"]},{"emoji":"๐Ÿคฝโ€โ™‚๏ธ","aliases":["man_playing_water_polo"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ”ฌ","aliases":["man_scientist"]},{"emoji":"๐Ÿคทโ€โ™‚๏ธ","aliases":["man_shrugging"]},{"emoji":"๐Ÿ‘จโ€๐ŸŽค","aliases":["man_singer"]},{"emoji":"๐Ÿ‘จโ€๐ŸŽ“","aliases":["man_student"]},{"emoji":"๐Ÿ‘จโ€๐Ÿซ","aliases":["man_teacher"]},{"emoji":"๐Ÿ‘จโ€๐Ÿ’ป","aliases":["man_technologist"]},{"emoji":"๐Ÿ‘ฒ","aliases":["man_with_gua_pi_mao"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆฏ","aliases":["man_with_probing_cane"]},{"emoji":"๐Ÿ‘ณโ€โ™‚๏ธ","aliases":["man_with_turban"]},{"emoji":"๐Ÿฅญ","aliases":["mango"]},{"emoji":"๐Ÿ‘ž","aliases":["mans_shoe","shoe"]},{"emoji":"๐Ÿ•ฐ๏ธ","aliases":["mantelpiece_clock"]},{"emoji":"๐Ÿฆฝ","aliases":["manual_wheelchair"]},{"emoji":"๐Ÿ","aliases":["maple_leaf"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ญ","aliases":["marshall_islands"]},{"emoji":"๐Ÿฅ‹","aliases":["martial_arts_uniform"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ถ","aliases":["martinique"]},{"emoji":"๐Ÿ˜ท","aliases":["mask"]},{"emoji":"๐Ÿ’†","aliases":["massage"]},{"emoji":"๐Ÿ’†โ€โ™‚๏ธ","aliases":["massage_man"]},{"emoji":"๐Ÿ’†โ€โ™€๏ธ","aliases":["massage_woman"]},{"emoji":"๐Ÿง‰","aliases":["mate"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ท","aliases":["mauritania"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡บ","aliases":["mauritius"]},{"emoji":"๐Ÿ‡พ๐Ÿ‡น","aliases":["mayotte"]},{"emoji":"๐Ÿ–","aliases":["meat_on_bone"]},{"emoji":"๐Ÿง‘โ€๐Ÿ”ง","aliases":["mechanic"]},{"emoji":"๐Ÿฆพ","aliases":["mechanical_arm"]},{"emoji":"๐Ÿฆฟ","aliases":["mechanical_leg"]},{"emoji":"๐ŸŽ–๏ธ","aliases":["medal_military"]},{"emoji":"๐Ÿ…","aliases":["medal_sports"]},{"emoji":"โš•๏ธ","aliases":["medical_symbol"]},{"emoji":"๐Ÿ“ฃ","aliases":["mega"]},{"emoji":"๐Ÿˆ","aliases":["melon"]},{"emoji":"๐Ÿ“","aliases":["memo","pencil"]},{"emoji":"๐Ÿคผโ€โ™‚๏ธ","aliases":["men_wrestling"]},{"emoji":"๐Ÿ•Ž","aliases":["menorah"]},{"emoji":"๐Ÿšน","aliases":["mens"]},{"emoji":"๐Ÿงœโ€โ™€๏ธ","aliases":["mermaid"]},{"emoji":"๐Ÿงœโ€โ™‚๏ธ","aliases":["merman"]},{"emoji":"๐Ÿงœ","aliases":["merperson"]},{"emoji":"๐Ÿค˜","aliases":["metal"]},{"emoji":"๐Ÿš‡","aliases":["metro"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฝ","aliases":["mexico"]},{"emoji":"๐Ÿฆ ","aliases":["microbe"]},{"emoji":"๐Ÿ‡ซ๐Ÿ‡ฒ","aliases":["micronesia"]},{"emoji":"๐ŸŽค","aliases":["microphone"]},{"emoji":"๐Ÿ”ฌ","aliases":["microscope"]},{"emoji":"๐Ÿ–•","aliases":["middle_finger","fu"]},{"emoji":"๐Ÿฅ›","aliases":["milk_glass"]},{"emoji":"๐ŸŒŒ","aliases":["milky_way"]},{"emoji":"๐Ÿš","aliases":["minibus"]},{"emoji":"๐Ÿ’ฝ","aliases":["minidisc"]},{"emoji":"๐Ÿ“ด","aliases":["mobile_phone_off"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฉ","aliases":["moldova"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡จ","aliases":["monaco"]},{"emoji":"๐Ÿค‘","aliases":["money_mouth_face"]},{"emoji":"๐Ÿ’ธ","aliases":["money_with_wings"]},{"emoji":"๐Ÿ’ฐ","aliases":["moneybag"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ณ","aliases":["mongolia"]},{"emoji":"๐Ÿ’","aliases":["monkey"]},{"emoji":"๐Ÿต","aliases":["monkey_face"]},{"emoji":"๐Ÿง","aliases":["monocle_face"]},{"emoji":"๐Ÿš","aliases":["monorail"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ช","aliases":["montenegro"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ธ","aliases":["montserrat"]},{"emoji":"๐ŸŒ”","aliases":["moon","waxing_gibbous_moon"]},{"emoji":"๐Ÿฅฎ","aliases":["moon_cake"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฆ","aliases":["morocco"]},{"emoji":"๐ŸŽ“","aliases":["mortar_board"]},{"emoji":"๐Ÿ•Œ","aliases":["mosque"]},{"emoji":"๐ŸฆŸ","aliases":["mosquito"]},{"emoji":"๐Ÿ›ฅ๏ธ","aliases":["motor_boat"]},{"emoji":"๐Ÿ›ต","aliases":["motor_scooter"]},{"emoji":"๐Ÿ๏ธ","aliases":["motorcycle"]},{"emoji":"๐Ÿฆผ","aliases":["motorized_wheelchair"]},{"emoji":"๐Ÿ›ฃ๏ธ","aliases":["motorway"]},{"emoji":"๐Ÿ—ป","aliases":["mount_fuji"]},{"emoji":"โ›ฐ๏ธ","aliases":["mountain"]},{"emoji":"๐Ÿšต","aliases":["mountain_bicyclist"]},{"emoji":"๐Ÿšตโ€โ™‚๏ธ","aliases":["mountain_biking_man"]},{"emoji":"๐Ÿšตโ€โ™€๏ธ","aliases":["mountain_biking_woman"]},{"emoji":"๐Ÿš ","aliases":["mountain_cableway"]},{"emoji":"๐Ÿšž","aliases":["mountain_railway"]},{"emoji":"๐Ÿ”๏ธ","aliases":["mountain_snow"]},{"emoji":"๐Ÿญ","aliases":["mouse"]},{"emoji":"๐Ÿ","aliases":["mouse2"]},{"emoji":"๐ŸŽฅ","aliases":["movie_camera"]},{"emoji":"๐Ÿ—ฟ","aliases":["moyai"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฟ","aliases":["mozambique"]},{"emoji":"๐Ÿคถ","aliases":["mrs_claus"]},{"emoji":"๐Ÿ’ช","aliases":["muscle"]},{"emoji":"๐Ÿ„","aliases":["mushroom"]},{"emoji":"๐ŸŽน","aliases":["musical_keyboard"]},{"emoji":"๐ŸŽต","aliases":["musical_note"]},{"emoji":"๐ŸŽผ","aliases":["musical_score"]},{"emoji":"๐Ÿ”‡","aliases":["mute"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ฒ","aliases":["myanmar"]},{"emoji":"๐Ÿ’…","aliases":["nail_care"]},{"emoji":"๐Ÿ“›","aliases":["name_badge"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ฆ","aliases":["namibia"]},{"emoji":"๐Ÿž๏ธ","aliases":["national_park"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ท","aliases":["nauru"]},{"emoji":"๐Ÿคข","aliases":["nauseated_face"]},{"emoji":"๐Ÿงฟ","aliases":["nazar_amulet"]},{"emoji":"๐Ÿ‘”","aliases":["necktie"]},{"emoji":"โŽ","aliases":["negative_squared_cross_mark"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ต","aliases":["nepal"]},{"emoji":"๐Ÿค“","aliases":["nerd_face"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ฑ","aliases":["netherlands"]},{"emoji":"๐Ÿ˜","aliases":["neutral_face"]},{"emoji":"๐Ÿ†•","aliases":["new"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡จ","aliases":["new_caledonia"]},{"emoji":"๐ŸŒ‘","aliases":["new_moon"]},{"emoji":"๐ŸŒš","aliases":["new_moon_with_face"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ฟ","aliases":["new_zealand"]},{"emoji":"๐Ÿ“ฐ","aliases":["newspaper"]},{"emoji":"๐Ÿ—ž๏ธ","aliases":["newspaper_roll"]},{"emoji":"โญ๏ธ","aliases":["next_track_button"]},{"emoji":"๐Ÿ†–","aliases":["ng"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ฎ","aliases":["nicaragua"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ช","aliases":["niger"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ฌ","aliases":["nigeria"]},{"emoji":"๐ŸŒƒ","aliases":["night_with_stars"]},{"emoji":"9๏ธโƒฃ","aliases":["nine"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡บ","aliases":["niue"]},{"emoji":"๐Ÿ”•","aliases":["no_bell"]},{"emoji":"๐Ÿšณ","aliases":["no_bicycles"]},{"emoji":"โ›”","aliases":["no_entry"]},{"emoji":"๐Ÿšซ","aliases":["no_entry_sign"]},{"emoji":"๐Ÿ™…","aliases":["no_good"]},{"emoji":"๐Ÿ™…โ€โ™‚๏ธ","aliases":["no_good_man","ng_man"]},{"emoji":"๐Ÿ™…โ€โ™€๏ธ","aliases":["no_good_woman","ng_woman"]},{"emoji":"๐Ÿ“ต","aliases":["no_mobile_phones"]},{"emoji":"๐Ÿ˜ถ","aliases":["no_mouth"]},{"emoji":"๐Ÿšท","aliases":["no_pedestrians"]},{"emoji":"๐Ÿšญ","aliases":["no_smoking"]},{"emoji":"๐Ÿšฑ","aliases":["non-potable_water"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ซ","aliases":["norfolk_island"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ต","aliases":["north_korea"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ต","aliases":["northern_mariana_islands"]},{"emoji":"๐Ÿ‡ณ๐Ÿ‡ด","aliases":["norway"]},{"emoji":"๐Ÿ‘ƒ","aliases":["nose"]},{"emoji":"๐Ÿ““","aliases":["notebook"]},{"emoji":"๐Ÿ“”","aliases":["notebook_with_decorative_cover"]},{"emoji":"๐ŸŽถ","aliases":["notes"]},{"emoji":"๐Ÿ”ฉ","aliases":["nut_and_bolt"]},{"emoji":"โญ•","aliases":["o"]},{"emoji":"๐Ÿ…พ๏ธ","aliases":["o2"]},{"emoji":"๐ŸŒŠ","aliases":["ocean"]},{"emoji":"๐Ÿ™","aliases":["octopus"]},{"emoji":"๐Ÿข","aliases":["oden"]},{"emoji":"๐Ÿข","aliases":["office"]},{"emoji":"๐Ÿง‘โ€๐Ÿ’ผ","aliases":["office_worker"]},{"emoji":"๐Ÿ›ข๏ธ","aliases":["oil_drum"]},{"emoji":"๐Ÿ†—","aliases":["ok"]},{"emoji":"๐Ÿ‘Œ","aliases":["ok_hand"]},{"emoji":"๐Ÿ™†โ€โ™‚๏ธ","aliases":["ok_man"]},{"emoji":"๐Ÿ™†","aliases":["ok_person"]},{"emoji":"๐Ÿ™†โ€โ™€๏ธ","aliases":["ok_woman"]},{"emoji":"๐Ÿ—๏ธ","aliases":["old_key"]},{"emoji":"๐Ÿง“","aliases":["older_adult"]},{"emoji":"๐Ÿ‘ด","aliases":["older_man"]},{"emoji":"๐Ÿ‘ต","aliases":["older_woman"]},{"emoji":"๐Ÿ•‰๏ธ","aliases":["om"]},{"emoji":"๐Ÿ‡ด๐Ÿ‡ฒ","aliases":["oman"]},{"emoji":"๐Ÿ”›","aliases":["on"]},{"emoji":"๐Ÿš˜","aliases":["oncoming_automobile"]},{"emoji":"๐Ÿš","aliases":["oncoming_bus"]},{"emoji":"๐Ÿš”","aliases":["oncoming_police_car"]},{"emoji":"๐Ÿš–","aliases":["oncoming_taxi"]},{"emoji":"1๏ธโƒฃ","aliases":["one"]},{"emoji":"๐Ÿฉฑ","aliases":["one_piece_swimsuit"]},{"emoji":"๐Ÿง…","aliases":["onion"]},{"emoji":"๐Ÿ“‚","aliases":["open_file_folder"]},{"emoji":"๐Ÿ‘","aliases":["open_hands"]},{"emoji":"๐Ÿ˜ฎ","aliases":["open_mouth"]},{"emoji":"โ˜‚๏ธ","aliases":["open_umbrella"]},{"emoji":"โ›Ž","aliases":["ophiuchus"]},{"emoji":"๐Ÿ“™","aliases":["orange_book"]},{"emoji":"๐ŸŸ ","aliases":["orange_circle"]},{"emoji":"๐Ÿงก","aliases":["orange_heart"]},{"emoji":"๐ŸŸง","aliases":["orange_square"]},{"emoji":"๐Ÿฆง","aliases":["orangutan"]},{"emoji":"โ˜ฆ๏ธ","aliases":["orthodox_cross"]},{"emoji":"๐Ÿฆฆ","aliases":["otter"]},{"emoji":"๐Ÿ“ค","aliases":["outbox_tray"]},{"emoji":"๐Ÿฆ‰","aliases":["owl"]},{"emoji":"๐Ÿ‚","aliases":["ox"]},{"emoji":"๐Ÿฆช","aliases":["oyster"]},{"emoji":"๐Ÿ“ฆ","aliases":["package"]},{"emoji":"๐Ÿ“„","aliases":["page_facing_up"]},{"emoji":"๐Ÿ“ƒ","aliases":["page_with_curl"]},{"emoji":"๐Ÿ“Ÿ","aliases":["pager"]},{"emoji":"๐Ÿ–Œ๏ธ","aliases":["paintbrush"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ฐ","aliases":["pakistan"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ผ","aliases":["palau"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ธ","aliases":["palestinian_territories"]},{"emoji":"๐ŸŒด","aliases":["palm_tree"]},{"emoji":"๐Ÿคฒ","aliases":["palms_up_together"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ฆ","aliases":["panama"]},{"emoji":"๐Ÿฅž","aliases":["pancakes"]},{"emoji":"๐Ÿผ","aliases":["panda_face"]},{"emoji":"๐Ÿ“Ž","aliases":["paperclip"]},{"emoji":"๐Ÿ–‡๏ธ","aliases":["paperclips"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ฌ","aliases":["papua_new_guinea"]},{"emoji":"๐Ÿช‚","aliases":["parachute"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡พ","aliases":["paraguay"]},{"emoji":"โ›ฑ๏ธ","aliases":["parasol_on_ground"]},{"emoji":"๐Ÿ…ฟ๏ธ","aliases":["parking"]},{"emoji":"๐Ÿฆœ","aliases":["parrot"]},{"emoji":"ใ€ฝ๏ธ","aliases":["part_alternation_mark"]},{"emoji":"โ›…","aliases":["partly_sunny"]},{"emoji":"๐Ÿฅณ","aliases":["partying_face"]},{"emoji":"๐Ÿ›ณ๏ธ","aliases":["passenger_ship"]},{"emoji":"๐Ÿ›‚","aliases":["passport_control"]},{"emoji":"โธ๏ธ","aliases":["pause_button"]},{"emoji":"โ˜ฎ๏ธ","aliases":["peace_symbol"]},{"emoji":"๐Ÿ‘","aliases":["peach"]},{"emoji":"๐Ÿฆš","aliases":["peacock"]},{"emoji":"๐Ÿฅœ","aliases":["peanuts"]},{"emoji":"๐Ÿ","aliases":["pear"]},{"emoji":"๐Ÿ–Š๏ธ","aliases":["pen"]},{"emoji":"โœ๏ธ","aliases":["pencil2"]},{"emoji":"๐Ÿง","aliases":["penguin"]},{"emoji":"๐Ÿ˜”","aliases":["pensive"]},{"emoji":"๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘","aliases":["people_holding_hands"]},{"emoji":"๐ŸŽญ","aliases":["performing_arts"]},{"emoji":"๐Ÿ˜ฃ","aliases":["persevere"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆฒ","aliases":["person_bald"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆฑ","aliases":["person_curly_hair"]},{"emoji":"๐Ÿคบ","aliases":["person_fencing"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆฝ","aliases":["person_in_manual_wheelchair"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆผ","aliases":["person_in_motorized_wheelchair"]},{"emoji":"๐Ÿคต","aliases":["person_in_tuxedo"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆฐ","aliases":["person_red_hair"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆณ","aliases":["person_white_hair"]},{"emoji":"๐Ÿง‘โ€๐Ÿฆฏ","aliases":["person_with_probing_cane"]},{"emoji":"๐Ÿ‘ณ","aliases":["person_with_turban"]},{"emoji":"๐Ÿ‘ฐ","aliases":["person_with_veil"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ช","aliases":["peru"]},{"emoji":"๐Ÿงซ","aliases":["petri_dish"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ญ","aliases":["philippines"]},{"emoji":"โ˜Ž๏ธ","aliases":["phone","telephone"]},{"emoji":"โ›๏ธ","aliases":["pick"]},{"emoji":"๐Ÿฅง","aliases":["pie"]},{"emoji":"๐Ÿท","aliases":["pig"]},{"emoji":"๐Ÿ–","aliases":["pig2"]},{"emoji":"๐Ÿฝ","aliases":["pig_nose"]},{"emoji":"๐Ÿ’Š","aliases":["pill"]},{"emoji":"๐Ÿง‘โ€โœˆ๏ธ","aliases":["pilot"]},{"emoji":"๐Ÿค","aliases":["pinching_hand"]},{"emoji":"๐Ÿ","aliases":["pineapple"]},{"emoji":"๐Ÿ“","aliases":["ping_pong"]},{"emoji":"๐Ÿดโ€โ˜ ๏ธ","aliases":["pirate_flag"]},{"emoji":"โ™“","aliases":["pisces"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ณ","aliases":["pitcairn_islands"]},{"emoji":"๐Ÿ•","aliases":["pizza"]},{"emoji":"๐Ÿ›","aliases":["place_of_worship"]},{"emoji":"๐Ÿฝ๏ธ","aliases":["plate_with_cutlery"]},{"emoji":"โฏ๏ธ","aliases":["play_or_pause_button"]},{"emoji":"๐Ÿฅบ","aliases":["pleading_face"]},{"emoji":"๐Ÿ‘‡","aliases":["point_down"]},{"emoji":"๐Ÿ‘ˆ","aliases":["point_left"]},{"emoji":"๐Ÿ‘‰","aliases":["point_right"]},{"emoji":"โ˜๏ธ","aliases":["point_up"]},{"emoji":"๐Ÿ‘†","aliases":["point_up_2"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ฑ","aliases":["poland"]},{"emoji":"๐Ÿš“","aliases":["police_car"]},{"emoji":"๐Ÿ‘ฎ","aliases":["police_officer","cop"]},{"emoji":"๐Ÿ‘ฎโ€โ™‚๏ธ","aliases":["policeman"]},{"emoji":"๐Ÿ‘ฎโ€โ™€๏ธ","aliases":["policewoman"]},{"emoji":"๐Ÿฉ","aliases":["poodle"]},{"emoji":"๐Ÿฟ","aliases":["popcorn"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡น","aliases":["portugal"]},{"emoji":"๐Ÿฃ","aliases":["post_office"]},{"emoji":"๐Ÿ“ฏ","aliases":["postal_horn"]},{"emoji":"๐Ÿ“ฎ","aliases":["postbox"]},{"emoji":"๐Ÿšฐ","aliases":["potable_water"]},{"emoji":"๐Ÿฅ”","aliases":["potato"]},{"emoji":"๐Ÿ‘","aliases":["pouch"]},{"emoji":"๐Ÿ—","aliases":["poultry_leg"]},{"emoji":"๐Ÿ’ท","aliases":["pound"]},{"emoji":"๐Ÿ˜พ","aliases":["pouting_cat"]},{"emoji":"๐Ÿ™Ž","aliases":["pouting_face"]},{"emoji":"๐Ÿ™Žโ€โ™‚๏ธ","aliases":["pouting_man"]},{"emoji":"๐Ÿ™Žโ€โ™€๏ธ","aliases":["pouting_woman"]},{"emoji":"๐Ÿ™","aliases":["pray"]},{"emoji":"๐Ÿ“ฟ","aliases":["prayer_beads"]},{"emoji":"๐Ÿคฐ","aliases":["pregnant_woman"]},{"emoji":"๐Ÿฅจ","aliases":["pretzel"]},{"emoji":"โฎ๏ธ","aliases":["previous_track_button"]},{"emoji":"๐Ÿคด","aliases":["prince"]},{"emoji":"๐Ÿ‘ธ","aliases":["princess"]},{"emoji":"๐Ÿ–จ๏ธ","aliases":["printer"]},{"emoji":"๐Ÿฆฏ","aliases":["probing_cane"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ท","aliases":["puerto_rico"]},{"emoji":"๐ŸŸฃ","aliases":["purple_circle"]},{"emoji":"๐Ÿ’œ","aliases":["purple_heart"]},{"emoji":"๐ŸŸช","aliases":["purple_square"]},{"emoji":"๐Ÿ‘›","aliases":["purse"]},{"emoji":"๐Ÿ“Œ","aliases":["pushpin"]},{"emoji":"๐Ÿšฎ","aliases":["put_litter_in_its_place"]},{"emoji":"๐Ÿ‡ถ๐Ÿ‡ฆ","aliases":["qatar"]},{"emoji":"โ“","aliases":["question"]},{"emoji":"๐Ÿฐ","aliases":["rabbit"]},{"emoji":"๐Ÿ‡","aliases":["rabbit2"]},{"emoji":"๐Ÿฆ","aliases":["raccoon"]},{"emoji":"๐ŸŽ","aliases":["racehorse"]},{"emoji":"๐ŸŽ๏ธ","aliases":["racing_car"]},{"emoji":"๐Ÿ“ป","aliases":["radio"]},{"emoji":"๐Ÿ”˜","aliases":["radio_button"]},{"emoji":"โ˜ข๏ธ","aliases":["radioactive"]},{"emoji":"๐Ÿ˜ก","aliases":["rage","pout"]},{"emoji":"๐Ÿšƒ","aliases":["railway_car"]},{"emoji":"๐Ÿ›ค๏ธ","aliases":["railway_track"]},{"emoji":"๐ŸŒˆ","aliases":["rainbow"]},{"emoji":"๐Ÿณ๏ธโ€๐ŸŒˆ","aliases":["rainbow_flag"]},{"emoji":"๐Ÿคš","aliases":["raised_back_of_hand"]},{"emoji":"๐Ÿคจ","aliases":["raised_eyebrow"]},{"emoji":"๐Ÿ–๏ธ","aliases":["raised_hand_with_fingers_splayed"]},{"emoji":"๐Ÿ™Œ","aliases":["raised_hands"]},{"emoji":"๐Ÿ™‹","aliases":["raising_hand"]},{"emoji":"๐Ÿ™‹โ€โ™‚๏ธ","aliases":["raising_hand_man"]},{"emoji":"๐Ÿ™‹โ€โ™€๏ธ","aliases":["raising_hand_woman"]},{"emoji":"๐Ÿ","aliases":["ram"]},{"emoji":"๐Ÿœ","aliases":["ramen"]},{"emoji":"๐Ÿ€","aliases":["rat"]},{"emoji":"๐Ÿช’","aliases":["razor"]},{"emoji":"๐Ÿงพ","aliases":["receipt"]},{"emoji":"โบ๏ธ","aliases":["record_button"]},{"emoji":"โ™ป๏ธ","aliases":["recycle"]},{"emoji":"๐Ÿ”ด","aliases":["red_circle"]},{"emoji":"๐Ÿงง","aliases":["red_envelope"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆฐ","aliases":["red_haired_man"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆฐ","aliases":["red_haired_woman"]},{"emoji":"๐ŸŸฅ","aliases":["red_square"]},{"emoji":"ยฎ๏ธ","aliases":["registered"]},{"emoji":"โ˜บ๏ธ","aliases":["relaxed"]},{"emoji":"๐Ÿ˜Œ","aliases":["relieved"]},{"emoji":"๐ŸŽ—๏ธ","aliases":["reminder_ribbon"]},{"emoji":"๐Ÿ”","aliases":["repeat"]},{"emoji":"๐Ÿ”‚","aliases":["repeat_one"]},{"emoji":"โ›‘๏ธ","aliases":["rescue_worker_helmet"]},{"emoji":"๐Ÿšป","aliases":["restroom"]},{"emoji":"๐Ÿ‡ท๐Ÿ‡ช","aliases":["reunion"]},{"emoji":"๐Ÿ’ž","aliases":["revolving_hearts"]},{"emoji":"โช","aliases":["rewind"]},{"emoji":"๐Ÿฆ","aliases":["rhinoceros"]},{"emoji":"๐ŸŽ€","aliases":["ribbon"]},{"emoji":"๐Ÿš","aliases":["rice"]},{"emoji":"๐Ÿ™","aliases":["rice_ball"]},{"emoji":"๐Ÿ˜","aliases":["rice_cracker"]},{"emoji":"๐ŸŽ‘","aliases":["rice_scene"]},{"emoji":"๐Ÿ—ฏ๏ธ","aliases":["right_anger_bubble"]},{"emoji":"๐Ÿ’","aliases":["ring"]},{"emoji":"๐Ÿช","aliases":["ringed_planet"]},{"emoji":"๐Ÿค–","aliases":["robot"]},{"emoji":"๐Ÿš€","aliases":["rocket"]},{"emoji":"๐Ÿคฃ","aliases":["rofl"]},{"emoji":"๐Ÿ™„","aliases":["roll_eyes"]},{"emoji":"๐Ÿงป","aliases":["roll_of_paper"]},{"emoji":"๐ŸŽข","aliases":["roller_coaster"]},{"emoji":"๐Ÿ‡ท๐Ÿ‡ด","aliases":["romania"]},{"emoji":"๐Ÿ“","aliases":["rooster"]},{"emoji":"๐ŸŒน","aliases":["rose"]},{"emoji":"๐Ÿต๏ธ","aliases":["rosette"]},{"emoji":"๐Ÿšจ","aliases":["rotating_light"]},{"emoji":"๐Ÿ“","aliases":["round_pushpin"]},{"emoji":"๐Ÿšฃ","aliases":["rowboat"]},{"emoji":"๐Ÿšฃโ€โ™‚๏ธ","aliases":["rowing_man"]},{"emoji":"๐Ÿšฃโ€โ™€๏ธ","aliases":["rowing_woman"]},{"emoji":"๐Ÿ‡ท๐Ÿ‡บ","aliases":["ru"]},{"emoji":"๐Ÿ‰","aliases":["rugby_football"]},{"emoji":"๐Ÿƒ","aliases":["runner","running"]},{"emoji":"๐Ÿƒโ€โ™‚๏ธ","aliases":["running_man"]},{"emoji":"๐ŸŽฝ","aliases":["running_shirt_with_sash"]},{"emoji":"๐Ÿƒโ€โ™€๏ธ","aliases":["running_woman"]},{"emoji":"๐Ÿ‡ท๐Ÿ‡ผ","aliases":["rwanda"]},{"emoji":"๐Ÿˆ‚๏ธ","aliases":["sa"]},{"emoji":"๐Ÿงท","aliases":["safety_pin"]},{"emoji":"๐Ÿฆบ","aliases":["safety_vest"]},{"emoji":"โ™","aliases":["sagittarius"]},{"emoji":"๐Ÿถ","aliases":["sake"]},{"emoji":"๐Ÿง‚","aliases":["salt"]},{"emoji":"๐Ÿ‡ผ๐Ÿ‡ธ","aliases":["samoa"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฒ","aliases":["san_marino"]},{"emoji":"๐Ÿ‘ก","aliases":["sandal"]},{"emoji":"๐Ÿฅช","aliases":["sandwich"]},{"emoji":"๐ŸŽ…","aliases":["santa"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡น","aliases":["sao_tome_principe"]},{"emoji":"๐Ÿฅป","aliases":["sari"]},{"emoji":"๐Ÿ“ก","aliases":["satellite"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฆ","aliases":["saudi_arabia"]},{"emoji":"๐Ÿง–โ€โ™‚๏ธ","aliases":["sauna_man"]},{"emoji":"๐Ÿง–","aliases":["sauna_person"]},{"emoji":"๐Ÿง–โ€โ™€๏ธ","aliases":["sauna_woman"]},{"emoji":"๐Ÿฆ•","aliases":["sauropod"]},{"emoji":"๐ŸŽท","aliases":["saxophone"]},{"emoji":"๐Ÿงฃ","aliases":["scarf"]},{"emoji":"๐Ÿซ","aliases":["school"]},{"emoji":"๐ŸŽ’","aliases":["school_satchel"]},{"emoji":"๐Ÿง‘โ€๐Ÿ”ฌ","aliases":["scientist"]},{"emoji":"โœ‚๏ธ","aliases":["scissors"]},{"emoji":"๐Ÿฆ‚","aliases":["scorpion"]},{"emoji":"โ™","aliases":["scorpius"]},{"emoji":"๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ","aliases":["scotland"]},{"emoji":"๐Ÿ˜ฑ","aliases":["scream"]},{"emoji":"๐Ÿ™€","aliases":["scream_cat"]},{"emoji":"๐Ÿ“œ","aliases":["scroll"]},{"emoji":"๐Ÿ’บ","aliases":["seat"]},{"emoji":"ใŠ™๏ธ","aliases":["secret"]},{"emoji":"๐Ÿ™ˆ","aliases":["see_no_evil"]},{"emoji":"๐ŸŒฑ","aliases":["seedling"]},{"emoji":"๐Ÿคณ","aliases":["selfie"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ณ","aliases":["senegal"]},{"emoji":"๐Ÿ‡ท๐Ÿ‡ธ","aliases":["serbia"]},{"emoji":"๐Ÿ•โ€๐Ÿฆบ","aliases":["service_dog"]},{"emoji":"7๏ธโƒฃ","aliases":["seven"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡จ","aliases":["seychelles"]},{"emoji":"๐Ÿฅ˜","aliases":["shallow_pan_of_food"]},{"emoji":"โ˜˜๏ธ","aliases":["shamrock"]},{"emoji":"๐Ÿฆˆ","aliases":["shark"]},{"emoji":"๐Ÿง","aliases":["shaved_ice"]},{"emoji":"๐Ÿ‘","aliases":["sheep"]},{"emoji":"๐Ÿš","aliases":["shell"]},{"emoji":"๐Ÿ›ก๏ธ","aliases":["shield"]},{"emoji":"โ›ฉ๏ธ","aliases":["shinto_shrine"]},{"emoji":"๐Ÿšข","aliases":["ship"]},{"emoji":"๐Ÿ‘•","aliases":["shirt","tshirt"]},{"emoji":"๐Ÿ›๏ธ","aliases":["shopping"]},{"emoji":"๐Ÿ›’","aliases":["shopping_cart"]},{"emoji":"๐Ÿฉณ","aliases":["shorts"]},{"emoji":"๐Ÿšฟ","aliases":["shower"]},{"emoji":"๐Ÿฆ","aliases":["shrimp"]},{"emoji":"๐Ÿคท","aliases":["shrug"]},{"emoji":"๐Ÿคซ","aliases":["shushing_face"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฑ","aliases":["sierra_leone"]},{"emoji":"๐Ÿ“ถ","aliases":["signal_strength"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฌ","aliases":["singapore"]},{"emoji":"๐Ÿง‘โ€๐ŸŽค","aliases":["singer"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฝ","aliases":["sint_maarten"]},{"emoji":"6๏ธโƒฃ","aliases":["six"]},{"emoji":"๐Ÿ”ฏ","aliases":["six_pointed_star"]},{"emoji":"๐Ÿ›น","aliases":["skateboard"]},{"emoji":"๐ŸŽฟ","aliases":["ski"]},{"emoji":"โ›ท๏ธ","aliases":["skier"]},{"emoji":"๐Ÿ’€","aliases":["skull"]},{"emoji":"โ˜ ๏ธ","aliases":["skull_and_crossbones"]},{"emoji":"๐Ÿฆจ","aliases":["skunk"]},{"emoji":"๐Ÿ›ท","aliases":["sled"]},{"emoji":"๐Ÿ˜ด","aliases":["sleeping"]},{"emoji":"๐Ÿ›Œ","aliases":["sleeping_bed"]},{"emoji":"๐Ÿ˜ช","aliases":["sleepy"]},{"emoji":"๐Ÿ™","aliases":["slightly_frowning_face"]},{"emoji":"๐Ÿ™‚","aliases":["slightly_smiling_face"]},{"emoji":"๐ŸŽฐ","aliases":["slot_machine"]},{"emoji":"๐Ÿฆฅ","aliases":["sloth"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฐ","aliases":["slovakia"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฎ","aliases":["slovenia"]},{"emoji":"๐Ÿ›ฉ๏ธ","aliases":["small_airplane"]},{"emoji":"๐Ÿ”น","aliases":["small_blue_diamond"]},{"emoji":"๐Ÿ”ธ","aliases":["small_orange_diamond"]},{"emoji":"๐Ÿ”บ","aliases":["small_red_triangle"]},{"emoji":"๐Ÿ”ป","aliases":["small_red_triangle_down"]},{"emoji":"๐Ÿ˜„","aliases":["smile"]},{"emoji":"๐Ÿ˜ธ","aliases":["smile_cat"]},{"emoji":"๐Ÿ˜ƒ","aliases":["smiley"]},{"emoji":"๐Ÿ˜บ","aliases":["smiley_cat"]},{"emoji":"๐Ÿฅฐ","aliases":["smiling_face_with_three_hearts"]},{"emoji":"๐Ÿ˜ˆ","aliases":["smiling_imp"]},{"emoji":"๐Ÿ˜","aliases":["smirk"]},{"emoji":"๐Ÿ˜ผ","aliases":["smirk_cat"]},{"emoji":"๐Ÿšฌ","aliases":["smoking"]},{"emoji":"๐ŸŒ","aliases":["snail"]},{"emoji":"๐Ÿ","aliases":["snake"]},{"emoji":"๐Ÿคง","aliases":["sneezing_face"]},{"emoji":"๐Ÿ‚","aliases":["snowboarder"]},{"emoji":"โ„๏ธ","aliases":["snowflake"]},{"emoji":"โ›„","aliases":["snowman"]},{"emoji":"โ˜ƒ๏ธ","aliases":["snowman_with_snow"]},{"emoji":"๐Ÿงผ","aliases":["soap"]},{"emoji":"๐Ÿ˜ญ","aliases":["sob"]},{"emoji":"โšฝ","aliases":["soccer"]},{"emoji":"๐Ÿงฆ","aliases":["socks"]},{"emoji":"๐ŸฅŽ","aliases":["softball"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ง","aliases":["solomon_islands"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ด","aliases":["somalia"]},{"emoji":"๐Ÿ”œ","aliases":["soon"]},{"emoji":"๐Ÿ†˜","aliases":["sos"]},{"emoji":"๐Ÿ”‰","aliases":["sound"]},{"emoji":"๐Ÿ‡ฟ๐Ÿ‡ฆ","aliases":["south_africa"]},{"emoji":"๐Ÿ‡ฌ๐Ÿ‡ธ","aliases":["south_georgia_south_sandwich_islands"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ธ","aliases":["south_sudan"]},{"emoji":"๐Ÿ‘พ","aliases":["space_invader"]},{"emoji":"โ™ ๏ธ","aliases":["spades"]},{"emoji":"๐Ÿ","aliases":["spaghetti"]},{"emoji":"โ‡๏ธ","aliases":["sparkle"]},{"emoji":"๐ŸŽ‡","aliases":["sparkler"]},{"emoji":"โœจ","aliases":["sparkles"]},{"emoji":"๐Ÿ’–","aliases":["sparkling_heart"]},{"emoji":"๐Ÿ™Š","aliases":["speak_no_evil"]},{"emoji":"๐Ÿ”ˆ","aliases":["speaker"]},{"emoji":"๐Ÿ—ฃ๏ธ","aliases":["speaking_head"]},{"emoji":"๐Ÿ’ฌ","aliases":["speech_balloon"]},{"emoji":"๐Ÿšค","aliases":["speedboat"]},{"emoji":"๐Ÿ•ท๏ธ","aliases":["spider"]},{"emoji":"๐Ÿ•ธ๏ธ","aliases":["spider_web"]},{"emoji":"๐Ÿ—“๏ธ","aliases":["spiral_calendar"]},{"emoji":"๐Ÿ—’๏ธ","aliases":["spiral_notepad"]},{"emoji":"๐Ÿงฝ","aliases":["sponge"]},{"emoji":"๐Ÿฅ„","aliases":["spoon"]},{"emoji":"๐Ÿฆ‘","aliases":["squid"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡ฐ","aliases":["sri_lanka"]},{"emoji":"๐Ÿ‡ง๐Ÿ‡ฑ","aliases":["st_barthelemy"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ญ","aliases":["st_helena"]},{"emoji":"๐Ÿ‡ฐ๐Ÿ‡ณ","aliases":["st_kitts_nevis"]},{"emoji":"๐Ÿ‡ฑ๐Ÿ‡จ","aliases":["st_lucia"]},{"emoji":"๐Ÿ‡ฒ๐Ÿ‡ซ","aliases":["st_martin"]},{"emoji":"๐Ÿ‡ต๐Ÿ‡ฒ","aliases":["st_pierre_miquelon"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡จ","aliases":["st_vincent_grenadines"]},{"emoji":"๐ŸŸ๏ธ","aliases":["stadium"]},{"emoji":"๐Ÿงโ€โ™‚๏ธ","aliases":["standing_man"]},{"emoji":"๐Ÿง","aliases":["standing_person"]},{"emoji":"๐Ÿงโ€โ™€๏ธ","aliases":["standing_woman"]},{"emoji":"โญ","aliases":["star"]},{"emoji":"๐ŸŒŸ","aliases":["star2"]},{"emoji":"โ˜ช๏ธ","aliases":["star_and_crescent"]},{"emoji":"โœก๏ธ","aliases":["star_of_david"]},{"emoji":"๐Ÿคฉ","aliases":["star_struck"]},{"emoji":"๐ŸŒ ","aliases":["stars"]},{"emoji":"๐Ÿš‰","aliases":["station"]},{"emoji":"๐Ÿ—ฝ","aliases":["statue_of_liberty"]},{"emoji":"๐Ÿš‚","aliases":["steam_locomotive"]},{"emoji":"๐Ÿฉบ","aliases":["stethoscope"]},{"emoji":"๐Ÿฒ","aliases":["stew"]},{"emoji":"โน๏ธ","aliases":["stop_button"]},{"emoji":"๐Ÿ›‘","aliases":["stop_sign"]},{"emoji":"โฑ๏ธ","aliases":["stopwatch"]},{"emoji":"๐Ÿ“","aliases":["straight_ruler"]},{"emoji":"๐Ÿ“","aliases":["strawberry"]},{"emoji":"๐Ÿ˜›","aliases":["stuck_out_tongue"]},{"emoji":"๐Ÿ˜","aliases":["stuck_out_tongue_closed_eyes"]},{"emoji":"๐Ÿ˜œ","aliases":["stuck_out_tongue_winking_eye"]},{"emoji":"๐Ÿง‘โ€๐ŸŽ“","aliases":["student"]},{"emoji":"๐ŸŽ™๏ธ","aliases":["studio_microphone"]},{"emoji":"๐Ÿฅ™","aliases":["stuffed_flatbread"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฉ","aliases":["sudan"]},{"emoji":"๐ŸŒฅ๏ธ","aliases":["sun_behind_large_cloud"]},{"emoji":"๐ŸŒฆ๏ธ","aliases":["sun_behind_rain_cloud"]},{"emoji":"๐ŸŒค๏ธ","aliases":["sun_behind_small_cloud"]},{"emoji":"๐ŸŒž","aliases":["sun_with_face"]},{"emoji":"๐ŸŒป","aliases":["sunflower"]},{"emoji":"๐Ÿ˜Ž","aliases":["sunglasses"]},{"emoji":"โ˜€๏ธ","aliases":["sunny"]},{"emoji":"๐ŸŒ…","aliases":["sunrise"]},{"emoji":"๐ŸŒ„","aliases":["sunrise_over_mountains"]},{"emoji":"๐Ÿฆธ","aliases":["superhero"]},{"emoji":"๐Ÿฆธโ€โ™‚๏ธ","aliases":["superhero_man"]},{"emoji":"๐Ÿฆธโ€โ™€๏ธ","aliases":["superhero_woman"]},{"emoji":"๐Ÿฆน","aliases":["supervillain"]},{"emoji":"๐Ÿฆนโ€โ™‚๏ธ","aliases":["supervillain_man"]},{"emoji":"๐Ÿฆนโ€โ™€๏ธ","aliases":["supervillain_woman"]},{"emoji":"๐Ÿ„","aliases":["surfer"]},{"emoji":"๐Ÿ„โ€โ™‚๏ธ","aliases":["surfing_man"]},{"emoji":"๐Ÿ„โ€โ™€๏ธ","aliases":["surfing_woman"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ท","aliases":["suriname"]},{"emoji":"๐Ÿฃ","aliases":["sushi"]},{"emoji":"๐ŸšŸ","aliases":["suspension_railway"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฏ","aliases":["svalbard_jan_mayen"]},{"emoji":"๐Ÿฆข","aliases":["swan"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ฟ","aliases":["swaziland"]},{"emoji":"๐Ÿ˜“","aliases":["sweat"]},{"emoji":"๐Ÿ’ฆ","aliases":["sweat_drops"]},{"emoji":"๐Ÿ˜…","aliases":["sweat_smile"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡ช","aliases":["sweden"]},{"emoji":"๐Ÿ ","aliases":["sweet_potato"]},{"emoji":"๐Ÿฉฒ","aliases":["swim_brief"]},{"emoji":"๐ŸŠ","aliases":["swimmer"]},{"emoji":"๐ŸŠโ€โ™‚๏ธ","aliases":["swimming_man"]},{"emoji":"๐ŸŠโ€โ™€๏ธ","aliases":["swimming_woman"]},{"emoji":"๐Ÿ‡จ๐Ÿ‡ญ","aliases":["switzerland"]},{"emoji":"๐Ÿ”ฃ","aliases":["symbols"]},{"emoji":"๐Ÿ•","aliases":["synagogue"]},{"emoji":"๐Ÿ‡ธ๐Ÿ‡พ","aliases":["syria"]},{"emoji":"๐Ÿ’‰","aliases":["syringe"]},{"emoji":"๐Ÿฆ–","aliases":["t-rex"]},{"emoji":"๐ŸŒฎ","aliases":["taco"]},{"emoji":"๐ŸŽ‰","aliases":["tada","hooray"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ผ","aliases":["taiwan"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฏ","aliases":["tajikistan"]},{"emoji":"๐Ÿฅก","aliases":["takeout_box"]},{"emoji":"๐ŸŽ‹","aliases":["tanabata_tree"]},{"emoji":"๐ŸŠ","aliases":["tangerine","orange","mandarin"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฟ","aliases":["tanzania"]},{"emoji":"โ™‰","aliases":["taurus"]},{"emoji":"๐Ÿš•","aliases":["taxi"]},{"emoji":"๐Ÿต","aliases":["tea"]},{"emoji":"๐Ÿง‘โ€๐Ÿซ","aliases":["teacher"]},{"emoji":"๐Ÿง‘โ€๐Ÿ’ป","aliases":["technologist"]},{"emoji":"๐Ÿงธ","aliases":["teddy_bear"]},{"emoji":"๐Ÿ“ž","aliases":["telephone_receiver"]},{"emoji":"๐Ÿ”ญ","aliases":["telescope"]},{"emoji":"๐ŸŽพ","aliases":["tennis"]},{"emoji":"โ›บ","aliases":["tent"]},{"emoji":"๐Ÿงช","aliases":["test_tube"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ญ","aliases":["thailand"]},{"emoji":"๐ŸŒก๏ธ","aliases":["thermometer"]},{"emoji":"๐Ÿค”","aliases":["thinking"]},{"emoji":"๐Ÿ’ญ","aliases":["thought_balloon"]},{"emoji":"๐Ÿงต","aliases":["thread"]},{"emoji":"3๏ธโƒฃ","aliases":["three"]},{"emoji":"๐ŸŽซ","aliases":["ticket"]},{"emoji":"๐ŸŽŸ๏ธ","aliases":["tickets"]},{"emoji":"๐Ÿฏ","aliases":["tiger"]},{"emoji":"๐Ÿ…","aliases":["tiger2"]},{"emoji":"โฒ๏ธ","aliases":["timer_clock"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฑ","aliases":["timor_leste"]},{"emoji":"๐Ÿ’โ€โ™‚๏ธ","aliases":["tipping_hand_man","sassy_man"]},{"emoji":"๐Ÿ’","aliases":["tipping_hand_person","information_desk_person"]},{"emoji":"๐Ÿ’โ€โ™€๏ธ","aliases":["tipping_hand_woman","sassy_woman"]},{"emoji":"๐Ÿ˜ซ","aliases":["tired_face"]},{"emoji":"โ„ข๏ธ","aliases":["tm"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฌ","aliases":["togo"]},{"emoji":"๐Ÿšฝ","aliases":["toilet"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฐ","aliases":["tokelau"]},{"emoji":"๐Ÿ—ผ","aliases":["tokyo_tower"]},{"emoji":"๐Ÿ…","aliases":["tomato"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ด","aliases":["tonga"]},{"emoji":"๐Ÿ‘…","aliases":["tongue"]},{"emoji":"๐Ÿงฐ","aliases":["toolbox"]},{"emoji":"๐Ÿฆท","aliases":["tooth"]},{"emoji":"๐Ÿ”","aliases":["top"]},{"emoji":"๐ŸŽฉ","aliases":["tophat"]},{"emoji":"๐ŸŒช๏ธ","aliases":["tornado"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ท","aliases":["tr"]},{"emoji":"๐Ÿ–ฒ๏ธ","aliases":["trackball"]},{"emoji":"๐Ÿšœ","aliases":["tractor"]},{"emoji":"๐Ÿšฅ","aliases":["traffic_light"]},{"emoji":"๐Ÿš‹","aliases":["train"]},{"emoji":"๐Ÿš†","aliases":["train2"]},{"emoji":"๐ŸšŠ","aliases":["tram"]},{"emoji":"๐Ÿšฉ","aliases":["triangular_flag_on_post"]},{"emoji":"๐Ÿ“","aliases":["triangular_ruler"]},{"emoji":"๐Ÿ”ฑ","aliases":["trident"]},{"emoji":"๐Ÿ‡น๐Ÿ‡น","aliases":["trinidad_tobago"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฆ","aliases":["tristan_da_cunha"]},{"emoji":"๐Ÿ˜ค","aliases":["triumph"]},{"emoji":"๐ŸšŽ","aliases":["trolleybus"]},{"emoji":"๐Ÿ†","aliases":["trophy"]},{"emoji":"๐Ÿน","aliases":["tropical_drink"]},{"emoji":"๐Ÿ ","aliases":["tropical_fish"]},{"emoji":"๐Ÿšš","aliases":["truck"]},{"emoji":"๐ŸŽบ","aliases":["trumpet"]},{"emoji":"๐ŸŒท","aliases":["tulip"]},{"emoji":"๐Ÿฅƒ","aliases":["tumbler_glass"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ณ","aliases":["tunisia"]},{"emoji":"๐Ÿฆƒ","aliases":["turkey"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ฒ","aliases":["turkmenistan"]},{"emoji":"๐Ÿ‡น๐Ÿ‡จ","aliases":["turks_caicos_islands"]},{"emoji":"๐Ÿข","aliases":["turtle"]},{"emoji":"๐Ÿ‡น๐Ÿ‡ป","aliases":["tuvalu"]},{"emoji":"๐Ÿ“บ","aliases":["tv"]},{"emoji":"๐Ÿ”€","aliases":["twisted_rightwards_arrows"]},{"emoji":"2๏ธโƒฃ","aliases":["two"]},{"emoji":"๐Ÿ’•","aliases":["two_hearts"]},{"emoji":"๐Ÿ‘ฌ","aliases":["two_men_holding_hands"]},{"emoji":"๐Ÿ‘ญ","aliases":["two_women_holding_hands"]},{"emoji":"๐Ÿˆน","aliases":["u5272"]},{"emoji":"๐Ÿˆด","aliases":["u5408"]},{"emoji":"๐Ÿˆบ","aliases":["u55b6"]},{"emoji":"๐Ÿˆฏ","aliases":["u6307"]},{"emoji":"๐Ÿˆท๏ธ","aliases":["u6708"]},{"emoji":"๐Ÿˆถ","aliases":["u6709"]},{"emoji":"๐Ÿˆต","aliases":["u6e80"]},{"emoji":"๐Ÿˆš","aliases":["u7121"]},{"emoji":"๐Ÿˆธ","aliases":["u7533"]},{"emoji":"๐Ÿˆฒ","aliases":["u7981"]},{"emoji":"๐Ÿˆณ","aliases":["u7a7a"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ฌ","aliases":["uganda"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ฆ","aliases":["ukraine"]},{"emoji":"โ˜”","aliases":["umbrella"]},{"emoji":"๐Ÿ˜’","aliases":["unamused"]},{"emoji":"๐Ÿ”ž","aliases":["underage"]},{"emoji":"๐Ÿฆ„","aliases":["unicorn"]},{"emoji":"๐Ÿ‡ฆ๐Ÿ‡ช","aliases":["united_arab_emirates"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ณ","aliases":["united_nations"]},{"emoji":"๐Ÿ”“","aliases":["unlock"]},{"emoji":"๐Ÿ†™","aliases":["up"]},{"emoji":"๐Ÿ™ƒ","aliases":["upside_down_face"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡พ","aliases":["uruguay"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ธ","aliases":["us"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ฒ","aliases":["us_outlying_islands"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡ฎ","aliases":["us_virgin_islands"]},{"emoji":"๐Ÿ‡บ๐Ÿ‡ฟ","aliases":["uzbekistan"]},{"emoji":"โœŒ๏ธ","aliases":["v"]},{"emoji":"๐Ÿง›","aliases":["vampire"]},{"emoji":"๐Ÿง›โ€โ™‚๏ธ","aliases":["vampire_man"]},{"emoji":"๐Ÿง›โ€โ™€๏ธ","aliases":["vampire_woman"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡บ","aliases":["vanuatu"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡ฆ","aliases":["vatican_city"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡ช","aliases":["venezuela"]},{"emoji":"๐Ÿšฆ","aliases":["vertical_traffic_light"]},{"emoji":"๐Ÿ“ผ","aliases":["vhs"]},{"emoji":"๐Ÿ“ณ","aliases":["vibration_mode"]},{"emoji":"๐Ÿ“น","aliases":["video_camera"]},{"emoji":"๐ŸŽฎ","aliases":["video_game"]},{"emoji":"๐Ÿ‡ป๐Ÿ‡ณ","aliases":["vietnam"]},{"emoji":"๐ŸŽป","aliases":["violin"]},{"emoji":"โ™","aliases":["virgo"]},{"emoji":"๐ŸŒ‹","aliases":["volcano"]},{"emoji":"๐Ÿ","aliases":["volleyball"]},{"emoji":"๐Ÿคฎ","aliases":["vomiting_face"]},{"emoji":"๐Ÿ†š","aliases":["vs"]},{"emoji":"๐Ÿ––","aliases":["vulcan_salute"]},{"emoji":"๐Ÿง‡","aliases":["waffle"]},{"emoji":"๐Ÿด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ","aliases":["wales"]},{"emoji":"๐Ÿšถ","aliases":["walking"]},{"emoji":"๐Ÿšถโ€โ™‚๏ธ","aliases":["walking_man"]},{"emoji":"๐Ÿšถโ€โ™€๏ธ","aliases":["walking_woman"]},{"emoji":"๐Ÿ‡ผ๐Ÿ‡ซ","aliases":["wallis_futuna"]},{"emoji":"๐ŸŒ˜","aliases":["waning_crescent_moon"]},{"emoji":"๐ŸŒ–","aliases":["waning_gibbous_moon"]},{"emoji":"โš ๏ธ","aliases":["warning"]},{"emoji":"๐Ÿ—‘๏ธ","aliases":["wastebasket"]},{"emoji":"โŒš","aliases":["watch"]},{"emoji":"๐Ÿƒ","aliases":["water_buffalo"]},{"emoji":"๐Ÿคฝ","aliases":["water_polo"]},{"emoji":"๐Ÿ‰","aliases":["watermelon"]},{"emoji":"๐Ÿ‘‹","aliases":["wave"]},{"emoji":"ใ€ฐ๏ธ","aliases":["wavy_dash"]},{"emoji":"๐ŸŒ’","aliases":["waxing_crescent_moon"]},{"emoji":"๐Ÿšพ","aliases":["wc"]},{"emoji":"๐Ÿ˜ฉ","aliases":["weary"]},{"emoji":"๐Ÿ’’","aliases":["wedding"]},{"emoji":"๐Ÿ‹๏ธ","aliases":["weight_lifting"]},{"emoji":"๐Ÿ‹๏ธโ€โ™‚๏ธ","aliases":["weight_lifting_man"]},{"emoji":"๐Ÿ‹๏ธโ€โ™€๏ธ","aliases":["weight_lifting_woman"]},{"emoji":"๐Ÿ‡ช๐Ÿ‡ญ","aliases":["western_sahara"]},{"emoji":"๐Ÿณ","aliases":["whale"]},{"emoji":"๐Ÿ‹","aliases":["whale2"]},{"emoji":"โ˜ธ๏ธ","aliases":["wheel_of_dharma"]},{"emoji":"โ™ฟ","aliases":["wheelchair"]},{"emoji":"โœ…","aliases":["white_check_mark"]},{"emoji":"โšช","aliases":["white_circle"]},{"emoji":"๐Ÿณ๏ธ","aliases":["white_flag"]},{"emoji":"๐Ÿ’ฎ","aliases":["white_flower"]},{"emoji":"๐Ÿ‘จโ€๐Ÿฆณ","aliases":["white_haired_man"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆณ","aliases":["white_haired_woman"]},{"emoji":"๐Ÿค","aliases":["white_heart"]},{"emoji":"โฌœ","aliases":["white_large_square"]},{"emoji":"โ—ฝ","aliases":["white_medium_small_square"]},{"emoji":"โ—ป๏ธ","aliases":["white_medium_square"]},{"emoji":"โ–ซ๏ธ","aliases":["white_small_square"]},{"emoji":"๐Ÿ”ณ","aliases":["white_square_button"]},{"emoji":"๐Ÿฅ€","aliases":["wilted_flower"]},{"emoji":"๐ŸŽ","aliases":["wind_chime"]},{"emoji":"๐ŸŒฌ๏ธ","aliases":["wind_face"]},{"emoji":"๐Ÿท","aliases":["wine_glass"]},{"emoji":"๐Ÿ˜‰","aliases":["wink"]},{"emoji":"๐Ÿบ","aliases":["wolf"]},{"emoji":"๐Ÿ‘ฉ","aliases":["woman"]},{"emoji":"๐Ÿ‘ฉโ€๐ŸŽจ","aliases":["woman_artist"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿš€","aliases":["woman_astronaut"]},{"emoji":"๐Ÿคธโ€โ™€๏ธ","aliases":["woman_cartwheeling"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿณ","aliases":["woman_cook"]},{"emoji":"๐Ÿ’ƒ","aliases":["woman_dancing","dancer"]},{"emoji":"๐Ÿคฆโ€โ™€๏ธ","aliases":["woman_facepalming"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿญ","aliases":["woman_factory_worker"]},{"emoji":"๐Ÿ‘ฉโ€๐ŸŒพ","aliases":["woman_farmer"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿš’","aliases":["woman_firefighter"]},{"emoji":"๐Ÿ‘ฉโ€โš•๏ธ","aliases":["woman_health_worker"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆฝ","aliases":["woman_in_manual_wheelchair"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆผ","aliases":["woman_in_motorized_wheelchair"]},{"emoji":"๐Ÿ‘ฉโ€โš–๏ธ","aliases":["woman_judge"]},{"emoji":"๐Ÿคนโ€โ™€๏ธ","aliases":["woman_juggling"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ”ง","aliases":["woman_mechanic"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ’ผ","aliases":["woman_office_worker"]},{"emoji":"๐Ÿ‘ฉโ€โœˆ๏ธ","aliases":["woman_pilot"]},{"emoji":"๐Ÿคพโ€โ™€๏ธ","aliases":["woman_playing_handball"]},{"emoji":"๐Ÿคฝโ€โ™€๏ธ","aliases":["woman_playing_water_polo"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ”ฌ","aliases":["woman_scientist"]},{"emoji":"๐Ÿคทโ€โ™€๏ธ","aliases":["woman_shrugging"]},{"emoji":"๐Ÿ‘ฉโ€๐ŸŽค","aliases":["woman_singer"]},{"emoji":"๐Ÿ‘ฉโ€๐ŸŽ“","aliases":["woman_student"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿซ","aliases":["woman_teacher"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿ’ป","aliases":["woman_technologist"]},{"emoji":"๐Ÿง•","aliases":["woman_with_headscarf"]},{"emoji":"๐Ÿ‘ฉโ€๐Ÿฆฏ","aliases":["woman_with_probing_cane"]},{"emoji":"๐Ÿ‘ณโ€โ™€๏ธ","aliases":["woman_with_turban"]},{"emoji":"๐Ÿ‘š","aliases":["womans_clothes"]},{"emoji":"๐Ÿ‘’","aliases":["womans_hat"]},{"emoji":"๐Ÿคผโ€โ™€๏ธ","aliases":["women_wrestling"]},{"emoji":"๐Ÿšบ","aliases":["womens"]},{"emoji":"๐Ÿฅด","aliases":["woozy_face"]},{"emoji":"๐Ÿ—บ๏ธ","aliases":["world_map"]},{"emoji":"๐Ÿ˜Ÿ","aliases":["worried"]},{"emoji":"๐Ÿ”ง","aliases":["wrench"]},{"emoji":"๐Ÿคผ","aliases":["wrestling"]},{"emoji":"โœ๏ธ","aliases":["writing_hand"]},{"emoji":"โŒ","aliases":["x"]},{"emoji":"๐Ÿงถ","aliases":["yarn"]},{"emoji":"๐Ÿฅฑ","aliases":["yawning_face"]},{"emoji":"๐ŸŸก","aliases":["yellow_circle"]},{"emoji":"๐Ÿ’›","aliases":["yellow_heart"]},{"emoji":"๐ŸŸจ","aliases":["yellow_square"]},{"emoji":"๐Ÿ‡พ๐Ÿ‡ช","aliases":["yemen"]},{"emoji":"๐Ÿ’ด","aliases":["yen"]},{"emoji":"โ˜ฏ๏ธ","aliases":["yin_yang"]},{"emoji":"๐Ÿช€","aliases":["yo_yo"]},{"emoji":"๐Ÿ˜‹","aliases":["yum"]},{"emoji":"๐Ÿ‡ฟ๐Ÿ‡ฒ","aliases":["zambia"]},{"emoji":"๐Ÿคช","aliases":["zany_face"]},{"emoji":"โšก","aliases":["zap"]},{"emoji":"๐Ÿฆ“","aliases":["zebra"]},{"emoji":"0๏ธโƒฃ","aliases":["zero"]},{"emoji":"๐Ÿ‡ฟ๐Ÿ‡ผ","aliases":["zimbabwe"]},{"emoji":"๐Ÿค","aliases":["zipper_mouth_face"]},{"emoji":"๐ŸงŸ","aliases":["zombie"]},{"emoji":"๐ŸงŸโ€โ™‚๏ธ","aliases":["zombie_man"]},{"emoji":"๐ŸงŸโ€โ™€๏ธ","aliases":["zombie_woman"]},{"emoji":"๐Ÿ’ค","aliases":["zzz"]}]
\ No newline at end of file
diff --git a/build/generate-emoji.go b/build/generate-emoji.go
index 6b1b6643cc..00d60acacc 100644
--- a/build/generate-emoji.go
+++ b/build/generate-emoji.go
@@ -19,6 +19,7 @@ import (
 	"sort"
 	"strconv"
 	"strings"
+	"unicode/utf8"
 )
 
 const (
@@ -39,6 +40,7 @@ type Emoji struct {
 	Description    string   `json:"description,omitempty"`
 	Aliases        []string `json:"aliases"`
 	UnicodeVersion string   `json:"unicode_version,omitempty"`
+	SkinTones      bool     `json:"skin_tones,omitempty"`
 }
 
 // Don't include some fields in JSON
@@ -47,6 +49,7 @@ func (e Emoji) MarshalJSON() ([]byte, error) {
 	x := emoji(e)
 	x.UnicodeVersion = ""
 	x.Description = ""
+	x.SkinTones = false
 	return json.Marshal(x)
 }
 
@@ -75,6 +78,7 @@ var replacer = strings.NewReplacer(
 	", Description:", ", ",
 	", Aliases:", ", ",
 	", UnicodeVersion:", ", ",
+	", SkinTones:", ", ",
 )
 
 var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`)
@@ -102,18 +106,20 @@ func generate() ([]byte, error) {
 		return nil, err
 	}
 
-	var re = regexp.MustCompile(`keycap|registered|copyright`)
-	tmp := data[:0]
+	var skinTones = make(map[string]string)
 
-	// filter out emoji that require greater than max unicode version
+	skinTones["\U0001f3fb"] = "Light Skin Tone"
+	skinTones["\U0001f3fc"] = "Medium-Light Skin Tone"
+	skinTones["\U0001f3fd"] = "Medium Skin Tone"
+	skinTones["\U0001f3fe"] = "Medium-Dark Skin Tone"
+	skinTones["\U0001f3ff"] = "Dark Skin Tone"
+
+	var tmp Gemoji
+
+	//filter out emoji that require greater than max unicode version
 	for i := range data {
 		val, _ := strconv.ParseFloat(data[i].UnicodeVersion, 64)
 		if int(val) <= maxUnicodeVersion {
-			// remove these keycaps for now they really complicate matching since
-			// they include normal letters in them
-			if re.MatchString(data[i].Description) {
-				continue
-			}
 			tmp = append(tmp, data[i])
 		}
 	}
@@ -123,7 +129,6 @@ func generate() ([]byte, error) {
 		return data[i].Aliases[0] < data[j].Aliases[0]
 	})
 
-	aliasPairs := make([]string, 0)
 	aliasMap := make(map[string]int, len(data))
 
 	for i, e := range data {
@@ -135,7 +140,6 @@ func generate() ([]byte, error) {
 				continue
 			}
 			aliasMap[a] = i
-			aliasPairs = append(aliasPairs, ":"+a+":", e.Emoji)
 		}
 	}
 
@@ -149,6 +153,43 @@ func generate() ([]byte, error) {
 		data[i].Aliases = append(data[i].Aliases, "laugh")
 	}
 
+	// write a JSON file to use with tribute (write before adding skin tones since we can't support them there yet)
+	file, _ := json.Marshal(data)
+	_ = ioutil.WriteFile("assets/emoji.json", file, 0644)
+
+	// Add skin tones to emoji that support it
+	var (
+		s              []string
+		newEmoji       string
+		newDescription string
+		newData        Emoji
+	)
+
+	for i := range data {
+		if data[i].SkinTones {
+			for k, v := range skinTones {
+				s = strings.Split(data[i].Emoji, "")
+
+				if utf8.RuneCountInString(data[i].Emoji) == 1 {
+					s = append(s, k)
+				} else {
+					// insert into slice after first element because all emoji that support skin tones
+					// have that modifer placed at this spot
+					s = append(s, "")
+					copy(s[2:], s[1:])
+					s[1] = k
+				}
+
+				newEmoji = strings.Join(s, "")
+				newDescription = data[i].Description + ": " + v
+				newAlias := data[i].Aliases[0] + "_" + strings.ReplaceAll(v, " ", "_")
+
+				newData = Emoji{newEmoji, newDescription, []string{newAlias}, "12.0", false}
+				data = append(data, newData)
+			}
+		}
+	}
+
 	// add header
 	str := replacer.Replace(fmt.Sprintf(hdr, gemojiURL, data))
 
@@ -162,10 +203,6 @@ func generate() ([]byte, error) {
 		return "{" + strconv.QuoteToASCII(s)
 	})
 
-	// write a JSON file to use with tribute
-	file, _ := json.Marshal(data)
-	_ = ioutil.WriteFile("assets/emoji.json", file, 0644)
-
 	// format
 	return format.Source([]byte(str))
 }
diff --git a/cmd/doctor.go b/cmd/doctor.go
index f469496cfd..48fd3158a4 100644
--- a/cmd/doctor.go
+++ b/cmd/doctor.go
@@ -85,10 +85,16 @@ var checklist = []check{
 	},
 	{
 		title:         "Check Database Version",
-		name:          "check-db",
+		name:          "check-db-version",
 		isDefault:     true,
 		f:             runDoctorCheckDBVersion,
-		abortIfFailed: true,
+		abortIfFailed: false,
+	},
+	{
+		title:     "Check consistency of database",
+		name:      "check-db-consistency",
+		isDefault: false,
+		f:         runDoctorCheckDBConsistency,
 	},
 	{
 		title:     "Check if OpenSSH authorized_keys file is up-to-date",
@@ -114,6 +120,12 @@ var checklist = []check{
 		isDefault: false,
 		f:         runDoctorPRMergeBase,
 	},
+	{
+		title:     "Recalculate Stars number for all user",
+		name:      "recalculate_stars_number",
+		isDefault: false,
+		f:         runDoctorUserStarNum,
+	},
 	// more checks please append here
 }
 
@@ -488,6 +500,10 @@ func runDoctorPRMergeBase(ctx *cli.Context) ([]string, error) {
 	return results, err
 }
 
+func runDoctorUserStarNum(ctx *cli.Context) ([]string, error) {
+	return nil, models.DoctorUserStarNum()
+}
+
 func runDoctorScriptType(ctx *cli.Context) ([]string, error) {
 	path, err := exec.LookPath(setting.ScriptType)
 	if err != nil {
@@ -495,3 +511,96 @@ func runDoctorScriptType(ctx *cli.Context) ([]string, error) {
 	}
 	return []string{fmt.Sprintf("ScriptType %s is on the current PATH at %s", setting.ScriptType, path)}, nil
 }
+
+func runDoctorCheckDBConsistency(ctx *cli.Context) ([]string, error) {
+	var results []string
+
+	// make sure DB version is uptodate
+	if err := models.NewEngine(context.Background(), migrations.EnsureUpToDate); err != nil {
+		return nil, fmt.Errorf("model version on the database does not match the current Gitea version. Model consistency will not be checked until the database is upgraded")
+	}
+
+	//find labels without existing repo or org
+	count, err := models.CountOrphanedLabels()
+	if err != nil {
+		return nil, err
+	}
+	if count > 0 {
+		if ctx.Bool("fix") {
+			if err = models.DeleteOrphanedLabels(); err != nil {
+				return nil, err
+			}
+			results = append(results, fmt.Sprintf("%d labels without existing repository/organisation deleted", count))
+		} else {
+			results = append(results, fmt.Sprintf("%d labels without existing repository/organisation", count))
+		}
+	}
+
+	//find issues without existing repository
+	count, err = models.CountOrphanedIssues()
+	if err != nil {
+		return nil, err
+	}
+	if count > 0 {
+		if ctx.Bool("fix") {
+			if err = models.DeleteOrphanedIssues(); err != nil {
+				return nil, err
+			}
+			results = append(results, fmt.Sprintf("%d issues without existing repository deleted", count))
+		} else {
+			results = append(results, fmt.Sprintf("%d issues without existing repository", count))
+		}
+	}
+
+	//find pulls without existing issues
+	count, err = models.CountOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id")
+	if err != nil {
+		return nil, err
+	}
+	if count > 0 {
+		if ctx.Bool("fix") {
+			if err = models.DeleteOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id"); err != nil {
+				return nil, err
+			}
+			results = append(results, fmt.Sprintf("%d pull requests without existing issue deleted", count))
+		} else {
+			results = append(results, fmt.Sprintf("%d pull requests without existing issue", count))
+		}
+	}
+
+	//find tracked times without existing issues/pulls
+	count, err = models.CountOrphanedObjects("tracked_time", "issue", "tracked_time.issue_id=issue.id")
+	if err != nil {
+		return nil, err
+	}
+	if count > 0 {
+		if ctx.Bool("fix") {
+			if err = models.DeleteOrphanedObjects("tracked_time", "issue", "tracked_time.issue_id=issue.id"); err != nil {
+				return nil, err
+			}
+			results = append(results, fmt.Sprintf("%d tracked times without existing issue deleted", count))
+		} else {
+			results = append(results, fmt.Sprintf("%d tracked times without existing issue", count))
+		}
+	}
+
+	count, err = models.CountNullArchivedRepository()
+	if err != nil {
+		return nil, err
+	}
+	if count > 0 {
+		if ctx.Bool("fix") {
+			updatedCount, err := models.FixNullArchivedRepository()
+			if err != nil {
+				return nil, err
+			}
+			results = append(results, fmt.Sprintf("%d repositories with null is_archived updated", updatedCount))
+		} else {
+			results = append(results, fmt.Sprintf("%d repositories with null is_archived", count))
+		}
+	}
+
+	//ToDo: function to recalc all counters
+
+	return results, nil
+}
diff --git a/cmd/dump.go b/cmd/dump.go
index 774b1d5d50..93f2f7aac1 100644
--- a/cmd/dump.go
+++ b/cmd/dump.go
@@ -66,6 +66,10 @@ func fatal(format string, args ...interface{}) {
 
 func runDump(ctx *cli.Context) error {
 	setting.NewContext()
+	if !setting.InstallLock {
+		log.Error("Is '%s' really the right config path?\n", setting.CustomConf)
+		return fmt.Errorf("gitea is not initialized")
+	}
 	setting.NewServices() // cannot access session settings otherwise
 
 	err := models.SetEngine()
diff --git a/cmd/generate.go b/cmd/generate.go
index 4e91b1d3f0..13a99c94f4 100644
--- a/cmd/generate.go
+++ b/cmd/generate.go
@@ -7,9 +7,11 @@ package cmd
 
 import (
 	"fmt"
+	"os"
 
 	"code.gitea.io/gitea/modules/generate"
 
+	"github.com/mattn/go-isatty"
 	"github.com/urfave/cli"
 )
 
@@ -59,7 +61,12 @@ func runGenerateInternalToken(c *cli.Context) error {
 		return err
 	}
 
-	fmt.Printf("%s\n", internalToken)
+	fmt.Printf("%s", internalToken)
+
+	if isatty.IsTerminal(os.Stdout.Fd()) {
+		fmt.Printf("\n")
+	}
+
 	return nil
 }
 
@@ -69,7 +76,12 @@ func runGenerateLfsJwtSecret(c *cli.Context) error {
 		return err
 	}
 
-	fmt.Printf("%s\n", JWTSecretBase64)
+	fmt.Printf("%s", JWTSecretBase64)
+
+	if isatty.IsTerminal(os.Stdout.Fd()) {
+		fmt.Printf("\n")
+	}
+
 	return nil
 }
 
@@ -79,6 +91,11 @@ func runGenerateSecretKey(c *cli.Context) error {
 		return err
 	}
 
-	fmt.Printf("%s\n", secretKey)
+	fmt.Printf("%s", secretKey)
+
+	if isatty.IsTerminal(os.Stdout.Fd()) {
+		fmt.Printf("\n")
+	}
+
 	return nil
 }
diff --git a/custom/conf/app.ini.sample b/custom/conf/app.ini.sample
index c8797ca56a..a5570136ba 100644
--- a/custom/conf/app.ini.sample
+++ b/custom/conf/app.ini.sample
@@ -50,6 +50,8 @@ DISABLED_REPO_UNITS =
 DEFAULT_REPO_UNITS = repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki
 ; Prefix archive files by placing them in a directory named after the repository
 PREFIX_ARCHIVE_FILES = true
+; The default branch name of new repositories
+DEFAULT_BRANCH=master
 
 [repository.editor]
 ; List of file extensions for which lines should be wrapped in the Monaco editor
@@ -209,14 +211,17 @@ MIN_TIMEOUT = 10s
 MAX_TIMEOUT = 60s
 TIMEOUT_STEP = 10s
 ; This setting determines how often the db is queried to get the latest notification counts.
-; If the browser client supports EventSource, it will be used in preference to polling notification.
+; If the browser client supports EventSource and SharedWorker, a SharedWorker will be used in preference to polling notification. Set to -1 to disable the EventSource
 EVENT_SOURCE_UPDATE_TIME = 10s
 
 [markdown]
 ; Render soft line breaks as hard line breaks, which means a single newline character between
 ; paragraphs will cause a line break and adding trailing whitespace to paragraphs is not
 ; necessary to force a line break.
-ENABLE_HARD_LINE_BREAK = true
+; Render soft line breaks as hard line breaks for comments
+ENABLE_HARD_LINE_BREAK_IN_COMMENTS = true
+; Render soft line breaks as hard line breaks for markdown documents
+ENABLE_HARD_LINE_BREAK_IN_DOCUMENTS = false
 ; Comma separated list of custom URL-Schemes that are allowed as links when rendering Markdown
 ; for example git,magnet,ftp (more at https://en.wikipedia.org/wiki/List_of_URI_schemes)
 ; URLs starting with http and https are always displayed, whatever is put in this entry.
@@ -934,8 +939,8 @@ JWT_SECRET=Bk0yK7Y9g_p56v86KaHqjSbxvNvu3SbKoOdOt2ZcXvU
 MAX_TOKEN_LENGTH=32767
 
 [i18n]
-LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR
-NAMES = English,็ฎ€ไฝ“ไธญๆ–‡,็น้ซ”ไธญๆ–‡๏ผˆ้ฆ™ๆธฏ๏ผ‰,็น้ซ”ไธญๆ–‡๏ผˆๅฐ็ฃ๏ผ‰,Deutsch,franรงais,Nederlands,latvieลกu,ั€ัƒััะบะธะน,ะฃะบั€ะฐั—ะฝััŒะบะฐ,ๆ—ฅๆœฌ่ชž,espaรฑol,portuguรชs do Brasil,polski,ะฑัŠะปะณะฐั€ัะบะธ,italiano,suomi,Tรผrkรงe,ฤeลกtina,ัั€ะฟัะบะธ,svenska,ํ•œ๊ตญ์–ด
+LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pt-PT,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR
+NAMES = English,็ฎ€ไฝ“ไธญๆ–‡,็น้ซ”ไธญๆ–‡๏ผˆ้ฆ™ๆธฏ๏ผ‰,็น้ซ”ไธญๆ–‡๏ผˆๅฐ็ฃ๏ผ‰,Deutsch,franรงais,Nederlands,latvieลกu,ั€ัƒััะบะธะน,ะฃะบั€ะฐั—ะฝััŒะบะฐ,ๆ—ฅๆœฌ่ชž,espaรฑol,portuguรชs do Brasil,Portuguรชs de Portugal,polski,ะฑัŠะปะณะฐั€ัะบะธ,italiano,suomi,Tรผrkรงe,ฤeลกtina,ัั€ะฟัะบะธ,svenska,ํ•œ๊ตญ์–ด
 
 ; Used for datetimepicker
 [i18n.datelang]
@@ -952,6 +957,7 @@ uk-UA = uk
 ja-JP = ja
 es-ES = es
 pt-BR = pt-BR
+pt-PT = pt
 pl-PL = pl
 bg-BG = bg
 it-IT = it
diff --git a/docker/Makefile b/docker/Makefile
index 7824847e54..bd4cb176bd 100644
--- a/docker/Makefile
+++ b/docker/Makefile
@@ -11,4 +11,4 @@ docker:
 
 .PHONY: docker-build
 docker-build:
-	docker run -ti --rm -v $(CURDIR):/srv/app/src/code.gitea.io/gitea -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" LDFLAGS="$(LDFLAGS)" webhippie/golang:edge make clean build
+	docker run -ti --rm -v $(CURDIR):/srv/app/src/code.gitea.io/gitea -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" LDFLAGS="$(LDFLAGS)" CGO_EXTRA_CFLAGS="$(CGO_EXTRA_CFLAGS)" webhippie/golang:edge make clean build
diff --git a/docs/config.yaml b/docs/config.yaml
index 1e6abb07e5..94f8704600 100644
--- a/docs/config.yaml
+++ b/docs/config.yaml
@@ -312,3 +312,50 @@ languages:
           url: https://discourse.gitea.io/
           weight: 80
           pre: group
+
+  pt-pt:
+    weight: 6
+    languageName: Portuguรชs de Portugal
+    menu:
+      page:
+        - name: Pรกgina inicial
+          url: https://gitea.io/pt-pt/
+          weight: 10
+          pre: home
+        - name: Documentaรงรฃo
+          url: /pt-pt/
+          weight: 20
+          pre: question
+          post: active
+        - name: API
+          url: https://try.gitea.io/api/swagger
+          weight: 45
+          pre: plug
+        - name: Blog
+          url: https://blog.gitea.io/
+          weight: 30
+          pre: rss
+        - name: Cรณdigo-fonte
+          url: https://code.gitea.io/
+          weight: 40
+          pre: code
+        - name: Traduรงรฃo
+          url: https://crowdin.com/project/gitea
+          weight: 41
+          pre: language
+        - name: Descarregamentos
+          url: https://dl.gitea.io/
+          weight: 50
+          pre: download
+        - name: GitHub
+          url: https://github.com/go-gitea/
+          weight: 60
+          pre: github
+        - name: Discussรฃo no Discord
+          url: https://discord.gg/Gitea
+          weight: 70
+          pre: comment
+        - name: Fรณrum
+          url: https://discourse.gitea.io/
+          weight: 80
+          pre: group
diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md
index 3ad24776ff..952d5a2938 100644
--- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md
+++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md
@@ -69,6 +69,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
 - `ENABLE_PUSH_CREATE_USER`:  **false**: Allow users to push local repositories to Gitea and have them automatically created for a user.
 - `ENABLE_PUSH_CREATE_ORG`:  **false**: Allow users to push local repositories to Gitea and have them automatically created for an org.
 - `PREFIX_ARCHIVE_FILES`: **true**: Prefix archive files by placing them in a directory named after the repository.
+- `DEFAULT_BRANCH`: **master**: Default branch name of all repositories.
 
 ### Repository - Pull Request (`repository.pull-request`)
 
@@ -147,12 +148,14 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
 - `MIN_TIMEOUT`: **10s**: These options control how often notification endpoint is polled to update the notification count. On page load the notification count will be checked after `MIN_TIMEOUT`. The timeout will increase to `MAX_TIMEOUT` by `TIMEOUT_STEP` if the notification count is unchanged. Set MIN_TIMEOUT to 0 to turn off.
 - `MAX_TIMEOUT`: **60s**.
 - `TIMEOUT_STEP`: **10s**.
-- `EVENT_SOURCE_UPDATE_TIME`: **10s**: This setting determines how often the database is queried to update notification counts. If the browser client supports `EventSource`, it will be used in preference to polling notification endpoint.
-
+- `EVENT_SOURCE_UPDATE_TIME`: **10s**: This setting determines how often the database is queried to update notification counts. If the browser client supports `EventSource` and `SharedWorker`, a `SharedWorker` will be used in preference to polling notification endpoint. Set to **-1** to disable the `EventSource`.
 
 ## Markdown (`markdown`)
 
-- `ENABLE_HARD_LINE_BREAK`: **true**: Render soft line breaks as hard line breaks, which
+- `ENABLE_HARD_LINE_BREAK_IN_COMMENTS`: **true**: Render soft line breaks as hard line breaks in comments, which
+  means a single newline character between paragraphs will cause a line break and adding
+  trailing whitespace to paragraphs is not necessary to force a line break.
+- `ENABLE_HARD_LINE_BREAK_IN_DOCUMENTS`: **false**: Render soft line breaks as hard line breaks in documents, which
   means a single newline character between paragraphs will cause a line break and adding
   trailing whitespace to paragraphs is not necessary to force a line break.
 - `CUSTOM_URL_SCHEMES`: Use a comma separated list (ftp,git,svn) to indicate additional
@@ -602,8 +605,8 @@ NB: You must `REDIRECT_MACARON_LOG` and have `DISABLE_ROUTER_LOG` set to `false`
 
 ## i18n (`i18n`)
 
-- `LANGS`: **en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR**: List of locales shown in language selector
-- `NAMES`: **English,็ฎ€ไฝ“ไธญๆ–‡,็น้ซ”ไธญๆ–‡๏ผˆ้ฆ™ๆธฏ๏ผ‰,็น้ซ”ไธญๆ–‡๏ผˆๅฐ็ฃ๏ผ‰,Deutsch,franรงais,Nederlands,latvieลกu,ั€ัƒััะบะธะน,ๆ—ฅๆœฌ่ชž,espaรฑol,portuguรชs do Brasil,polski,ะฑัŠะปะณะฐั€ัะบะธ,italiano,suomi,Tรผrkรงe,ฤeลกtina,ัั€ะฟัะบะธ,svenska,ํ•œ๊ตญ์–ด**: Visible names corresponding to the locales
+- `LANGS`: **en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pt-PT,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR**: List of locales shown in language selector
+- `NAMES`: **English,็ฎ€ไฝ“ไธญๆ–‡,็น้ซ”ไธญๆ–‡๏ผˆ้ฆ™ๆธฏ๏ผ‰,็น้ซ”ไธญๆ–‡๏ผˆๅฐ็ฃ๏ผ‰,Deutsch,franรงais,Nederlands,latvieลกu,ั€ัƒััะบะธะน,ๆ—ฅๆœฌ่ชž,espaรฑol,portuguรชs do Brasil,Portuguรชs de Portugal,polski,ะฑัŠะปะณะฐั€ัะบะธ,italiano,suomi,Tรผrkรงe,ฤeลกtina,ัั€ะฟัะบะธ,svenska,ํ•œ๊ตญ์–ด**: Visible names corresponding to the locales
 
 ### i18n - Datepicker Language (`i18n.datelang`)
 Maps locales to the languages used by the datepicker plugin
@@ -620,6 +623,7 @@ Maps locales to the languages used by the datepicker plugin
 - `ja-JP`: **ja**
 - `es-ES`: **es**
 - `pt-BR`: **pt-BR**
+- `pt-PT`: **pt**
 - `pl-PL`: **pl**
 - `bg-BG`: **bg**
 - `it-IT`: **it**
diff --git a/docs/content/doc/installation/from-source.en-us.md b/docs/content/doc/installation/from-source.en-us.md
index d70e000352..83e480be23 100644
--- a/docs/content/doc/installation/from-source.en-us.md
+++ b/docs/content/doc/installation/from-source.en-us.md
@@ -141,7 +141,7 @@ Gitea will search for a number of things from the `CustomPath`. By default this
 the `custom/` directory in the current working directory when running Gitea. It will also
 look for its configuration file `CustomConf` in `$CustomPath/conf/app.ini`, and will use the
 current working directory as the relative base path `AppWorkPath` for a number configurable
-values.
+values. Finally the static files will be served from `StaticRootPath` which defaults to the `AppWorkPath`.
 
 These values, although useful when developing, may conflict with downstream users preferences.
 
@@ -152,6 +152,7 @@ using the `LDFLAGS` environment variable for `make`. The appropriate settings ar
 * To set the `CustomPath` use `LDFLAGS="-X \"code.gitea.io/gitea/modules/setting.CustomPath=custom-path\""`
 * For `CustomConf` you should use `-X \"code.gitea.io/gitea/modules/setting.CustomConf=conf.ini\"`
 * For `AppWorkPath` you should use `-X \"code.gitea.io/gitea/modules/setting.AppWorkPath=working-path\"`
+* For `StaticRootPath` you should use `-X \"code.gitea.io/gitea/modules/setting.StaticRootPath=static-root-path\"`
 
 Add as many of the strings with their preceding `-X` to the `LDFLAGS` variable and run `make build`
 with the appropriate `TAGS` as above.
diff --git a/go.mod b/go.mod
index 970e65f3a6..da592e3970 100644
--- a/go.mod
+++ b/go.mod
@@ -15,7 +15,7 @@ require (
 	gitea.com/macaron/i18n v0.0.0-20190822004228-474e714e2223
 	gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a
 	gitea.com/macaron/macaron v1.4.0
-	gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d
+	gitea.com/macaron/session v0.0.0-20200902202411-e3a87877db6e
 	gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7
 	github.com/BurntSushi/toml v0.3.1
 	github.com/PuerkitoBio/goquery v1.5.0
@@ -37,9 +37,9 @@ require (
 	github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 // indirect
 	github.com/gliderlabs/ssh v0.2.2
 	github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a // indirect
-	github.com/go-enry/go-enry/v2 v2.3.0
+	github.com/go-enry/go-enry/v2 v2.5.2
 	github.com/go-git/go-billy/v5 v5.0.0
-	github.com/go-git/go-git/v5 v5.0.0
+	github.com/go-git/go-git/v5 v5.1.0
 	github.com/go-openapi/jsonreference v0.19.3 // indirect
 	github.com/go-redis/redis v6.15.2+incompatible
 	github.com/go-sql-driver/mysql v1.4.1
@@ -48,7 +48,8 @@ require (
 	github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28
 	github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
 	github.com/golang/protobuf v1.4.1 // indirect
-	github.com/google/go-github/v24 v24.0.1
+	github.com/google/go-github/v32 v32.1.0
+	github.com/google/uuid v1.1.1
 	github.com/gorilla/context v1.1.1
 	github.com/hashicorp/go-retryablehttp v0.6.6 // indirect
 	github.com/huandu/xstrings v1.3.0
@@ -74,7 +75,7 @@ require (
 	github.com/microcosm-cc/bluemonday v1.0.3-0.20191119130333-0a75d7616912
 	github.com/mitchellh/go-homedir v1.1.0
 	github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
-	github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5
+	github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
 	github.com/niklasfasching/go-org v0.1.9
 	github.com/oliamb/cutter v0.2.2
 	github.com/olivere/elastic/v7 v7.0.9
@@ -85,7 +86,6 @@ require (
 	github.com/prometheus/procfs v0.0.4 // indirect
 	github.com/quasoft/websspi v1.0.0
 	github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 // indirect
-	github.com/satori/go.uuid v1.2.0
 	github.com/sergi/go-diff v1.1.0
 	github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b // indirect
 	github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
@@ -102,10 +102,10 @@ require (
 	github.com/yohcop/openid-go v1.0.0
 	github.com/yuin/goldmark v1.1.25
 	github.com/yuin/goldmark-meta v0.0.0-20191126180153-f0638e958b60
-	golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79
-	golang.org/x/net v0.0.0-20200506145744-7e3656a0809f
+	golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9
+	golang.org/x/net v0.0.0-20200602114024-627f9648deb9
 	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
-	golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f
+	golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1
 	golang.org/x/text v0.3.2
 	golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect
 	golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224
@@ -117,7 +117,7 @@ require (
 	gopkg.in/ldap.v3 v3.0.2
 	gopkg.in/testfixtures.v2 v2.5.0
 	gopkg.in/yaml.v2 v2.2.8
-	mvdan.cc/xurls/v2 v2.1.0
+	mvdan.cc/xurls/v2 v2.2.0
 	strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
 	xorm.io/builder v0.3.7
 	xorm.io/xorm v1.0.1
diff --git a/go.sum b/go.sum
index df82fcc43c..e1a118e33d 100644
--- a/go.sum
+++ b/go.sum
@@ -37,8 +37,8 @@ gitea.com/macaron/macaron v1.4.0 h1:FY1QDGqyuUzs21K6ChkbYbRUfwL7v2aUrhNEJ0IgsAw=
 gitea.com/macaron/macaron v1.4.0/go.mod h1:P7hfDbQjcW22lkYkXlxdRIfWOXxH2+K4EogN4Q0UlLY=
 gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705 h1:mvkQGAlON1Z6Y8pqa/+FpYIskk54mazuECUfZK5oTg0=
 gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705/go.mod h1:1ujH0jD6Ca4iK9NL0Q2a7fG2chvXx5hVa7hBfABwpkA=
-gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d h1:XLww3CvnFZkXVwauN67fniDaIpIqsE+9KVcxlZKlvLU=
-gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d/go.mod h1:FanKy3WjWb5iw/iZBPk4ggoQT9FcM6bkBPvmDmsH6tY=
+gitea.com/macaron/session v0.0.0-20200902202411-e3a87877db6e h1:BHoJ/xWNt6FrVsL54JennM9HPIQlnbmRvmaC5DO65pU=
+gitea.com/macaron/session v0.0.0-20200902202411-e3a87877db6e/go.mod h1:FanKy3WjWb5iw/iZBPk4ggoQT9FcM6bkBPvmDmsH6tY=
 gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 h1:N9QFoeNsUXLhl14mefLzGluqV7w2mGU3u+iZU+jCeWk=
 gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7/go.mod h1:kgsbFPPS4P+acDYDOPDa3N4IWWOuDJt5/INKRUz7aks=
 gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
@@ -193,18 +193,18 @@ github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a h1:FQqo
 github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
 github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31 h1:gclg6gY70GLy3PbkQ1AERPfmLMMagS60DKF78eWwLn8=
 github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
-github.com/go-enry/go-enry/v2 v2.3.0 h1:o8KwgY6uSplysrIpj+Y42J/xGPp90ogVpxE2Z3s8Unk=
-github.com/go-enry/go-enry/v2 v2.3.0/go.mod h1:+xFJwbqWi15bvqFHb2ELUWVRKFQtwB61+sDrkvvxxGI=
-github.com/go-enry/go-oniguruma v1.2.0 h1:oBO9XC1IDT9+AoWW5oFsa/7gFeOPacEqDbyXZKWXuDs=
-github.com/go-enry/go-oniguruma v1.2.0/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
+github.com/go-enry/go-enry/v2 v2.5.2 h1:3f3PFAO6JitWkPi1GQ5/m6Xu4gNL1U5soJ8QaYqJ0YQ=
+github.com/go-enry/go-enry/v2 v2.5.2/go.mod h1:GVzIiAytiS5uT/QiuakK7TF1u4xDab87Y8V5EJRpsIQ=
+github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=
+github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
 github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
 github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
 github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
 github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
 github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp/pqnefH+Bc=
 github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
-github.com/go-git/go-git/v5 v5.0.0 h1:k5RWPm4iJwYtfWoxIJy4wJX9ON7ihPeZZYC1fLYDnpg=
-github.com/go-git/go-git/v5 v5.0.0/go.mod h1:oYD8y9kWsGINPFJoLdaScGCN6dlKg23blmClfZwtUVA=
+github.com/go-git/go-git/v5 v5.1.0 h1:HxJn9g/E7eYvKW3Fm7Jt4ee8LXfPOm/H1cdDu8vEssk=
+github.com/go-git/go-git/v5 v5.1.0/go.mod h1:ZKfuPUoY1ZqIG4QG9BDBh3G4gLM5zvPuSJAozQrZuyM=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
@@ -315,10 +315,8 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
-github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
-github.com/google/go-github/v24 v24.0.1 h1:KCt1LjMJEey1qvPXxa9SjaWxwTsCWSq6p2Ju57UR4Q4=
-github.com/google/go-github/v24 v24.0.1/go.mod h1:CRqaW1Uns1TCkP0wqTpxYyRxRjxwvKU/XSS44u6X74M=
+github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II=
+github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
 github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
 github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -371,6 +369,8 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/huandu/xstrings v1.3.0 h1:gvV6jG9dTgFEncxo+AF7PH6MZXi/vZl25owA/8Dg8Wo=
 github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
+github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
+github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/issue9/assert v1.3.1/go.mod h1:9Ger+iz8X7r1zMYYwEhh++2wMGWcNN2oVI+zIQXxcio=
 github.com/issue9/assert v1.3.2 h1:IaTa37u4m1fUuTH9K9ldO5IONKVDXjLiUO1T9vj0OF0=
@@ -483,8 +483,8 @@ github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOl
 github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc h1:z1PgdCCmYYVL0BoJTUgmAq1p7ca8fzYIPsNyfsN3xAU=
 github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc/go.mod h1:np1wUFZ6tyoke22qDJZY40URn9Ae51gX7ljIWXN5TJs=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY=
-github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/niklasfasching/go-org v0.1.9 h1:Toz8WMIt+qJb52uYEk1YD/muLuOOmRt1CfkV+bKVMkI=
@@ -554,10 +554,9 @@ github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqn
 github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 h1:YDeskXpkNDhPdWN3REluVa46HQOVuVkjkd2sWnrABNQ=
 github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
-github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
-github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b h1:4kg1wyftSKxLtnPAvcRWakIPpokB9w780/KwrNLnfPA=
@@ -616,8 +615,6 @@ github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDW
 github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ=
 github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
-github.com/toqueteos/trie v1.0.0 h1:8i6pXxNUXNRAqP246iibb7w/pSFquNTQ+uNfriG7vlk=
-github.com/toqueteos/trie v1.0.0/go.mod h1:Ywk48QhEqhU1+DwhMkJ2x7eeGxDHiGkAdc9+0DYcbsM=
 github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
 github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
 github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ=
@@ -666,7 +663,6 @@ go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
-golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -683,8 +679,8 @@ golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
 golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88=
-golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
+golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
@@ -723,8 +719,8 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200506145744-7e3656a0809f h1:QBjCr1Fz5kw158VqdE9JfI9cJnl/ymnJWAdMuinqL7Y=
-golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -739,7 +735,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -771,8 +766,8 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0
 golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f h1:mOhmO9WsBaJCNmaZHPtHs9wOcdqdKCjF6OPJlmDM3KI=
-golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
@@ -858,6 +853,7 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
@@ -876,8 +872,6 @@ gopkg.in/testfixtures.v2 v2.5.0 h1:N08B7l2GzFQenyYbzqthDnKAA+cmb17iAZhhFxr7JHw=
 gopkg.in/testfixtures.v2 v2.5.0/go.mod h1:vyAq+MYCgNpR29qitQdLZhdbLFf4mR/2MFJRFoQZZ2M=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
-gopkg.in/toqueteos/substring.v1 v1.0.2 h1:urLqCeMm6x/eTuQa1oZerNw8N1KNOIp5hD5kGL7lFsE=
-gopkg.in/toqueteos/substring.v1 v1.0.2/go.mod h1:Eb2Z1UYehlVK8LYW2WBVR2rwbujsz3aX8XDrM1vbNew=
 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
 gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
@@ -893,8 +887,7 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
-mvdan.cc/xurls/v2 v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA=
-mvdan.cc/xurls/v2 v2.1.0/go.mod h1:5GrSd9rOnKOpZaji1OZLYL/yeAAtGDlo/cFe+8K5n8E=
+mvdan.cc/xurls/v2 v2.2.0/go.mod h1:EV1RMtya9D6G5DMYPGD8zTQzaHet6Jh8gFlRgGRJeO8=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs=
 strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
diff --git a/integrations/api_gpg_keys_test.go b/integrations/api_gpg_keys_test.go
index edae22205e..e664c3c256 100644
--- a/integrations/api_gpg_keys_test.go
+++ b/integrations/api_gpg_keys_test.go
@@ -32,7 +32,7 @@ func TestGPGKeys(t *testing.T) {
 			results: []int{http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized, http.StatusUnauthorized},
 		},
 		{name: "LoggedAsUser2", makeRequest: session.MakeRequest, token: token,
-			results: []int{http.StatusOK, http.StatusOK, http.StatusNotFound, http.StatusNoContent, http.StatusInternalServerError, http.StatusInternalServerError, http.StatusCreated, http.StatusCreated}},
+			results: []int{http.StatusOK, http.StatusOK, http.StatusNotFound, http.StatusNoContent, http.StatusUnprocessableEntity, http.StatusNotFound, http.StatusCreated, http.StatusCreated}},
 	}
 
 	for _, tc := range tt {
diff --git a/integrations/api_helper_for_declarative_test.go b/integrations/api_helper_for_declarative_test.go
index ec7f1d7496..ae6f0e5e59 100644
--- a/integrations/api_helper_for_declarative_test.go
+++ b/integrations/api_helper_for_declarative_test.go
@@ -5,14 +5,17 @@
 package integrations
 
 import (
+	"context"
 	"encoding/json"
 	"fmt"
 	"io/ioutil"
 	"net/http"
 	"testing"
+	"time"
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/auth"
+	"code.gitea.io/gitea/modules/queue"
 	api "code.gitea.io/gitea/modules/structs"
 
 	"github.com/stretchr/testify/assert"
@@ -224,11 +227,25 @@ func doAPIMergePullRequest(ctx APITestContext, owner, repo string, index int64)
 			Do:                string(models.MergeStyleMerge),
 		})
 
-		if ctx.ExpectedCode != 0 {
-			ctx.Session.MakeRequest(t, req, ctx.ExpectedCode)
-			return
+		resp := ctx.Session.MakeRequest(t, req, NoExpectedStatus)
+
+		if resp.Code == http.StatusMethodNotAllowed {
+			err := api.APIError{}
+			DecodeJSON(t, resp, &err)
+			assert.EqualValues(t, "Please try again later", err.Message)
+			queue.GetManager().FlushAll(context.Background(), 5*time.Second)
+			resp = ctx.Session.MakeRequest(t, req, NoExpectedStatus)
+		}
+
+		expected := ctx.ExpectedCode
+		if expected == 0 {
+			expected = 200
+		}
+
+		if !assert.EqualValues(t, expected, resp.Code,
+			"Request: %s %s", req.Method, req.URL.String()) {
+			logUnexpectedResponse(t, resp)
 		}
-		ctx.Session.MakeRequest(t, req, 200)
 	}
 }
 
diff --git a/integrations/api_notification_test.go b/integrations/api_notification_test.go
index 3296604a08..4204173420 100644
--- a/integrations/api_notification_test.go
+++ b/integrations/api_notification_test.go
@@ -55,7 +55,7 @@ func TestAPINotification(t *testing.T) {
 	assert.EqualValues(t, false, apiNL[2].Pinned)
 
 	// -- GET /repos/{owner}/{repo}/notifications --
-	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/notifications?token=%s", user2.Name, repo1.Name, token))
+	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/notifications?status-types=unread&token=%s", user2.Name, repo1.Name, token))
 	resp = session.MakeRequest(t, req, http.StatusOK)
 	DecodeJSON(t, resp, &apiNL)
 
@@ -92,7 +92,7 @@ func TestAPINotification(t *testing.T) {
 	assert.True(t, new.New > 0)
 
 	// -- mark notifications as read --
-	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?token=%s", token))
+	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?status-types=unread&token=%s", token))
 	resp = session.MakeRequest(t, req, http.StatusOK)
 	DecodeJSON(t, resp, &apiNL)
 	assert.Len(t, apiNL, 2)
@@ -101,7 +101,7 @@ func TestAPINotification(t *testing.T) {
 	req = NewRequest(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/%s/notifications?last_read_at=%s&token=%s", user2.Name, repo1.Name, lastReadAt, token))
 	resp = session.MakeRequest(t, req, http.StatusResetContent)
 
-	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?token=%s", token))
+	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?status-types=unread&token=%s", token))
 	resp = session.MakeRequest(t, req, http.StatusOK)
 	DecodeJSON(t, resp, &apiNL)
 	assert.Len(t, apiNL, 1)
diff --git a/integrations/api_pull_review_test.go b/integrations/api_pull_review_test.go
index c90a5c11cd..28eed87255 100644
--- a/integrations/api_pull_review_test.go
+++ b/integrations/api_pull_review_test.go
@@ -43,7 +43,7 @@ func TestAPIPullReview(t *testing.T) {
 	assert.EqualValues(t, 10, reviews[5].ID)
 	assert.EqualValues(t, "REQUEST_CHANGES", reviews[5].State)
 	assert.EqualValues(t, 1, reviews[5].CodeCommentsCount)
-	assert.EqualValues(t, 0, reviews[5].Reviewer.ID) // ghost user
+	assert.EqualValues(t, -1, reviews[5].Reviewer.ID) // ghost user
 	assert.EqualValues(t, false, reviews[5].Stale)
 	assert.EqualValues(t, true, reviews[5].Official)
 
@@ -86,6 +86,11 @@ func TestAPIPullReview(t *testing.T) {
 			Body:       "first old line",
 			OldLineNum: 1,
 			NewLineNum: 0,
+		}, {
+			Path:       "iso-8859-1.txt",
+			Body:       "this line contains a non-utf-8 character",
+			OldLineNum: 0,
+			NewLineNum: 1,
 		},
 		},
 	})
@@ -93,7 +98,7 @@ func TestAPIPullReview(t *testing.T) {
 	DecodeJSON(t, resp, &review)
 	assert.EqualValues(t, 6, review.ID)
 	assert.EqualValues(t, "PENDING", review.State)
-	assert.EqualValues(t, 2, review.CodeCommentsCount)
+	assert.EqualValues(t, 3, review.CodeCommentsCount)
 
 	// test SubmitPullReview
 	req = NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/reviews/%d?token=%s", repo.OwnerName, repo.Name, pullIssue.Index, review.ID, token), &api.SubmitPullReviewOptions{
@@ -104,7 +109,7 @@ func TestAPIPullReview(t *testing.T) {
 	DecodeJSON(t, resp, &review)
 	assert.EqualValues(t, 6, review.ID)
 	assert.EqualValues(t, "APPROVED", review.State)
-	assert.EqualValues(t, 2, review.CodeCommentsCount)
+	assert.EqualValues(t, 3, review.CodeCommentsCount)
 
 	// test DeletePullReview
 	req = NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/reviews?token=%s", repo.OwnerName, repo.Name, pullIssue.Index, token), &api.CreatePullReviewOptions{
diff --git a/integrations/api_pull_test.go b/integrations/api_pull_test.go
index 9e22be5755..61daf917ff 100644
--- a/integrations/api_pull_test.go
+++ b/integrations/api_pull_test.go
@@ -58,7 +58,7 @@ func TestAPIMergePullWIP(t *testing.T) {
 	session.MakeRequest(t, req, http.StatusMethodNotAllowed)
 }
 
-func TestAPICreatePullSuccess1(t *testing.T) {
+func TestAPICreatePullSuccess(t *testing.T) {
 	defer prepareTestEnv(t)()
 	repo10 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 10}).(*models.Repository)
 	// repo10 have code, pulls units.
@@ -78,7 +78,7 @@ func TestAPICreatePullSuccess1(t *testing.T) {
 	session.MakeRequest(t, req, 201)
 }
 
-func TestAPICreatePullSuccess2(t *testing.T) {
+func TestAPIEditPull(t *testing.T) {
 	defer prepareTestEnv(t)()
 	repo10 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 10}).(*models.Repository)
 	owner10 := models.AssertExistsAndLoadBean(t, &models.User{ID: repo10.OwnerID}).(*models.User)
@@ -90,6 +90,21 @@ func TestAPICreatePullSuccess2(t *testing.T) {
 		Base:  "master",
 		Title: "create a success pr",
 	})
+	pull := new(api.PullRequest)
+	resp := session.MakeRequest(t, req, 201)
+	DecodeJSON(t, resp, pull)
+	assert.EqualValues(t, "master", pull.Base.Name)
 
-	session.MakeRequest(t, req, 201)
+	req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d?token=%s", owner10.Name, repo10.Name, pull.Index, token), &api.EditPullRequestOption{
+		Base:  "feature/1",
+		Title: "edit a this pr",
+	})
+	resp = session.MakeRequest(t, req, 201)
+	DecodeJSON(t, resp, pull)
+	assert.EqualValues(t, "feature/1", pull.Base.Name)
+
+	req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d?token=%s", owner10.Name, repo10.Name, pull.Index, token), &api.EditPullRequestOption{
+		Base: "not-exist",
+	})
+	session.MakeRequest(t, req, 404)
 }
diff --git a/integrations/api_repo_file_create_test.go b/integrations/api_repo_file_create_test.go
index 3c8b50d5d1..853224f091 100644
--- a/integrations/api_repo_file_create_test.go
+++ b/integrations/api_repo_file_create_test.go
@@ -189,7 +189,7 @@ func TestAPICreateFile(t *testing.T) {
 		treePath = "README.md"
 		url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
 		req = NewRequestWithJSON(t, "POST", url, &createFileOptions)
-		resp = session.MakeRequest(t, req, http.StatusInternalServerError)
+		resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity)
 		expectedAPIError := context.APIError{
 			Message: "repository file already exists [path: " + treePath + "]",
 			URL:     setting.API.SwaggerURL,
diff --git a/integrations/api_repo_file_update_test.go b/integrations/api_repo_file_update_test.go
index 369e48d646..69a9463774 100644
--- a/integrations/api_repo_file_update_test.go
+++ b/integrations/api_repo_file_update_test.go
@@ -208,7 +208,7 @@ func TestAPIUpdateFile(t *testing.T) {
 		updateFileOptions.SHA = "badsha"
 		url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2)
 		req = NewRequestWithJSON(t, "PUT", url, &updateFileOptions)
-		resp = session.MakeRequest(t, req, http.StatusInternalServerError)
+		resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity)
 		expectedAPIError := context.APIError{
 			Message: "sha does not match [given: " + updateFileOptions.SHA + ", expected: " + correctSHA + "]",
 			URL:     setting.API.SwaggerURL,
diff --git a/integrations/api_repo_test.go b/integrations/api_repo_test.go
index d57e5daaf3..7797b8f498 100644
--- a/integrations/api_repo_test.go
+++ b/integrations/api_repo_test.go
@@ -13,6 +13,7 @@ import (
 	"testing"
 
 	"code.gitea.io/gitea/models"
+	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 
 	"github.com/stretchr/testify/assert"
@@ -57,6 +58,12 @@ func TestAPISearchRepo(t *testing.T) {
 	user4 := models.AssertExistsAndLoadBean(t, &models.User{ID: 20}).(*models.User)
 	orgUser := models.AssertExistsAndLoadBean(t, &models.User{ID: 17}).(*models.User)
 
+	oldAPIDefaultNum := setting.API.DefaultPagingNum
+	defer func() {
+		setting.API.DefaultPagingNum = oldAPIDefaultNum
+	}()
+	setting.API.DefaultPagingNum = 10
+
 	// Map of expected results, where key is user for login
 	type expectedResults map[*models.User]struct {
 		count           int
@@ -79,7 +86,7 @@ func TestAPISearchRepo(t *testing.T) {
 			user:  {count: 10},
 			user2: {count: 10}},
 		},
-		{name: "RepositoriesDefaultMax10", requestURL: "/api/v1/repos/search?default&private=false", expectedResults: expectedResults{
+		{name: "RepositoriesDefault", requestURL: "/api/v1/repos/search?default&private=false", expectedResults: expectedResults{
 			nil:   {count: 10},
 			user:  {count: 10},
 			user2: {count: 10}},
diff --git a/integrations/api_user_heatmap_test.go b/integrations/api_user_heatmap_test.go
index 159d70e867..105d39e9ae 100644
--- a/integrations/api_user_heatmap_test.go
+++ b/integrations/api_user_heatmap_test.go
@@ -26,7 +26,7 @@ func TestUserHeatmap(t *testing.T) {
 	var heatmap []*models.UserHeatmapData
 	DecodeJSON(t, resp, &heatmap)
 	var dummyheatmap []*models.UserHeatmapData
-	dummyheatmap = append(dummyheatmap, &models.UserHeatmapData{Timestamp: 1571616000, Contributions: 1})
+	dummyheatmap = append(dummyheatmap, &models.UserHeatmapData{Timestamp: 1603152000, Contributions: 1})
 
 	assert.Equal(t, dummyheatmap, heatmap)
 }
diff --git a/integrations/api_user_search_test.go b/integrations/api_user_search_test.go
index 6661862228..c5295fbba5 100644
--- a/integrations/api_user_search_test.go
+++ b/integrations/api_user_search_test.go
@@ -5,9 +5,12 @@
 package integrations
 
 import (
+	"fmt"
 	"net/http"
 	"testing"
 
+	"code.gitea.io/gitea/models"
+	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 
 	"github.com/stretchr/testify/assert"
@@ -45,8 +48,14 @@ func TestAPIUserSearchNotLoggedIn(t *testing.T) {
 	var results SearchResults
 	DecodeJSON(t, resp, &results)
 	assert.NotEmpty(t, results.Data)
+	var modelUser *models.User
 	for _, user := range results.Data {
 		assert.Contains(t, user.UserName, query)
-		assert.Empty(t, user.Email)
+		modelUser = models.AssertExistsAndLoadBean(t, &models.User{ID: user.ID}).(*models.User)
+		if modelUser.KeepEmailPrivate {
+			assert.EqualValues(t, fmt.Sprintf("%s@%s", modelUser.LowerName, setting.Service.NoReplyAddress), user.Email)
+		} else {
+			assert.EqualValues(t, modelUser.Email, user.Email)
+		}
 	}
 }
diff --git a/integrations/auth_ldap_test.go b/integrations/auth_ldap_test.go
index 520a611eab..1569458418 100644
--- a/integrations/auth_ldap_test.go
+++ b/integrations/auth_ldap_test.go
@@ -141,7 +141,7 @@ func TestLDAPUserSignin(t *testing.T) {
 
 	assert.Equal(t, u.UserName, htmlDoc.GetInputValueByName("name"))
 	assert.Equal(t, u.FullName, htmlDoc.GetInputValueByName("full_name"))
-	assert.Equal(t, u.Email, htmlDoc.GetInputValueByName("email"))
+	assert.Equal(t, u.Email, htmlDoc.Find(`label[for="email"]`).Siblings().First().Text())
 }
 
 func TestLDAPUserSync(t *testing.T) {
diff --git a/integrations/branches_test.go b/integrations/branches_test.go
index ed6a73fdb4..2b9fc8dda5 100644
--- a/integrations/branches_test.go
+++ b/integrations/branches_test.go
@@ -32,14 +32,14 @@ func TestDeleteBranch(t *testing.T) {
 }
 
 func TestUndoDeleteBranch(t *testing.T) {
-	defer prepareTestEnv(t)()
-
-	deleteBranch(t)
-	htmlDoc, name := branchAction(t, ".undo-button")
-	assert.Contains(t,
-		htmlDoc.doc.Find(".ui.positive.message").Text(),
-		i18n.Tr("en", "repo.branch.restore_success", name),
-	)
+	onGiteaRun(t, func(t *testing.T, u *url.URL) {
+		deleteBranch(t)
+		htmlDoc, name := branchAction(t, ".undo-button")
+		assert.Contains(t,
+			htmlDoc.doc.Find(".ui.positive.message").Text(),
+			i18n.Tr("en", "repo.branch.restore_success", name),
+		)
+	})
 }
 
 func deleteBranch(t *testing.T) {
diff --git a/integrations/eventsource_test.go b/integrations/eventsource_test.go
index bc15453147..caaf8c2cef 100644
--- a/integrations/eventsource_test.go
+++ b/integrations/eventsource_test.go
@@ -59,7 +59,7 @@ func TestEventSourceManagerRun(t *testing.T) {
 	var apiNL []api.NotificationThread
 
 	// -- mark notifications as read --
-	req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?token=%s", token))
+	req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?status-types=unread&token=%s", token))
 	resp := session.MakeRequest(t, req, http.StatusOK)
 
 	DecodeJSON(t, resp, &apiNL)
@@ -69,7 +69,7 @@ func TestEventSourceManagerRun(t *testing.T) {
 	req = NewRequest(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/%s/notifications?last_read_at=%s&token=%s", user2.Name, repo1.Name, lastReadAt, token))
 	resp = session.MakeRequest(t, req, http.StatusResetContent)
 
-	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?token=%s", token))
+	req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?token=%s&status-types=unread", token))
 	resp = session.MakeRequest(t, req, http.StatusOK)
 	DecodeJSON(t, resp, &apiNL)
 	assert.Len(t, apiNL, 1)
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/5f/22f7d0d95d614d25a5b68592adb345a4b5c7fd b/integrations/gitea-repositories-meta/user2/repo1.git/objects/5f/22f7d0d95d614d25a5b68592adb345a4b5c7fd
new file mode 100644
index 0000000000..17fdf18edb
Binary files /dev/null and b/integrations/gitea-repositories-meta/user2/repo1.git/objects/5f/22f7d0d95d614d25a5b68592adb345a4b5c7fd differ
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/90/dcd07da077d1e7cd6032b52d1f79ae2b5f19b2 b/integrations/gitea-repositories-meta/user2/repo1.git/objects/90/dcd07da077d1e7cd6032b52d1f79ae2b5f19b2
new file mode 100644
index 0000000000..1404abdaa2
--- /dev/null
+++ b/integrations/gitea-repositories-meta/user2/repo1.git/objects/90/dcd07da077d1e7cd6032b52d1f79ae2b5f19b2
@@ -0,0 +1,2 @@
+xeฑNฤ0Dฉ#ๅๆŽ4 
+JฤAล5”Žณ—,—xัzsV‚5„Dๅัุปž7,=ฎฎo.แEๅขแq5J=้ˆศ	rฤ=>4ง๚
O!๓ยАใด๐ะ6ms˜8ƒพ&\EaพtอT„ดIขz”‰ิ…!	ขdso@a›ฺ&ฬK5B)›r4–”Qฆ`Y่Lฺฏฒb	›พo`aไ3น@(๎Šถาeิญ5
๔ยH—\sิH9Ÿ9Rช3)ฮ๋@ŽS๙ใ_"ง‘4sE0”Rบ๑งค.‘U|/€mฆฟ]U๗ฬzภ
\ No newline at end of file
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/dd/59742c0f6672911f2b64cba5711ac00593ed32 b/integrations/gitea-repositories-meta/user2/repo1.git/objects/dd/59742c0f6672911f2b64cba5711ac00593ed32
new file mode 100644
index 0000000000..f9137c5f77
Binary files /dev/null and b/integrations/gitea-repositories-meta/user2/repo1.git/objects/dd/59742c0f6672911f2b64cba5711ac00593ed32 differ
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/3/head b/integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/3/head
index 98593d6537..33a9eaa7f1 100644
--- a/integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/3/head
+++ b/integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/3/head
@@ -1 +1 @@
-4a357436d925b5c974181ff12a994538ddc5a269
+5f22f7d0d95d614d25a5b68592adb345a4b5c7fd
diff --git a/integrations/html_helper.go b/integrations/html_helper.go
index 823ed44851..6dc806a76e 100644
--- a/integrations/html_helper.go
+++ b/integrations/html_helper.go
@@ -37,6 +37,13 @@ func (doc *HTMLDoc) GetInputValueByName(name string) string {
 	return text
 }
 
+// Find gets the descendants of each element in the current set of
+// matched elements, filtered by a selector. It returns a new Selection
+// object containing these matched elements.
+func (doc *HTMLDoc) Find(selector string) *goquery.Selection {
+	return doc.doc.Find(selector)
+}
+
 // GetCSRF for get CSRC token value from input
 func (doc *HTMLDoc) GetCSRF() string {
 	return doc.GetInputValueByName("_csrf")
diff --git a/integrations/migration-test/migration_test.go b/integrations/migration-test/migration_test.go
index 4ee045db38..081dd095fb 100644
--- a/integrations/migration-test/migration_test.go
+++ b/integrations/migration-test/migration_test.go
@@ -152,6 +152,7 @@ func restoreOldDB(t *testing.T, version string) bool {
 
 		_, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name))
 		assert.NoError(t, err)
+		db.Close()
 
 		db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?multiStatements=true",
 			setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name))
@@ -182,6 +183,8 @@ func restoreOldDB(t *testing.T, version string) bool {
 			if !assert.NoError(t, err) {
 				return false
 			}
+			defer db.Close()
+
 			schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema))
 			if !assert.NoError(t, err) || !assert.NotEmpty(t, schrows) {
 				return false
diff --git a/integrations/private-testing.key b/integrations/private-testing.key
index c39a08d38f..293256a16c 100644
--- a/integrations/private-testing.key
+++ b/integrations/private-testing.key
@@ -76,6 +76,53 @@ nARUPZ9SqaUmRm+KGsSyoYnvN9apiDk5KVQoyfrmweNN7DCIIcoh/B9Ax8nmouKz
 yBB2fjCM/bJNtN/AsgYbZIScuYK/xqTkwNtbe5WdCyD/QJOHTsPJzx59hgSVo6gf
 Fe8VBnxHtrY8gPSUU3gkhYLvLzyVX+YLNzRcffobd8gJbfumwFJUkz91oGvYz7xg
 XN2qmsgBNCbTIzWZMpRDMAbY+n2QFImGf+EJZlMdj6gOrIYq8N4+nMW1FwJivsOb
-muqySyjZnD2AYjEA6OYPXfCVhaB5fTfhQXbIrZbgsEh4ob/eIdM=
-=oSDR
+muqySyjZnD2AYjEA6OYPXfCVhaB5fTfhQXbIrZbgsEh4ob/eIdOdBVgEXta5egEM
+AMYlmZ47NqBMBeaN0o/ahYMe8eIMaroWkufMfC9VRBSMAkpbDl34oNp0cflmnMYo
+AFAl8ucRMFTiUnjiWpo27q14tjSyDVsn/CqwbnrgJgCFNV/MGsYsToEkb4JwDIRC
+bky+1BvqvI8RMlO3MlwzrlIaMrlQfx5NtUb9TyO7S4xZTz864+Ty5p3HhRwbdZMe
+Ko8sfXFhCcCHFXosI0mX83EyzsrXlbkGRawId7jvrdOAUg/cYP8f/XmV6z1NHHH9
+cvz+3oLOGuVxUdG0KuS/jigHrLWdRuKM3xfEeesp870yZU3AbyFdoHnGXROJePTl
+FV8j2P5Ahf/yuVhjdyJSKdZC2h6+HtLG9RiGgLviLLYhtlZG2H6pYyKY5Ud3php+
+qw1aYL1xtdxrHYkQlAa0vLY/mwpuPfMke9I+rtnrwlLRMCstdiN34ybZ4sRD+gL1
+w5VIZ/aM6/Gsczd3s/T8psIi09TKPfEU2gWLMGvlDsgz+aSDdVP7XYQpNglaEPet
+PwARAQABAAv8CHg6+hnV2pblTwGTlTU7V8DO3gwMfn/QhQ/8ju66G5a7J6p/ZreQ
+nfCJnqYq4AgoW0SuqVSBbbTENF6YjixNmiSlb9iHMZ+ilms24xG0Y3lOMBYYCY3Y
+nTSNf6nXyconz31TW7jLmTdG9hpykKEKO9WFgt5UpgWe+2CAgtUoBDZyaLrVBZ2h
+te99WmziDbPQZeZPm7UQ0aX0iRBclxy4+dxjcnrcmi1mdQAM/glgs2sHbEjN7JnV
+dTOvUSN7/8ixj6I719Wx6MN6jE+BNd0ytZOun6tcDl0vamfT5fBpqbQoJMib2ggo
++FGg9VFnzEMLqyI47LfOKUjCIhwVsxS4q9HXa2FtpO8UfRMPjDKgDZQzRTRJScrP
+s1NJ9HiM/eCHS1YjRmgroo60HygxkoLVCHp+Rz/hi0tG/ptv4q6mdnm8Mwb5JJtV
+48EvmZoNTWl9xOez1wmQn6caVHipc0qDqn/veoe8N5wdc+3hoMEXbSXqU+kx2KUa
+cVxCCVoUeURhBgDUGWtx34j1y17zE92BYhtVJTCU89dDe4wOEqGPyCGvRtgTmZ+1
+KwWr66pij91MV9mlY+7Ue2QHUSmgav2EFGIjVes956p4/F/CJ6qaYoekirMSnmX5
+jhRt4p6RW7m4omha3LAQ+gN4Fqa4acZUywENBvv1x3v+IWbjGJGn3eBnRrP3o9P+
+QUAtyMifiRm0ZN8J767o+bzUVmscXrkh7Qml47lQfDToyRI1UZZQmP2izpwHcwbZ
+NtfkgRUdeEq4GJUGAO8o4Oebbt0ALZ54E2LHhk8xi4ofKkFBDCkUFjcqS3bJJNck
+rkhfqEkMLETNhPbiC4TRNiunI5PXOinwNPkKI8P/hfp4S49WdIvnARazCoxjZNtl
+0Cbo+F1wtOH9FZaaWzNlU2lCQ2JJ3MCpLHz+nEmdYWOIWGQu2/s7smLODVEFbYKR
+50VWVRL7mB83v1XdfMFvExdQ7i5MOX4hFvmwi/WJIKClJfhNwTrHp6Jrm9jA66RL
++dNyPKfwcFcYrqt1gwYAruZzP7QgTYVL+cmvGtCaHY4KoR8hanbpqR4YbzzyEXwS
+ll2FUCaVSokuRAdH3+/CHF9bqog3Zvn6HYcCS/A/rHVGIU9a+7s5IbRe0Ysc2FAN
+Nm9AsC5YnuyoAjW3cJGaZLYxp2WOZcMEXZeLPFYrNz22R1nRoxnUIPRpsKICXcK0
+aC4rSMk479jc/8WprWx4d45EVG+6Gsh1AT8LVhDL9yHFrh50ss2jCe1Fnftet6DI
+V5zHcxBx4sCs91aPxxe12UiJA2wEGAEKACAWIQQ4G/p4KVUOUEVu5g5R68KXFICq
+DwUCXta5egIbAgHACRBR68KXFICqD8D0IAQZAQoAHRYhBKAm5ShdO9gmF/o8jan0
+RkmWoKbKBQJe1rl6AAoJEKn0RkmWoKbKacUL/3YYKmiVvcr5LYFzMdwdahkla+6m
+hEEkL0l3dJNuU97Ou71tA1ieF0fjbVRSWjXKsntKwhyPoXjaZEZwMmv7iZ8BXV+b
+oO/EG5sg2/6iukJFXZqGnQwMdLVo1jPoXDteZU1qYiCoxLHhGhHL7ivtD1ygEi6w
+/cMbbOEB5Le1vOWIwqazs8dDcAYyy1PKthRl0ygvh8CpqPwy+AK3uLm0TVwetQAp
+taux0bDYWCb5Aft1r1nlV44gU4RiC131TDo+TKd754+UuI+UHk1D+LjTmZxRX2S6
+fXgoMXzrWmthGPdqvVOgKWm7Ef18hmaBECvPnp/tUJeDVVe02KrYQi8Bf2kxveSd
+8T0N/ExcydU9HgzTL8MuyPI+yp086elQzKJu6vb9tpgxCcglQZrUNT9Uy82pzTRY
+z9MmhnCDI2SD5L/CW5PsNpPTPy7s3f9DOV0G5Vka4LTSBOCK64NvAGBmRf8rFjJU
+lPtRPhC7h6uHdUIx3Q550Xogvq5sQm8UBCsbG8OJDADT3FJSIulR9Sh96OsES3sc
+H09juN4KcbpS03MAeUFwXqw3jBMhDoGKlsjX17Jf31qh/nI/XjigS3XWyj1BLSMG
+rJfH0NyYoGDCnff37tf+8lD9km9TlnV4Qjd9ujYbDRsefhaSjLVcy/gqdxZEuNBC
+BWmGwsmLI3nyZ4KDtNsa5JUHUNNZLBN20hvmE41Eszmz4Yg9Ho9DxKiFKvzUULMc
+bnMHaVHseHHq6+NVUnN1SAcOA0ygjnEid8D57RtdBCD90LXjLB7vlR+HaSMZYOnr
+DtseivHvqqy4+rxhwV2S3avnls9vRwE4bV6GCiqhoBnWIZRrARLZc2OTBIya82vS
+BIS1eyhjif1mE7Lqhs6aPD+eqQK2mBtQ/sidN8P/IfKfVF5siXfFbuGZLz5nRIho
+Yp1z7oO3OZ09lpUk0G1h+ouIFF6goDP48M/AKtbvs9OWk3QKxnOUZD8sRncq95x6
+m4q1MVb+aJyxwBqDRGaFY+3TVArB1b+kG1JsAvV5dag=
+=511T
 -----END PGP PRIVATE KEY BLOCK-----
diff --git a/integrations/pull_merge_test.go b/integrations/pull_merge_test.go
index b5ac9406ac..04e68ff3dc 100644
--- a/integrations/pull_merge_test.go
+++ b/integrations/pull_merge_test.go
@@ -194,7 +194,7 @@ func TestCantMergeWorkInProgress(t *testing.T) {
 		req := NewRequest(t, "GET", resp.Header().Get("Location"))
 		resp = session.MakeRequest(t, req, http.StatusOK)
 		htmlDoc := NewHTMLParser(t, resp.Body)
-		text := strings.TrimSpace(htmlDoc.doc.Find(".attached.header > .text.grey").Last().Text())
+		text := strings.TrimSpace(htmlDoc.doc.Find(".attached.merge-section.no-header > .text.grey").Last().Text())
 		assert.NotEmpty(t, text, "Can't find WIP text")
 
 		// remove  from lang
diff --git a/integrations/release_test.go b/integrations/release_test.go
index 176f83d55a..4d2260d884 100644
--- a/integrations/release_test.go
+++ b/integrations/release_test.go
@@ -10,6 +10,7 @@ import (
 	"testing"
 	"time"
 
+	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/test"
 
 	"github.com/stretchr/testify/assert"
@@ -106,6 +107,12 @@ func TestCreateReleaseDraft(t *testing.T) {
 func TestCreateReleasePaging(t *testing.T) {
 	defer prepareTestEnv(t)()
 
+	oldAPIDefaultNum := setting.API.DefaultPagingNum
+	defer func() {
+		setting.API.DefaultPagingNum = oldAPIDefaultNum
+	}()
+	setting.API.DefaultPagingNum = 10
+
 	session := loginUser(t, "user2")
 	// Create enaugh releases to have paging
 	for i := 0; i < 12; i++ {
diff --git a/models/attachment.go b/models/attachment.go
index 7e59c7eef4..6c3996ff01 100644
--- a/models/attachment.go
+++ b/models/attachment.go
@@ -14,7 +14,7 @@ import (
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/timeutil"
 
-	gouuid "github.com/satori/go.uuid"
+	gouuid "github.com/google/uuid"
 	"xorm.io/xorm"
 )
 
@@ -97,7 +97,7 @@ func (a *Attachment) LinkedRepository() (*Repository, UnitType, error) {
 
 // NewAttachment creates a new attachment object.
 func NewAttachment(attach *Attachment, buf []byte, file io.Reader) (_ *Attachment, err error) {
-	attach.UUID = gouuid.NewV4().String()
+	attach.UUID = gouuid.New().String()
 
 	localPath := attach.LocalPath()
 	if err = os.MkdirAll(path.Dir(localPath), os.ModePerm); err != nil {
@@ -136,9 +136,8 @@ func GetAttachmentByID(id int64) (*Attachment, error) {
 }
 
 func getAttachmentByID(e Engine, id int64) (*Attachment, error) {
-	attach := &Attachment{ID: id}
-
-	if has, err := e.Get(attach); err != nil {
+	attach := &Attachment{}
+	if has, err := e.ID(id).Get(attach); err != nil {
 		return nil, err
 	} else if !has {
 		return nil, ErrAttachmentNotExist{ID: id, UUID: ""}
@@ -147,8 +146,8 @@ func getAttachmentByID(e Engine, id int64) (*Attachment, error) {
 }
 
 func getAttachmentByUUID(e Engine, uuid string) (*Attachment, error) {
-	attach := &Attachment{UUID: uuid}
-	has, err := e.Get(attach)
+	attach := &Attachment{}
+	has, err := e.Where("uuid=?", uuid).Get(attach)
 	if err != nil {
 		return nil, err
 	} else if !has {
diff --git a/models/avatar.go b/models/avatar.go
index 311d714629..c9ba2961ef 100644
--- a/models/avatar.go
+++ b/models/avatar.go
@@ -41,7 +41,18 @@ func AvatarLink(email string) string {
 			Email: lowerEmail,
 			Hash:  sum,
 		}
-		_, _ = x.Insert(emailHash)
+		// OK we're going to open a session just because I think that that might hide away any problems with postgres reporting errors
+		sess := x.NewSession()
+		defer sess.Close()
+		if err := sess.Begin(); err != nil {
+			// we don't care about any DB problem just return the lowerEmail
+			return lowerEmail, nil
+		}
+		_, _ = sess.Insert(emailHash)
+		if err := sess.Commit(); err != nil {
+			// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time
+			return lowerEmail, nil
+		}
 		return lowerEmail, nil
 	})
 	return setting.AppSubURL + "/avatar/" + url.PathEscape(sum)
diff --git a/models/branches.go b/models/branches.go
index 688e2d7f51..38aa79d2dc 100644
--- a/models/branches.go
+++ b/models/branches.go
@@ -98,9 +98,10 @@ func (protectBranch *ProtectedBranch) CanUserPush(userID int64) bool {
 }
 
 // IsUserMergeWhitelisted checks if some user is whitelisted to merge to this branch
-func (protectBranch *ProtectedBranch) IsUserMergeWhitelisted(userID int64) bool {
+func (protectBranch *ProtectedBranch) IsUserMergeWhitelisted(userID int64, permissionInRepo Permission) bool {
 	if !protectBranch.EnableMergeWhitelist {
-		return true
+		// Then we need to fall back on whether the user has write permission
+		return permissionInRepo.CanWrite(UnitTypeCode)
 	}
 
 	if base.Int64sContains(protectBranch.MergeWhitelistUserIDs, userID) {
@@ -240,8 +241,8 @@ func getProtectedBranchBy(e Engine, repoID int64, branchName string) (*Protected
 
 // GetProtectedBranchByID getting protected branch by ID
 func GetProtectedBranchByID(id int64) (*ProtectedBranch, error) {
-	rel := &ProtectedBranch{ID: id}
-	has, err := x.Get(rel)
+	rel := &ProtectedBranch{}
+	has, err := x.ID(id).Get(rel)
 	if err != nil {
 		return nil, err
 	}
@@ -509,9 +510,9 @@ func (repo *Repository) GetDeletedBranches() ([]*DeletedBranch, error) {
 }
 
 // GetDeletedBranchByID get a deleted branch by its ID
-func (repo *Repository) GetDeletedBranchByID(ID int64) (*DeletedBranch, error) {
-	deletedBranch := &DeletedBranch{ID: ID}
-	has, err := x.Get(deletedBranch)
+func (repo *Repository) GetDeletedBranchByID(id int64) (*DeletedBranch, error) {
+	deletedBranch := &DeletedBranch{}
+	has, err := x.ID(id).Get(deletedBranch)
 	if err != nil {
 		return nil, err
 	}
diff --git a/models/consistency.go b/models/consistency.go
index 62d1d2e874..fbb99ca80c 100644
--- a/models/consistency.go
+++ b/models/consistency.go
@@ -10,6 +10,7 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	"xorm.io/builder"
 )
 
 // consistencyCheckable a type that can be tested for database consistency
@@ -167,3 +168,130 @@ func (action *Action) checkForConsistency(t *testing.T) {
 	repo := AssertExistsAndLoadBean(t, &Repository{ID: action.RepoID}).(*Repository)
 	assert.Equal(t, repo.IsPrivate, action.IsPrivate, "action: %+v", action)
 }
+
+// CountOrphanedLabels return count of labels witch are broken and not accessible via ui anymore
+func CountOrphanedLabels() (int64, error) {
+	noref, err := x.Table("label").Where("repo_id=? AND org_id=?", 0, 0).Count("label.id")
+	if err != nil {
+		return 0, err
+	}
+
+	norepo, err := x.Table("label").
+		Join("LEFT", "repository", "label.repo_id=repository.id").
+		Where(builder.IsNull{"repository.id"}).And(builder.Gt{"label.repo_id": 0}).
+		Count("id")
+	if err != nil {
+		return 0, err
+	}
+
+	noorg, err := x.Table("label").
+		Join("LEFT", "`user`", "label.org_id=`user`.id").
+		Where(builder.IsNull{"`user`.id"}).And(builder.Gt{"label.org_id": 0}).
+		Count("id")
+	if err != nil {
+		return 0, err
+	}
+
+	return noref + norepo + noorg, nil
+}
+
+// DeleteOrphanedLabels delete labels witch are broken and not accessible via ui anymore
+func DeleteOrphanedLabels() error {
+	// delete labels with no reference
+	if _, err := x.Table("label").Where("repo_id=? AND org_id=?", 0, 0).Delete(new(Label)); err != nil {
+		return err
+	}
+
+	// delete labels with none existing repos
+	if _, err := x.In("id", builder.Select("label.id").From("label").
+		Join("LEFT", "repository", "label.repo_id=repository.id").
+		Where(builder.IsNull{"repository.id"}).And(builder.Gt{"label.repo_id": 0})).
+		Delete(Label{}); err != nil {
+		return err
+	}
+
+	// delete labels with none existing orgs
+	if _, err := x.In("id", builder.Select("label.id").From("label").
+		Join("LEFT", "`user`", "label.org_id=`user`.id").
+		Where(builder.IsNull{"`user`.id"}).And(builder.Gt{"label.org_id": 0})).
+		Delete(Label{}); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// CountOrphanedIssues count issues without a repo
+func CountOrphanedIssues() (int64, error) {
+	return x.Table("issue").
+		Join("LEFT", "repository", "issue.repo_id=repository.id").
+		Where(builder.IsNull{"repository.id"}).
+		Count("id")
+}
+
+// DeleteOrphanedIssues delete issues without a repo
+func DeleteOrphanedIssues() error {
+	sess := x.NewSession()
+	defer sess.Close()
+	if err := sess.Begin(); err != nil {
+		return err
+	}
+
+	var ids []int64
+
+	if err := sess.Table("issue").Distinct("issue.repo_id").
+		Join("LEFT", "repository", "issue.repo_id=repository.id").
+		Where(builder.IsNull{"repository.id"}).GroupBy("issue.repo_id").
+		Find(&ids); err != nil {
+		return err
+	}
+
+	var attachmentPaths []string
+	for i := range ids {
+		paths, err := deleteIssuesByRepoID(sess, ids[i])
+		if err != nil {
+			return err
+		}
+		attachmentPaths = append(attachmentPaths, paths...)
+	}
+
+	if err := sess.Commit(); err != nil {
+		return err
+	}
+
+	// Remove issue attachment files.
+	for i := range attachmentPaths {
+		removeAllWithNotice(x, "Delete issue attachment", attachmentPaths[i])
+	}
+	return nil
+}
+
+// CountOrphanedObjects count subjects with have no existing refobject anymore
+func CountOrphanedObjects(subject, refobject, joinCond string) (int64, error) {
+	return x.Table("`"+subject+"`").
+		Join("LEFT", refobject, joinCond).
+		Where(builder.IsNull{"`" + refobject + "`.id"}).
+		Count("id")
+}
+
+// DeleteOrphanedObjects delete subjects with have no existing refobject anymore
+func DeleteOrphanedObjects(subject, refobject, joinCond string) error {
+	_, err := x.In("id", builder.Select("`"+subject+"`.id").
+		From("`"+subject+"`").
+		Join("LEFT", "`"+refobject+"`", joinCond).
+		Where(builder.IsNull{"`" + refobject + "`.id"})).
+		Delete("`" + subject + "`")
+	return err
+}
+
+// CountNullArchivedRepository counts the number of repositories with is_archived is null
+func CountNullArchivedRepository() (int64, error) {
+	return x.Where(builder.IsNull{"is_archived"}).Count(new(Repository))
+}
+
+// FixNullArchivedRepository sets is_archived to false where it is null
+func FixNullArchivedRepository() (int64, error) {
+	return x.Where(builder.IsNull{"is_archived"}).Cols("is_archived").Update(&Repository{
+		IsArchived: false,
+	})
+}
diff --git a/models/fixtures/action.yml b/models/fixtures/action.yml
index e8a6d531f2..eb92aeedbe 100644
--- a/models/fixtures/action.yml
+++ b/models/fixtures/action.yml
@@ -5,7 +5,7 @@
   act_user_id: 2
   repo_id: 2
   is_private: true
-  created_unix: 1571686356
+  created_unix: 1603228283
 
 -
   id: 2
diff --git a/models/gpg_key.go b/models/gpg_key.go
index a32312a12d..8897bba56b 100644
--- a/models/gpg_key.go
+++ b/models/gpg_key.go
@@ -273,7 +273,7 @@ func parseGPGKey(ownerID int64, e *openpgp.Entity) (*GPGKey, error) {
 	for i, k := range e.Subkeys {
 		subs, err := parseSubGPGKey(ownerID, pubkey.KeyIdString(), k.PublicKey, expiry)
 		if err != nil {
-			return nil, err
+			return nil, ErrGPGKeyParsing{ParseError: err}
 		}
 		subkeys[i] = subs
 	}
@@ -286,6 +286,9 @@ func parseGPGKey(ownerID int64, e *openpgp.Entity) (*GPGKey, error) {
 
 	emails := make([]*EmailAddress, 0, len(e.Identities))
 	for _, ident := range e.Identities {
+		if ident.Revocation != nil {
+			continue
+		}
 		email := strings.ToLower(strings.TrimSpace(ident.UserId.Email))
 		for _, e := range userEmails {
 			if e.Email == email {
@@ -509,6 +512,18 @@ func hashAndVerifyForKeyID(sig *packet.Signature, payload string, committer *Use
 		return nil
 	}
 	for _, key := range keys {
+		var primaryKeys []*GPGKey
+		if key.PrimaryKeyID != "" {
+			primaryKeys, err = GetGPGKeysByKeyID(key.PrimaryKeyID)
+			if err != nil {
+				log.Error("GetGPGKeysByKeyID: %v", err)
+				return &CommitVerification{
+					CommittingUser: committer,
+					Verified:       false,
+					Reason:         "gpg.error.failed_retrieval_gpg_keys",
+				}
+			}
+		}
 		activated := false
 		if len(email) != 0 {
 			for _, e := range key.Emails {
@@ -518,6 +533,20 @@ func hashAndVerifyForKeyID(sig *packet.Signature, payload string, committer *Use
 					break
 				}
 			}
+			if !activated {
+				for _, pkey := range primaryKeys {
+					for _, e := range pkey.Emails {
+						if e.IsActivated && strings.EqualFold(e.Email, email) {
+							activated = true
+							email = e.Email
+							break
+						}
+					}
+					if activated {
+						break
+					}
+				}
+			}
 		} else {
 			for _, e := range key.Emails {
 				if e.IsActivated {
@@ -526,7 +555,22 @@ func hashAndVerifyForKeyID(sig *packet.Signature, payload string, committer *Use
 					break
 				}
 			}
+			if !activated {
+				for _, pkey := range primaryKeys {
+					for _, e := range pkey.Emails {
+						if e.IsActivated {
+							activated = true
+							email = e.Email
+							break
+						}
+					}
+					if activated {
+						break
+					}
+				}
+			}
 		}
+
 		if !activated {
 			continue
 		}
@@ -614,7 +658,6 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification {
 	if keyID == "" && sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) > 0 {
 		keyID = fmt.Sprintf("%X", sig.IssuerFingerprint[12:20])
 	}
-
 	defaultReason := NoKeyFound
 
 	// First check if the sig has a keyID and if so just look at that
@@ -741,6 +784,21 @@ func verifyWithGPGSettings(gpgSettings *git.GPGSettings, sig *packet.Signature,
 		CanSign: pubkey.CanSign(),
 		KeyID:   pubkey.KeyIdString(),
 	}
+	for _, subKey := range ekey.Subkeys {
+		content, err := base64EncPubKey(subKey.PublicKey)
+		if err != nil {
+			return &CommitVerification{
+				CommittingUser: committer,
+				Verified:       false,
+				Reason:         "gpg.error.generate_hash",
+			}
+		}
+		k.SubsKey = append(k.SubsKey, &GPGKey{
+			Content: content,
+			CanSign: subKey.PublicKey.CanSign(),
+			KeyID:   subKey.PublicKey.KeyIdString(),
+		})
+	}
 	if commitVerification := hashAndVerifyWithSubKeys(sig, payload, k, committer, &User{
 		Name:  gpgSettings.Name,
 		Email: gpgSettings.Email,
diff --git a/models/issue.go b/models/issue.go
index d9f8e929c7..05eed6a78d 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -76,7 +76,6 @@ var (
 const issueTasksRegexpStr = `(^\s*[-*]\s\[[\sxX]\]\s.)|(\n\s*[-*]\s\[[\sxX]\]\s.)`
 const issueTasksDoneRegexpStr = `(^\s*[-*]\s\[[xX]\]\s.)|(\n\s*[-*]\s\[[xX]\]\s.)`
 const issueMaxDupIndexAttempts = 3
-const maxIssueIDs = 950
 
 func init() {
 	issueTasksPat = regexp.MustCompile(issueTasksRegexpStr)
@@ -249,7 +248,7 @@ func (issue *Issue) loadReactions(e Engine) (err error) {
 }
 
 func (issue *Issue) loadMilestone(e Engine) (err error) {
-	if issue.Milestone == nil && issue.MilestoneID > 0 {
+	if (issue.Milestone == nil || issue.Milestone.ID != issue.MilestoneID) && issue.MilestoneID > 0 {
 		issue.Milestone, err = getMilestoneByRepoID(e, issue.RepoID, issue.MilestoneID)
 		if err != nil && !IsErrMilestoneNotExist(err) {
 			return fmt.Errorf("getMilestoneByRepoID [repo_id: %d, milestone_id: %d]: %v", issue.RepoID, issue.MilestoneID, err)
@@ -1114,9 +1113,6 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) {
 	}
 
 	if len(opts.IssueIDs) > 0 {
-		if len(opts.IssueIDs) > maxIssueIDs {
-			opts.IssueIDs = opts.IssueIDs[:maxIssueIDs]
-		}
 		sess.In("issue.id", opts.IssueIDs)
 	}
 
@@ -1360,9 +1356,6 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats,
 			Where("issue.repo_id = ?", opts.RepoID)
 
 		if len(opts.IssueIDs) > 0 {
-			if len(opts.IssueIDs) > maxIssueIDs {
-				opts.IssueIDs = opts.IssueIDs[:maxIssueIDs]
-			}
 			sess.In("issue.id", opts.IssueIDs)
 		}
 
@@ -1446,9 +1439,6 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
 		cond = cond.And(builder.In("issue.repo_id", opts.RepoIDs))
 	}
 	if len(opts.IssueIDs) > 0 {
-		if len(opts.IssueIDs) > maxIssueIDs {
-			opts.IssueIDs = opts.IssueIDs[:maxIssueIDs]
-		}
 		cond = cond.And(builder.In("issue.id", opts.IssueIDs))
 	}
 
@@ -1916,3 +1906,75 @@ func UpdateReactionsMigrationsByType(gitServiceType structs.GitServiceType, orig
 		})
 	return err
 }
+
+func deleteIssuesByRepoID(sess Engine, repoID int64) (attachmentPaths []string, err error) {
+	deleteCond := builder.Select("id").From("issue").Where(builder.Eq{"issue.repo_id": repoID})
+
+	// Delete comments and attachments
+	if _, err = sess.In("issue_id", deleteCond).
+		Delete(&Comment{}); err != nil {
+		return
+	}
+
+	// Dependencies for issues in this repository
+	if _, err = sess.In("issue_id", deleteCond).
+		Delete(&IssueDependency{}); err != nil {
+		return
+	}
+
+	// Delete dependencies for issues in other repositories
+	if _, err = sess.In("dependency_id", deleteCond).
+		Delete(&IssueDependency{}); err != nil {
+		return
+	}
+
+	if _, err = sess.In("issue_id", deleteCond).
+		Delete(&IssueUser{}); err != nil {
+		return
+	}
+
+	if _, err = sess.In("issue_id", deleteCond).
+		Delete(&Reaction{}); err != nil {
+		return
+	}
+
+	if _, err = sess.In("issue_id", deleteCond).
+		Delete(&IssueWatch{}); err != nil {
+		return
+	}
+
+	if _, err = sess.In("issue_id", deleteCond).
+		Delete(&Stopwatch{}); err != nil {
+		return
+	}
+
+	if _, err = sess.In("issue_id", deleteCond).
+		Delete(&TrackedTime{}); err != nil {
+		return
+	}
+
+	if _, err = sess.In("dependent_issue_id", deleteCond).
+		Delete(&Comment{}); err != nil {
+		return
+	}
+
+	var attachments []*Attachment
+	if err = sess.In("issue_id", deleteCond).
+		Find(&attachments); err != nil {
+		return
+	}
+	for j := range attachments {
+		attachmentPaths = append(attachmentPaths, attachments[j].LocalPath())
+	}
+
+	if _, err = sess.In("issue_id", deleteCond).
+		Delete(&Attachment{}); err != nil {
+		return
+	}
+
+	if _, err = sess.Delete(&Issue{RepoID: repoID}); err != nil {
+		return
+	}
+
+	return
+}
diff --git a/models/issue_comment.go b/models/issue_comment.go
index f7017435d7..28f45b59f6 100644
--- a/models/issue_comment.go
+++ b/models/issue_comment.go
@@ -8,7 +8,10 @@ package models
 
 import (
 	"fmt"
+	"regexp"
+	"strconv"
 	"strings"
+	"unicode/utf8"
 
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/log"
@@ -138,7 +141,8 @@ type Comment struct {
 	RenderedContent string `xorm:"-"`
 
 	// Path represents the 4 lines of code cemented by this comment
-	Patch string `xorm:"TEXT"`
+	Patch       string `xorm:"-"`
+	PatchQuoted string `xorm:"TEXT patch"`
 
 	CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
 	UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
@@ -182,6 +186,33 @@ func (c *Comment) loadIssue(e Engine) (err error) {
 	return
 }
 
+// BeforeInsert will be invoked by XORM before inserting a record
+func (c *Comment) BeforeInsert() {
+	c.PatchQuoted = c.Patch
+	if !utf8.ValidString(c.Patch) {
+		c.PatchQuoted = strconv.Quote(c.Patch)
+	}
+}
+
+// BeforeUpdate will be invoked by XORM before updating a record
+func (c *Comment) BeforeUpdate() {
+	c.PatchQuoted = c.Patch
+	if !utf8.ValidString(c.Patch) {
+		c.PatchQuoted = strconv.Quote(c.Patch)
+	}
+}
+
+// AfterLoad is invoked from XORM after setting the values of all fields of this object.
+func (c *Comment) AfterLoad(session *xorm.Session) {
+	c.Patch = c.PatchQuoted
+	if len(c.PatchQuoted) > 0 && c.PatchQuoted[0] == '"' {
+		unquoted, err := strconv.Unquote(c.PatchQuoted)
+		if err == nil {
+			c.Patch = unquoted
+		}
+	}
+}
+
 func (c *Comment) loadPoster(e Engine) (err error) {
 	if c.PosterID <= 0 || c.Poster != nil {
 		return nil
@@ -489,10 +520,12 @@ func (c *Comment) LoadReview() error {
 	return c.loadReview(x)
 }
 
+var notEnoughLines = regexp.MustCompile(`fatal: file .* has only \d+ lines?`)
+
 func (c *Comment) checkInvalidation(doer *User, repo *git.Repository, branch string) error {
 	// FIXME differentiate between previous and proposed line
 	commit, err := repo.LineBlame(branch, repo.Path, c.TreePath, uint(c.UnsignedLine()))
-	if err != nil && strings.Contains(err.Error(), "fatal: no such path") {
+	if err != nil && (strings.Contains(err.Error(), "fatal: no such path") || notEnoughLines.MatchString(err.Error())) {
 		c.Invalidated = true
 		return UpdateComment(c, doer)
 	}
diff --git a/models/issue_label.go b/models/issue_label.go
index aa2c8de009..2b519ee71d 100644
--- a/models/issue_label.go
+++ b/models/issue_label.go
@@ -295,10 +295,8 @@ func getLabelByID(e Engine, labelID int64) (*Label, error) {
 		return nil, ErrLabelNotExist{labelID}
 	}
 
-	l := &Label{
-		ID: labelID,
-	}
-	has, err := e.Get(l)
+	l := &Label{}
+	has, err := e.ID(labelID).Get(l)
 	if err != nil {
 		return nil, err
 	} else if !has {
diff --git a/models/list_options.go b/models/list_options.go
index 0946917fec..62c0944cc8 100644
--- a/models/list_options.go
+++ b/models/list_options.go
@@ -38,7 +38,10 @@ func (opts ListOptions) setEnginePagination(e Engine) Engine {
 }
 
 func (opts ListOptions) setDefaultValues() {
-	if opts.PageSize <= 0 || opts.PageSize > setting.API.MaxResponseItems {
+	if opts.PageSize <= 0 {
+		opts.PageSize = setting.API.DefaultPagingNum
+	}
+	if opts.PageSize > setting.API.MaxResponseItems {
 		opts.PageSize = setting.API.MaxResponseItems
 	}
 	if opts.Page <= 0 {
diff --git a/models/login_source.go b/models/login_source.go
index 5350446233..1de24a9cf7 100644
--- a/models/login_source.go
+++ b/models/login_source.go
@@ -300,7 +300,7 @@ func (source *LoginSource) SSPI() *SSPIConfig {
 // CreateLoginSource inserts a LoginSource in the DB if not already
 // existing with the given name.
 func CreateLoginSource(source *LoginSource) error {
-	has, err := x.Get(&LoginSource{Name: source.Name})
+	has, err := x.Where("name=?", source.Name).Exist(new(LoginSource))
 	if err != nil {
 		return err
 	} else if has {
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 00d84da2e8..b25b6eebd3 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -7,6 +7,7 @@ package migrations
 
 import (
 	"fmt"
+	"os"
 	"regexp"
 	"strings"
 
@@ -212,6 +213,8 @@ var migrations = []Migration{
 	NewMigration("Add ResolveDoerID to Comment table", addResolveDoerIDCommentColumn),
 	// v139 -> v140
 	NewMigration("prepend refs/heads/ to issue refs", prependRefsHeadsToIssueRefs),
+	// v140 -> v141
+	NewMigration("Save detected language file size to database instead of percent", fixLanguageStatsToSaveSize),
 }
 
 // GetCurrentDBVersion returns the current db version
@@ -288,12 +291,16 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t
 		return nil
 	}
 
+	// Downgrading Gitea's database version not supported
 	if int(v-minDBVersion) > len(migrations) {
-		// User downgraded Gitea.
-		currentVersion.Version = int64(len(migrations) + minDBVersion)
-		_, err = x.ID(1).Update(currentVersion)
-		return err
+		msg := fmt.Sprintf("Downgrading database version from '%d' to '%d' is not supported and may result in loss of data integrity.\nIf you really know what you're doing, execute `UPDATE version SET version=%d WHERE id=1;`\n",
+			v, minDBVersion+len(migrations), minDBVersion+len(migrations))
+		fmt.Fprint(os.Stderr, msg)
+		log.Fatal(msg)
+		return nil
 	}
+
+	// Migrate
 	for i, m := range migrations[v-minDBVersion:] {
 		log.Info("Migration[%d]: %s", v+int64(i), m.Description())
 		if err = m.Migrate(x); err != nil {
diff --git a/models/migrations/v111.go b/models/migrations/v111.go
index 30128abd04..e4efc1ea57 100644
--- a/models/migrations/v111.go
+++ b/models/migrations/v111.go
@@ -11,7 +11,6 @@ import (
 )
 
 func addBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
-
 	type ProtectedBranch struct {
 		CanPush                  bool  `xorm:"NOT NULL DEFAULT false"`
 		EnableApprovalsWhitelist bool  `xorm:"NOT NULL DEFAULT false"`
@@ -23,29 +22,26 @@ func addBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
 		Official bool  `xorm:"NOT NULL DEFAULT false"`
 	}
 
-	sess := x.NewSession()
-	defer sess.Close()
-
-	if err := sess.Sync2(new(ProtectedBranch)); err != nil {
+	if err := x.Sync2(new(ProtectedBranch)); err != nil {
 		return err
 	}
 
-	if err := sess.Sync2(new(Review)); err != nil {
+	if err := x.Sync2(new(Review)); err != nil {
 		return err
 	}
 
-	if _, err := sess.Exec("UPDATE `protected_branch` SET `enable_whitelist` = ? WHERE enable_whitelist IS NULL", false); err != nil {
+	if _, err := x.Exec("UPDATE `protected_branch` SET `enable_whitelist` = ? WHERE enable_whitelist IS NULL", false); err != nil {
 		return err
 	}
-	if _, err := sess.Exec("UPDATE `protected_branch` SET `can_push` = `enable_whitelist`"); err != nil {
+	if _, err := x.Exec("UPDATE `protected_branch` SET `can_push` = `enable_whitelist`"); err != nil {
 		return err
 	}
-	if _, err := sess.Exec("UPDATE `protected_branch` SET `enable_approvals_whitelist` = ? WHERE `required_approvals` > ?", true, 0); err != nil {
+	if _, err := x.Exec("UPDATE `protected_branch` SET `enable_approvals_whitelist` = ? WHERE `required_approvals` > ?", true, 0); err != nil {
 		return err
 	}
 
 	var pageSize int64 = 20
-	qresult, err := sess.QueryInterface("SELECT max(id) as max_id FROM issue")
+	qresult, err := x.QueryInterface("SELECT max(id) as max_id FROM issue")
 	if err != nil {
 		return err
 	}
@@ -57,10 +53,19 @@ func addBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
 	}
 	totalPages := totalIssues / pageSize
 
+	sess := x.NewSession()
+	defer sess.Close()
+
+	if err := sess.Begin(); err != nil {
+		return err
+	}
+
 	// Find latest review of each user in each pull request, and set official field if appropriate
-	reviews := []*models.Review{}
+
 	var page int64
+	var count int
 	for page = 0; page <= totalPages; page++ {
+		reviews := []*models.Review{}
 		if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id > ? AND issue_id <= ? AND type in (?, ?) GROUP BY issue_id, reviewer_id)",
 			page*pageSize, (page+1)*pageSize, models.ReviewTypeApprove, models.ReviewTypeReject).
 			Find(&reviews); err != nil {
@@ -68,23 +73,37 @@ func addBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
 		}
 
 		for _, review := range reviews {
-			if err := review.LoadAttributes(); err != nil {
+			if err := review.LoadAttributesX(sess); err != nil {
 				// Error might occur if user or issue doesn't exist, ignore it.
 				continue
 			}
-			official, err := models.IsOfficialReviewer(review.Issue, review.Reviewer)
+			official, err := models.IsOfficialReviewerX(sess, review.Issue, review.Reviewer)
 			if err != nil {
 				// Branch might not be proteced or other error, ignore it.
 				continue
 			}
 			review.Official = official
 
+			count++
+
 			if _, err := sess.ID(review.ID).Cols("official").Update(review); err != nil {
 				return err
 			}
-		}
 
+			if count == 100 {
+				if err := sess.Commit(); err != nil {
+					return err
+				}
+				count = 0
+				if err := sess.Begin(); err != nil {
+					return err
+				}
+			}
+		}
 	}
 
-	return sess.Commit()
+	if count > 0 {
+		return sess.Commit()
+	}
+	return nil
 }
diff --git a/models/migrations/v115.go b/models/migrations/v115.go
index 67d37536c0..9b5c70a7ac 100644
--- a/models/migrations/v115.go
+++ b/models/migrations/v115.go
@@ -8,8 +8,10 @@ import (
 	"crypto/md5"
 	"fmt"
 	"io/ioutil"
+	"math"
 	"os"
 	"path/filepath"
+	"time"
 
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
@@ -26,8 +28,19 @@ func renameExistingUserAvatarName(x *xorm.Engine) error {
 		LowerName string `xorm:"UNIQUE NOT NULL"`
 		Avatar    string
 	}
+
+	ticker := time.NewTicker(5 * time.Second)
+	defer ticker.Stop()
+
+	count, err := x.Count(new(User))
+	if err != nil {
+		return err
+	}
+	log.Info("%d User Avatar(s) to migrate ...", count)
+
 	deleteList := make(map[string]struct{})
 	start := 0
+	migrated := 0
 	for {
 		if err := sess.Begin(); err != nil {
 			return fmt.Errorf("session.Begin: %v", err)
@@ -73,6 +86,19 @@ func renameExistingUserAvatarName(x *xorm.Engine) error {
 			}
 
 			deleteList[filepath.Join(setting.AvatarUploadPath, oldAvatar)] = struct{}{}
+			migrated++
+			select {
+			case <-ticker.C:
+				log.Info(
+					"%d/%d (%2.0f%%) User Avatar(s) migrated (%d old avatars to be deleted) in %d batches. %d Remaining ...",
+					migrated,
+					count,
+					float64(migrated)/float64(count)*100,
+					len(deleteList),
+					int(math.Ceil(float64(migrated)/float64(50))),
+					count-int64(migrated))
+			default:
+			}
 		}
 		if err := sess.Commit(); err != nil {
 			_ = sess.Rollback()
@@ -80,11 +106,28 @@ func renameExistingUserAvatarName(x *xorm.Engine) error {
 		}
 	}
 
+	deleteCount := len(deleteList)
+	log.Info("Deleting %d old avatars ...", deleteCount)
+	i := 0
 	for file := range deleteList {
 		if err := os.Remove(file); err != nil {
 			log.Warn("os.Remove: %v", err)
 		}
+		i++
+		select {
+		case <-ticker.C:
+			log.Info(
+				"%d/%d (%2.0f%%) Old User Avatar(s) deleted. %d Remaining ...",
+				i,
+				deleteCount,
+				float64(i)/float64(deleteCount)*100,
+				deleteCount-i)
+		default:
+		}
 	}
+
+	log.Info("Completed migrating %d User Avatar(s) and deleting %d Old Avatars", count, deleteCount)
+
 	return nil
 }
 
diff --git a/models/migrations/v128.go b/models/migrations/v128.go
index 1f4bc20527..9f698e3e57 100644
--- a/models/migrations/v128.go
+++ b/models/migrations/v128.go
@@ -6,8 +6,10 @@ package migrations
 
 import (
 	"fmt"
+	"math"
 	"path/filepath"
 	"strings"
+	"time"
 
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/log"
@@ -43,17 +45,27 @@ func fixMergeBase(x *xorm.Engine) error {
 		limit = 50
 	}
 
+	ticker := time.NewTicker(5 * time.Second)
+	defer ticker.Stop()
+
+	count, err := x.Count(new(PullRequest))
+	if err != nil {
+		return err
+	}
+	log.Info("%d Pull Request(s) to migrate ...", count)
+
 	i := 0
+	start := 0
 	for {
 		prs := make([]PullRequest, 0, 50)
-		if err := x.Limit(limit, i).Asc("id").Find(&prs); err != nil {
+		if err := x.Limit(limit, start).Asc("id").Find(&prs); err != nil {
 			return fmt.Errorf("Find: %v", err)
 		}
 		if len(prs) == 0 {
 			break
 		}
 
-		i += len(prs)
+		start += 50
 		for _, pr := range prs {
 			baseRepo := &Repository{ID: pr.BaseRepoID}
 			has, err := x.Table("repository").Get(baseRepo)
@@ -102,8 +114,14 @@ func fixMergeBase(x *xorm.Engine) error {
 			}
 			pr.MergeBase = strings.TrimSpace(pr.MergeBase)
 			x.ID(pr.ID).Cols("merge_base").Update(pr)
+			i++
+			select {
+			case <-ticker.C:
+				log.Info("%d/%d (%2.0f%%) Pull Request(s) migrated in %d batches. %d PRs Remaining ...", i, count, float64(i)/float64(count)*100, int(math.Ceil(float64(i)/float64(limit))), count-int64(i))
+			default:
+			}
 		}
 	}
-
+	log.Info("Completed migrating %d Pull Request(s) in: %d batches", count, int(math.Ceil(float64(i)/float64(limit))))
 	return nil
 }
diff --git a/models/migrations/v134.go b/models/migrations/v134.go
index 527cbafe07..3ad94e7368 100644
--- a/models/migrations/v134.go
+++ b/models/migrations/v134.go
@@ -6,8 +6,10 @@ package migrations
 
 import (
 	"fmt"
+	"math"
 	"path/filepath"
 	"strings"
+	"time"
 
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/log"
@@ -43,17 +45,26 @@ func refixMergeBase(x *xorm.Engine) error {
 		limit = 50
 	}
 
+	ticker := time.NewTicker(5 * time.Second)
+	defer ticker.Stop()
+	count, err := x.Where("has_merged = ?", true).Count(new(PullRequest))
+	if err != nil {
+		return err
+	}
+	log.Info("%d Merged Pull Request(s) to migrate ...", count)
+
 	i := 0
+	start := 0
 	for {
 		prs := make([]PullRequest, 0, 50)
-		if err := x.Limit(limit, i).Asc("id").Where("has_merged = ?", true).Find(&prs); err != nil {
+		if err := x.Limit(limit, start).Asc("id").Where("has_merged = ?", true).Find(&prs); err != nil {
 			return fmt.Errorf("Find: %v", err)
 		}
 		if len(prs) == 0 {
 			break
 		}
 
-		i += len(prs)
+		start += 50
 		for _, pr := range prs {
 			baseRepo := &Repository{ID: pr.BaseRepoID}
 			has, err := x.Table("repository").Get(baseRepo)
@@ -90,7 +101,15 @@ func refixMergeBase(x *xorm.Engine) error {
 			}
 			pr.MergeBase = strings.TrimSpace(pr.MergeBase)
 			x.ID(pr.ID).Cols("merge_base").Update(pr)
+			i++
+			select {
+			case <-ticker.C:
+				log.Info("%d/%d (%2.0f%%) Pull Request(s) migrated in %d batches. %d PRs Remaining ...", i, count, float64(i)/float64(count)*100, int(math.Ceil(float64(i)/float64(limit))), count-int64(i))
+			default:
+			}
 		}
 	}
+
+	log.Info("Completed migrating %d Pull Request(s) in: %d batches", count, int(math.Ceil(float64(i)/float64(limit))))
 	return nil
 }
diff --git a/models/migrations/v136.go b/models/migrations/v136.go
index da5706258e..3f718798ba 100644
--- a/models/migrations/v136.go
+++ b/models/migrations/v136.go
@@ -6,25 +6,60 @@ package migrations
 
 import (
 	"fmt"
+	"math"
+	"path/filepath"
+	"strings"
+	"time"
 
 	"code.gitea.io/gitea/models"
+	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
-	pull_service "code.gitea.io/gitea/services/pull"
 
 	"xorm.io/xorm"
 )
 
 func addCommitDivergenceToPulls(x *xorm.Engine) error {
+	type Repository struct {
+		ID        int64 `xorm:"pk autoincr"`
+		OwnerID   int64 `xorm:"UNIQUE(s) index"`
+		OwnerName string
+		LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
+		Name      string `xorm:"INDEX NOT NULL"`
+	}
+
+	type PullRequest struct {
+		ID int64 `xorm:"pk autoincr"`
+
+		CommitsAhead  int
+		CommitsBehind int
+
+		BaseRepoID int64 `xorm:"INDEX"`
+		BaseBranch string
+
+		HasMerged      bool   `xorm:"INDEX"`
+		MergedCommitID string `xorm:"VARCHAR(40)"`
+	}
 
 	if err := x.Sync2(new(models.PullRequest)); err != nil {
 		return fmt.Errorf("Sync2: %v", err)
 	}
 
-	var last int
+	last := 0
+	migrated := 0
+
 	batchSize := setting.Database.IterateBufferSize
 	sess := x.NewSession()
 	defer sess.Close()
+
+	ticker := time.NewTicker(5 * time.Second)
+	defer ticker.Stop()
+	count, err := sess.Where("has_merged = ?", false).Count(new(PullRequest))
+	if err != nil {
+		return err
+	}
+	log.Info("%d Unmerged Pull Request(s) to migrate ...", count)
+
 	for {
 		if err := sess.Begin(); err != nil {
 			return err
@@ -37,27 +72,53 @@ func addCommitDivergenceToPulls(x *xorm.Engine) error {
 		if len(results) == 0 {
 			break
 		}
-		last += len(results)
+		last += batchSize
 
 		for _, pr := range results {
-			divergence, err := pull_service.GetDiverging(pr)
+			baseRepo := &Repository{ID: pr.BaseRepoID}
+			has, err := x.Table("repository").Get(baseRepo)
+			if err != nil {
+				return fmt.Errorf("Unable to get base repo %d %v", pr.BaseRepoID, err)
+			}
+			if !has {
+				log.Error("Missing base repo with id %d for PR ID %d", pr.BaseRepoID, pr.ID)
+				continue
+			}
+			userPath := filepath.Join(setting.RepoRootPath, strings.ToLower(baseRepo.OwnerName))
+			repoPath := filepath.Join(userPath, strings.ToLower(baseRepo.Name)+".git")
+
+			gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
+
+			divergence, err := git.GetDivergingCommits(repoPath, pr.BaseBranch, gitRefName)
 			if err != nil {
 				log.Warn("Could not recalculate Divergence for pull: %d", pr.ID)
 				pr.CommitsAhead = 0
 				pr.CommitsBehind = 0
 			}
-			if divergence != nil {
-				pr.CommitsAhead = divergence.Ahead
-				pr.CommitsBehind = divergence.Behind
-			}
+			pr.CommitsAhead = divergence.Ahead
+			pr.CommitsBehind = divergence.Behind
+
 			if _, err = sess.ID(pr.ID).Cols("commits_ahead", "commits_behind").Update(pr); err != nil {
 				return fmt.Errorf("Update Cols: %v", err)
 			}
+			migrated++
 		}
 
 		if err := sess.Commit(); err != nil {
 			return err
 		}
+		select {
+		case <-ticker.C:
+			log.Info(
+				"%d/%d (%2.0f%%) Pull Request(s) migrated in %d batches. %d PRs Remaining ...",
+				migrated,
+				count,
+				float64(migrated)/float64(count)*100,
+				int(math.Ceil(float64(migrated)/float64(batchSize))),
+				count-int64(migrated))
+		default:
+		}
 	}
+	log.Info("Completed migrating %d Pull Request(s) in: %d batches", count, int(math.Ceil(float64(migrated)/float64(batchSize))))
 	return nil
 }
diff --git a/models/migrations/v140.go b/models/migrations/v140.go
new file mode 100644
index 0000000000..871d14b84e
--- /dev/null
+++ b/models/migrations/v140.go
@@ -0,0 +1,56 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+	"fmt"
+
+	"code.gitea.io/gitea/modules/setting"
+
+	"xorm.io/xorm"
+)
+
+func fixLanguageStatsToSaveSize(x *xorm.Engine) error {
+	// LanguageStat see models/repo_language_stats.go
+	type LanguageStat struct {
+		Size int64 `xorm:"NOT NULL DEFAULT 0"`
+	}
+
+	// RepoIndexerType specifies the repository indexer type
+	type RepoIndexerType int
+
+	const (
+		// RepoIndexerTypeCode code indexer
+		RepoIndexerTypeCode RepoIndexerType = iota // 0
+		// RepoIndexerTypeStats repository stats indexer
+		RepoIndexerTypeStats // 1
+	)
+
+	// RepoIndexerStatus see models/repo_indexer.go
+	type RepoIndexerStatus struct {
+		IndexerType RepoIndexerType `xorm:"INDEX(s) NOT NULL DEFAULT 0"`
+	}
+
+	if err := x.Sync2(new(LanguageStat)); err != nil {
+		return fmt.Errorf("Sync2: %v", err)
+	}
+
+	x.Delete(&RepoIndexerStatus{IndexerType: RepoIndexerTypeStats})
+
+	// Delete language stat statuses
+	truncExpr := "TRUNCATE TABLE"
+	if setting.Database.UseSQLite3 {
+		truncExpr = "DELETE FROM"
+	}
+
+	// Delete language stats
+	if _, err := x.Exec(fmt.Sprintf("%s language_stat", truncExpr)); err != nil {
+		return err
+	}
+
+	sess := x.NewSession()
+	defer sess.Close()
+	return dropTableColumns(sess, "language_stat", "percentage")
+}
diff --git a/models/models.go b/models/models.go
index c818c65100..af5835d59d 100644
--- a/models/models.go
+++ b/models/models.go
@@ -182,6 +182,10 @@ func SetEngine() (err error) {
 }
 
 // NewEngine initializes a new xorm.Engine
+// This function must never call .Sync2() if the provided migration function fails.
+// When called from the "doctor" command, the migration function is a version check
+// that prevents the doctor from fixing anything in the database if the migration level
+// is different from the expected value.
 func NewEngine(ctx context.Context, migrateFunc func(*xorm.Engine) error) (err error) {
 	if err = SetEngine(); err != nil {
 		return err
@@ -260,6 +264,17 @@ func DumpDatabase(filePath string, dbType string) error {
 		}
 		tbs = append(tbs, t)
 	}
+
+	type Version struct {
+		ID      int64 `xorm:"pk autoincr"`
+		Version int64
+	}
+	t, err := x.TableInfo(Version{})
+	if err != nil {
+		return err
+	}
+	tbs = append(tbs, t)
+
 	if len(dbType) > 0 {
 		return x.DumpTablesToFile(tbs, filePath, schemas.DBType(dbType))
 	}
diff --git a/models/models_test.go b/models/models_test.go
index 37e9a352f8..2441ad7fb0 100644
--- a/models/models_test.go
+++ b/models/models_test.go
@@ -21,6 +21,12 @@ func TestDumpDatabase(t *testing.T) {
 	dir, err := ioutil.TempDir(os.TempDir(), "dump")
 	assert.NoError(t, err)
 
+	type Version struct {
+		ID      int64 `xorm:"pk autoincr"`
+		Version int64
+	}
+	assert.NoError(t, x.Sync2(Version{}))
+
 	for _, dbName := range setting.SupportedDatabases {
 		dbType := setting.GetDBTypeByName(dbName)
 		assert.NoError(t, DumpDatabase(filepath.Join(dir, dbType+".sql"), dbType))
diff --git a/models/notification.go b/models/notification.go
index 1c378a1350..9258b68f22 100644
--- a/models/notification.go
+++ b/models/notification.go
@@ -72,7 +72,7 @@ type FindNotificationOptions struct {
 	UserID            int64
 	RepoID            int64
 	IssueID           int64
-	Status            NotificationStatus
+	Status            []NotificationStatus
 	UpdatedAfterUnix  int64
 	UpdatedBeforeUnix int64
 }
@@ -89,8 +89,8 @@ func (opts *FindNotificationOptions) ToCond() builder.Cond {
 	if opts.IssueID != 0 {
 		cond = cond.And(builder.Eq{"notification.issue_id": opts.IssueID})
 	}
-	if opts.Status != 0 {
-		cond = cond.And(builder.Eq{"notification.status": opts.Status})
+	if len(opts.Status) > 0 {
+		cond = cond.And(builder.In("notification.status", opts.Status))
 	}
 	if opts.UpdatedAfterUnix != 0 {
 		cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix})
diff --git a/models/oauth2_application.go b/models/oauth2_application.go
index eba03d9480..1c7937685c 100644
--- a/models/oauth2_application.go
+++ b/models/oauth2_application.go
@@ -16,7 +16,7 @@ import (
 	"code.gitea.io/gitea/modules/timeutil"
 
 	"github.com/dgrijalva/jwt-go"
-	uuid "github.com/satori/go.uuid"
+	uuid "github.com/google/uuid"
 	"github.com/unknwon/com"
 	"golang.org/x/crypto/bcrypt"
 	"xorm.io/xorm"
@@ -174,7 +174,7 @@ func CreateOAuth2Application(opts CreateOAuth2ApplicationOptions) (*OAuth2Applic
 }
 
 func createOAuth2Application(e Engine, opts CreateOAuth2ApplicationOptions) (*OAuth2Application, error) {
-	clientID := uuid.NewV4().String()
+	clientID := uuid.New().String()
 	app := &OAuth2Application{
 		UID:          opts.UserID,
 		Name:         opts.Name,
diff --git a/models/org.go b/models/org.go
index 58afc5cb59..4a108a80ba 100644
--- a/models/org.go
+++ b/models/org.go
@@ -435,7 +435,7 @@ func hasOrgVisible(e Engine, org *User, user *User) bool {
 		return true
 	}
 
-	if (org.Visibility == structs.VisibleTypePrivate || user.IsRestricted) && !org.isUserPartOfOrg(e, user.ID) {
+	if (org.Visibility == structs.VisibleTypePrivate || user.IsRestricted) && !org.hasMemberWithUserID(e, user.ID) {
 		return false
 	}
 	return true
diff --git a/models/pull_sign.go b/models/pull_sign.go
index 91b8defa53..ab61232d65 100644
--- a/models/pull_sign.go
+++ b/models/pull_sign.go
@@ -27,12 +27,13 @@ func (pr *PullRequest) SignMerge(u *User, tmpBasePath, baseCommit, headCommit st
 	var gitRepo *git.Repository
 	var err error
 
+Loop:
 	for _, rule := range rules {
 		switch rule {
 		case never:
 			return false, "", &ErrWontSign{never}
 		case always:
-			break
+			break Loop
 		case pubkey:
 			keys, err := ListGPGKeys(u.ID, ListOptions{})
 			if err != nil {
diff --git a/models/repo.go b/models/repo.go
index f79740e747..51ea558c37 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -11,6 +11,7 @@ import (
 	"errors"
 	"fmt"
 	"html/template"
+	"unicode/utf8"
 
 	// Needed for jpeg support
 	_ "image/jpeg"
@@ -174,9 +175,10 @@ type Repository struct {
 	*Mirror    `xorm:"-"`
 	Status     RepositoryStatus `xorm:"NOT NULL DEFAULT 0"`
 
-	RenderingMetas  map[string]string `xorm:"-"`
-	Units           []*RepoUnit       `xorm:"-"`
-	PrimaryLanguage *LanguageStat     `xorm:"-"`
+	RenderingMetas         map[string]string `xorm:"-"`
+	DocumentRenderingMetas map[string]string `xorm:"-"`
+	Units                  []*RepoUnit       `xorm:"-"`
+	PrimaryLanguage        *LanguageStat     `xorm:"-"`
 
 	IsFork                          bool               `xorm:"INDEX NOT NULL DEFAULT false"`
 	ForkID                          int64              `xorm:"INDEX"`
@@ -534,11 +536,12 @@ func (repo *Repository) mustOwner(e Engine) *User {
 
 // ComposeMetas composes a map of metas for properly rendering issue links and external issue trackers.
 func (repo *Repository) ComposeMetas() map[string]string {
-	if repo.RenderingMetas == nil {
+	if len(repo.RenderingMetas) == 0 {
 		metas := map[string]string{
 			"user":     repo.OwnerName,
 			"repo":     repo.Name,
 			"repoPath": repo.RepoPath(),
+			"mode":     "comment",
 		}
 
 		unit, err := repo.GetUnit(UnitTypeExternalTracker)
@@ -570,6 +573,19 @@ func (repo *Repository) ComposeMetas() map[string]string {
 	return repo.RenderingMetas
 }
 
+// ComposeDocumentMetas composes a map of metas for properly rendering documents
+func (repo *Repository) ComposeDocumentMetas() map[string]string {
+	if len(repo.DocumentRenderingMetas) == 0 {
+		metas := map[string]string{}
+		for k, v := range repo.ComposeMetas() {
+			metas[k] = v
+		}
+		metas["mode"] = "document"
+		repo.DocumentRenderingMetas = metas
+	}
+	return repo.DocumentRenderingMetas
+}
+
 // DeleteWiki removes the actual and local copy of repository wiki.
 func (repo *Repository) DeleteWiki() error {
 	return repo.deleteWiki(x)
@@ -1369,11 +1385,11 @@ func GetRepositoriesByForkID(forkID int64) ([]*Repository, error) {
 func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err error) {
 	repo.LowerName = strings.ToLower(repo.Name)
 
-	if len(repo.Description) > 255 {
-		repo.Description = repo.Description[:255]
+	if utf8.RuneCountInString(repo.Description) > 255 {
+		repo.Description = string([]rune(repo.Description)[:255])
 	}
-	if len(repo.Website) > 255 {
-		repo.Website = repo.Website[:255]
+	if utf8.RuneCountInString(repo.Website) > 255 {
+		repo.Website = string([]rune(repo.Website)[:255])
 	}
 
 	if _, err = e.ID(repo.ID).AllCols().Update(repo); err != nil {
@@ -1551,6 +1567,10 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
 		releaseAttachments = append(releaseAttachments, attachments[i].LocalPath())
 	}
 
+	if _, err = sess.Exec("UPDATE `user` SET num_stars=num_stars-1 WHERE id IN (SELECT `uid` FROM `star` WHERE repo_id = ?)", repo.ID); err != nil {
+		return err
+	}
+
 	if err = deleteBeans(sess,
 		&Access{RepoID: repo.ID},
 		&Action{RepoID: repo.ID},
@@ -1575,67 +1595,9 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
 		return fmt.Errorf("deleteBeans: %v", err)
 	}
 
-	deleteCond := builder.Select("id").From("issue").Where(builder.Eq{"repo_id": repoID})
-	// Delete comments and attachments
-	if _, err = sess.In("issue_id", deleteCond).
-		Delete(&Comment{}); err != nil {
-		return err
-	}
-
-	// Dependencies for issues in this repository
-	if _, err = sess.In("issue_id", deleteCond).
-		Delete(&IssueDependency{}); err != nil {
-		return err
-	}
-
-	// Delete dependencies for issues in other repositories
-	if _, err = sess.In("dependency_id", deleteCond).
-		Delete(&IssueDependency{}); err != nil {
-		return err
-	}
-
-	if _, err = sess.In("issue_id", deleteCond).
-		Delete(&IssueUser{}); err != nil {
-		return err
-	}
-
-	if _, err = sess.In("issue_id", deleteCond).
-		Delete(&Reaction{}); err != nil {
-		return err
-	}
-
-	if _, err = sess.In("issue_id", deleteCond).
-		Delete(&IssueWatch{}); err != nil {
-		return err
-	}
-
-	if _, err = sess.In("issue_id", deleteCond).
-		Delete(&Stopwatch{}); err != nil {
-		return err
-	}
-
-	if _, err = sess.In("issue_id", deleteCond).
-		Delete(&TrackedTime{}); err != nil {
-		return err
-	}
-
-	attachments = attachments[:0]
-	if err = sess.Join("INNER", "issue", "issue.id = attachment.issue_id").
-		Where("issue.repo_id = ?", repoID).
-		Find(&attachments); err != nil {
-		return err
-	}
-	attachmentPaths := make([]string, 0, len(attachments))
-	for j := range attachments {
-		attachmentPaths = append(attachmentPaths, attachments[j].LocalPath())
-	}
-
-	if _, err = sess.In("issue_id", deleteCond).
-		Delete(&Attachment{}); err != nil {
-		return err
-	}
-
-	if _, err = sess.Delete(&Issue{RepoID: repoID}); err != nil {
+	// Delete Issues and related objects
+	var attachmentPaths []string
+	if attachmentPaths, err = deleteIssuesByRepoID(sess, repoID); err != nil {
 		return err
 	}
 
@@ -1798,22 +1760,28 @@ func GetRepositoriesMapByIDs(ids []int64) (map[int64]*Repository, error) {
 }
 
 // GetUserRepositories returns a list of repositories of given user.
-func GetUserRepositories(opts *SearchRepoOptions) ([]*Repository, error) {
+func GetUserRepositories(opts *SearchRepoOptions) ([]*Repository, int64, error) {
 	if len(opts.OrderBy) == 0 {
 		opts.OrderBy = "updated_unix DESC"
 	}
 
-	sess := x.
-		Where("owner_id = ?", opts.Actor.ID).
-		OrderBy(opts.OrderBy.String())
+	var cond = builder.NewCond()
+	cond = cond.And(builder.Eq{"owner_id": opts.Actor.ID})
 	if !opts.Private {
-		sess.And("is_private=?", false)
+		cond = cond.And(builder.Eq{"is_private": false})
 	}
 
-	sess = opts.setSessionPagination(sess)
+	sess := x.NewSession()
+	defer sess.Close()
 
+	count, err := sess.Where(cond).Count(new(Repository))
+	if err != nil {
+		return nil, 0, fmt.Errorf("Count: %v", err)
+	}
+
+	sess.Where(cond).OrderBy(opts.OrderBy.String())
 	repos := make([]*Repository, 0, opts.PageSize)
-	return repos, opts.setSessionPagination(sess).Find(&repos)
+	return repos, count, opts.setSessionPagination(sess).Find(&repos)
 }
 
 // GetUserMirrorRepositories returns a list of mirror repositories of given user.
@@ -2368,3 +2336,38 @@ func updateRepositoryCols(e Engine, repo *Repository, cols ...string) error {
 func UpdateRepositoryCols(repo *Repository, cols ...string) error {
 	return updateRepositoryCols(x, repo, cols...)
 }
+
+// DoctorUserStarNum recalculate Stars number for all user
+func DoctorUserStarNum() (err error) {
+	const batchSize = 100
+	sess := x.NewSession()
+	defer sess.Close()
+
+	for start := 0; ; start += batchSize {
+		users := make([]User, 0, batchSize)
+		if err = sess.Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil {
+			return
+		}
+		if len(users) == 0 {
+			break
+		}
+
+		if err = sess.Begin(); err != nil {
+			return
+		}
+
+		for _, user := range users {
+			if _, err = sess.Exec("UPDATE `user` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE uid=?) WHERE id=?", user.ID, user.ID); err != nil {
+				return
+			}
+		}
+
+		if err = sess.Commit(); err != nil {
+			return
+		}
+	}
+
+	log.Debug("recalculate Stars number for all user finished")
+
+	return
+}
diff --git a/models/repo_language_stats.go b/models/repo_language_stats.go
index 5f1aed1f30..a15063e25a 100644
--- a/models/repo_language_stats.go
+++ b/models/repo_language_stats.go
@@ -20,7 +20,8 @@ type LanguageStat struct {
 	CommitID    string
 	IsPrimary   bool
 	Language    string             `xorm:"VARCHAR(30) UNIQUE(s) INDEX NOT NULL"`
-	Percentage  float32            `xorm:"NUMERIC(5,2) NOT NULL DEFAULT 0"`
+	Percentage  float32            `xorm:"-"`
+	Size        int64              `xorm:"NOT NULL DEFAULT 0"`
 	Color       string             `xorm:"-"`
 	CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
 }
@@ -34,12 +35,36 @@ func (stats LanguageStatList) loadAttributes() {
 	}
 }
 
+func (stats LanguageStatList) getLanguagePercentages() map[string]float32 {
+	langPerc := make(map[string]float32)
+	var otherPerc float32 = 100
+	var total int64
+
+	for _, stat := range stats {
+		total += stat.Size
+	}
+	if total > 0 {
+		for _, stat := range stats {
+			perc := float32(math.Round(float64(stat.Size)/float64(total)*1000) / 10)
+			if perc <= 0.1 {
+				continue
+			}
+			otherPerc -= perc
+			langPerc[stat.Language] = perc
+		}
+		otherPerc = float32(math.Round(float64(otherPerc)*10) / 10)
+	}
+	if otherPerc > 0 {
+		langPerc["other"] = otherPerc
+	}
+	return langPerc
+}
+
 func (repo *Repository) getLanguageStats(e Engine) (LanguageStatList, error) {
 	stats := make(LanguageStatList, 0, 6)
-	if err := e.Where("`repo_id` = ?", repo.ID).Desc("`percentage`").Find(&stats); err != nil {
+	if err := e.Where("`repo_id` = ?", repo.ID).Desc("`size`").Find(&stats); err != nil {
 		return nil, err
 	}
-	stats.loadAttributes()
 	return stats, nil
 }
 
@@ -54,13 +79,18 @@ func (repo *Repository) GetTopLanguageStats(limit int) (LanguageStatList, error)
 	if err != nil {
 		return nil, err
 	}
+	perc := stats.getLanguagePercentages()
 	topstats := make(LanguageStatList, 0, limit)
 	var other float32
 	for i := range stats {
-		if stats[i].Language == "other" || len(topstats) >= limit {
-			other += stats[i].Percentage
+		if _, ok := perc[stats[i].Language]; !ok {
 			continue
 		}
+		if stats[i].Language == "other" || len(topstats) >= limit {
+			other += perc[stats[i].Language]
+			continue
+		}
+		stats[i].Percentage = perc[stats[i].Language]
 		topstats = append(topstats, stats[i])
 	}
 	if other > 0 {
@@ -71,11 +101,12 @@ func (repo *Repository) GetTopLanguageStats(limit int) (LanguageStatList, error)
 			Percentage: float32(math.Round(float64(other)*10) / 10),
 		})
 	}
+	topstats.loadAttributes()
 	return topstats, nil
 }
 
 // UpdateLanguageStats updates the language statistics for repository
-func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]float32) error {
+func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]int64) error {
 	sess := x.NewSession()
 	if err := sess.Begin(); err != nil {
 		return err
@@ -87,15 +118,15 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]fl
 		return err
 	}
 	var topLang string
-	var p float32
-	for lang, perc := range stats {
-		if perc > p {
-			p = perc
+	var s int64
+	for lang, size := range stats {
+		if size > s {
+			s = size
 			topLang = strings.ToLower(lang)
 		}
 	}
 
-	for lang, perc := range stats {
+	for lang, size := range stats {
 		upd := false
 		llang := strings.ToLower(lang)
 		for _, s := range oldstats {
@@ -103,8 +134,8 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]fl
 			if strings.ToLower(s.Language) == llang {
 				s.CommitID = commitID
 				s.IsPrimary = llang == topLang
-				s.Percentage = perc
-				if _, err := sess.ID(s.ID).Cols("`commit_id`", "`percentage`", "`is_primary`").Update(s); err != nil {
+				s.Size = size
+				if _, err := sess.ID(s.ID).Cols("`commit_id`", "`size`", "`is_primary`").Update(s); err != nil {
 					return err
 				}
 				upd = true
@@ -114,11 +145,11 @@ func (repo *Repository) UpdateLanguageStats(commitID string, stats map[string]fl
 		// Insert new language
 		if !upd {
 			if _, err := sess.Insert(&LanguageStat{
-				RepoID:     repo.ID,
-				CommitID:   commitID,
-				IsPrimary:  llang == topLang,
-				Language:   lang,
-				Percentage: perc,
+				RepoID:    repo.ID,
+				CommitID:  commitID,
+				IsPrimary: llang == topLang,
+				Language:  lang,
+				Size:      size,
 			}); err != nil {
 				return err
 			}
@@ -153,7 +184,7 @@ func CopyLanguageStat(originalRepo, destRepo *Repository) error {
 		return err
 	}
 	RepoLang := make(LanguageStatList, 0, 6)
-	if err := sess.Where("`repo_id` = ?", originalRepo.ID).Desc("`percentage`").Find(&RepoLang); err != nil {
+	if err := sess.Where("`repo_id` = ?", originalRepo.ID).Desc("`size`").Find(&RepoLang); err != nil {
 		return err
 	}
 	if len(RepoLang) > 0 {
diff --git a/models/repo_list.go b/models/repo_list.go
index 316e6d084c..dea88d8816 100644
--- a/models/repo_list.go
+++ b/models/repo_list.go
@@ -140,10 +140,13 @@ type SearchRepoOptions struct {
 	PriorityOwnerID int64
 	OrderBy         SearchOrderBy
 	Private         bool // Include private repositories in results
-	OnlyPrivate     bool // Include only private repositories in results
 	StarredByID     int64
 	AllPublic       bool // Include also all public repositories of users and public organisations
 	AllLimited      bool // Include also all public repositories of limited organisations
+	// None -> include public and private
+	// True -> include just private
+	// False -> incude just public
+	IsPrivate util.OptionalBool
 	// None -> include collaborative AND non-collaborative
 	// True -> include just collaborative
 	// False -> incude just non-collaborative
@@ -221,15 +224,8 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
 				))))
 	}
 
-	if opts.OnlyPrivate {
-		cond = cond.And(
-			builder.Or(
-				builder.Eq{"is_private": true},
-				builder.In("owner_id", builder.Select("id").From("`user`").Where(
-					builder.And(
-						builder.Eq{"type": UserTypeOrganization},
-						builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}),
-					)))))
+	if opts.IsPrivate != util.OptionalBoolNone {
+		cond = cond.And(builder.Eq{"is_private": opts.IsPrivate.IsTrue()})
 	}
 
 	if opts.Template != util.OptionalBoolNone {
@@ -249,14 +245,35 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
 		}
 
 		if opts.Collaborate != util.OptionalBoolFalse {
+			// A Collaboration is:
 			collaborateCond := builder.And(
+				// 1. Repository we don't own
+				builder.Neq{"owner_id": opts.OwnerID},
+				// 2. But we can see because of:
 				builder.Or(
-					builder.Expr("repository.id IN (SELECT repo_id FROM `access` WHERE access.user_id = ?)", opts.OwnerID),
-					builder.In("id", builder.Select("`team_repo`.repo_id").
+					// A. We have access
+					builder.In("`repository`.id",
+						builder.Select("`access`.repo_id").
+							From("access").
+							Where(builder.Eq{"`access`.user_id": opts.OwnerID})),
+					// B. We are in a team for
+					builder.In("`repository`.id", builder.Select("`team_repo`.repo_id").
 						From("team_repo").
 						Where(builder.Eq{"`team_user`.uid": opts.OwnerID}).
-						Join("INNER", "team_user", "`team_user`.team_id = `team_repo`.team_id"))),
-				builder.Neq{"owner_id": opts.OwnerID})
+						Join("INNER", "team_user", "`team_user`.team_id = `team_repo`.team_id")),
+					// C. Public repositories in private organizations that we are member of
+					builder.And(
+						builder.Eq{"`repository`.is_private": false},
+						builder.In("`repository`.owner_id",
+							builder.Select("`org_user`.org_id").
+								From("org_user").
+								Join("INNER", "`user`", "`user`.id = `org_user`.org_id").
+								Where(builder.Eq{
+									"`org_user`.uid":    opts.OwnerID,
+									"`user`.type":       UserTypeOrganization,
+									"`user`.visibility": structs.VisibleTypePrivate,
+								})))),
+			)
 			if !opts.Private {
 				collaborateCond = collaborateCond.And(builder.Expr("owner_id NOT IN (SELECT org_id FROM org_user WHERE org_user.uid = ? AND org_user.is_public = ?)", opts.OwnerID, false))
 			}
diff --git a/models/repo_permission.go b/models/repo_permission.go
index 2061f9770d..7768bb6257 100644
--- a/models/repo_permission.go
+++ b/models/repo_permission.go
@@ -178,7 +178,7 @@ func getUserRepoPermission(e Engine, repo *Repository, user *User) (perm Permiss
 
 	// Prevent strangers from checking out public repo of private orginization
 	// Allow user if they are collaborator of a repo within a private orginization but not a member of the orginization itself
-	if repo.Owner.IsOrganization() && !HasOrgVisible(repo.Owner, user) && !isCollaborator {
+	if repo.Owner.IsOrganization() && !hasOrgVisible(e, repo.Owner, user) && !isCollaborator {
 		perm.AccessMode = AccessModeNone
 		return
 	}
diff --git a/models/repo_test.go b/models/repo_test.go
index 20da43fbbf..045f94670b 100644
--- a/models/repo_test.go
+++ b/models/repo_test.go
@@ -187,3 +187,9 @@ func TestDeleteAvatar(t *testing.T) {
 
 	assert.Equal(t, "", repo.Avatar)
 }
+
+func TestDoctorUserStarNum(t *testing.T) {
+	assert.NoError(t, PrepareTestDatabase())
+
+	assert.NoError(t, DoctorUserStarNum())
+}
diff --git a/models/review.go b/models/review.go
index 522fe5886c..03f15e46eb 100644
--- a/models/review.go
+++ b/models/review.go
@@ -110,7 +110,8 @@ func (r *Review) LoadReviewer() error {
 	return r.loadReviewer(x)
 }
 
-func (r *Review) loadAttributes(e Engine) (err error) {
+// LoadAttributesX loads all attributes except CodeComments with an Engine parameter
+func (r *Review) LoadAttributesX(e Engine) (err error) {
 	if err = r.loadIssue(e); err != nil {
 		return
 	}
@@ -125,7 +126,7 @@ func (r *Review) loadAttributes(e Engine) (err error) {
 
 // LoadAttributes loads all attributes except CodeComments
 func (r *Review) LoadAttributes() error {
-	return r.loadAttributes(x)
+	return r.LoadAttributesX(x)
 }
 
 func getReviewByID(e Engine, id int64) (*Review, error) {
@@ -203,6 +204,12 @@ func IsOfficialReviewer(issue *Issue, reviewer *User) (bool, error) {
 	return isOfficialReviewer(x, issue, reviewer)
 }
 
+// IsOfficialReviewerX check if reviewer can make official reviews in issue (counts towards required approvals)
+// with an Engine parameter
+func IsOfficialReviewerX(e Engine, issue *Issue, reviewer *User) (bool, error) {
+	return isOfficialReviewer(x, issue, reviewer)
+}
+
 func isOfficialReviewer(e Engine, issue *Issue, reviewer *User) (bool, error) {
 	pr, err := getPullRequestByIssueID(e, issue.ID)
 	if err != nil {
diff --git a/models/token.go b/models/token.go
index 71a9f0975f..a18f15f325 100644
--- a/models/token.go
+++ b/models/token.go
@@ -13,7 +13,7 @@ import (
 	"code.gitea.io/gitea/modules/generate"
 	"code.gitea.io/gitea/modules/timeutil"
 
-	gouuid "github.com/satori/go.uuid"
+	gouuid "github.com/google/uuid"
 )
 
 // AccessToken represents a personal access token.
@@ -45,7 +45,7 @@ func NewAccessToken(t *AccessToken) error {
 		return err
 	}
 	t.TokenSalt = salt
-	t.Token = base.EncodeSha1(gouuid.NewV4().String())
+	t.Token = base.EncodeSha1(gouuid.New().String())
 	t.TokenHash = hashToken(t.Token, t.TokenSalt)
 	t.TokenLastEight = t.Token[len(t.Token)-8:]
 	_, err = x.Insert(t)
diff --git a/models/twofactor.go b/models/twofactor.go
index 00a465353a..888c910b94 100644
--- a/models/twofactor.go
+++ b/models/twofactor.go
@@ -142,8 +142,8 @@ func UpdateTwoFactor(t *TwoFactor) error {
 // GetTwoFactorByUID returns the two-factor authentication token associated with
 // the user, if any.
 func GetTwoFactorByUID(uid int64) (*TwoFactor, error) {
-	twofa := &TwoFactor{UID: uid}
-	has, err := x.Get(twofa)
+	twofa := &TwoFactor{}
+	has, err := x.Where("uid=?", uid).Get(twofa)
 	if err != nil {
 		return nil, err
 	} else if !has {
diff --git a/models/upload.go b/models/upload.go
index 65b3220c12..21c73a43f7 100644
--- a/models/upload.go
+++ b/models/upload.go
@@ -14,7 +14,7 @@ import (
 
 	"code.gitea.io/gitea/modules/setting"
 
-	gouuid "github.com/satori/go.uuid"
+	gouuid "github.com/google/uuid"
 	"github.com/unknwon/com"
 )
 
@@ -46,7 +46,7 @@ func (upload *Upload) LocalPath() string {
 // NewUpload creates a new upload object.
 func NewUpload(name string, buf []byte, file multipart.File) (_ *Upload, err error) {
 	upload := &Upload{
-		UUID: gouuid.NewV4().String(),
+		UUID: gouuid.New().String(),
 		Name: name,
 	}
 
@@ -76,8 +76,8 @@ func NewUpload(name string, buf []byte, file multipart.File) (_ *Upload, err err
 
 // GetUploadByUUID returns the Upload by UUID
 func GetUploadByUUID(uuid string) (*Upload, error) {
-	upload := &Upload{UUID: uuid}
-	has, err := x.Get(upload)
+	upload := &Upload{}
+	has, err := x.Where("uuid=?", uuid).Get(upload)
 	if err != nil {
 		return nil, err
 	} else if !has {
diff --git a/models/user.go b/models/user.go
index 8875840db7..87d191eb63 100644
--- a/models/user.go
+++ b/models/user.go
@@ -29,6 +29,7 @@ import (
 	"code.gitea.io/gitea/modules/generate"
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/log"
+	"code.gitea.io/gitea/modules/public"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/structs"
 	api "code.gitea.io/gitea/modules/structs"
@@ -608,12 +609,12 @@ func (u *User) IsUserOrgOwner(orgID int64) bool {
 	return isOwner
 }
 
-// IsUserPartOfOrg returns true if user with userID is part of the u organisation.
-func (u *User) IsUserPartOfOrg(userID int64) bool {
-	return u.isUserPartOfOrg(x, userID)
+// HasMemberWithUserID returns true if user with userID is part of the u organisation.
+func (u *User) HasMemberWithUserID(userID int64) bool {
+	return u.hasMemberWithUserID(x, userID)
 }
 
-func (u *User) isUserPartOfOrg(e Engine, userID int64) bool {
+func (u *User) hasMemberWithUserID(e Engine, userID int64) bool {
 	isMember, err := isOrganizationMember(e, u.ID, userID)
 	if err != nil {
 		log.Error("IsOrganizationMember: %v", err)
@@ -645,7 +646,7 @@ func (u *User) GetOrganizationCount() (int64, error) {
 
 // GetRepositories returns repositories that user owns, including private repositories.
 func (u *User) GetRepositories(listOpts ListOptions) (err error) {
-	u.Repos, err = GetUserRepositories(&SearchRepoOptions{Actor: u, Private: true, ListOptions: listOpts})
+	u.Repos, _, err = GetUserRepositories(&SearchRepoOptions{Actor: u, Private: true, ListOptions: listOpts})
 	return err
 }
 
@@ -878,7 +879,7 @@ func (u *User) IsGhost() bool {
 }
 
 var (
-	reservedUsernames = []string{
+	reservedUsernames = append([]string{
 		".",
 		"..",
 		".well-known",
@@ -888,17 +889,13 @@ var (
 		"attachments",
 		"avatars",
 		"commits",
-		"css",
 		"debug",
 		"error",
 		"explore",
-		"fomantic",
 		"ghost",
 		"help",
-		"img",
 		"install",
 		"issues",
-		"js",
 		"less",
 		"login",
 		"manifest.json",
@@ -916,8 +913,8 @@ var (
 		"stars",
 		"template",
 		"user",
-		"vendor",
-	}
+	}, public.KnownPublicEntries...)
+
 	reservedUserPatterns = []string{"*.keys", "*.gpg"}
 )
 
@@ -1421,11 +1418,21 @@ func getUserEmailsByNames(e Engine, names []string) []string {
 }
 
 // GetMaileableUsersByIDs gets users from ids, but only if they can receive mails
-func GetMaileableUsersByIDs(ids []int64) ([]*User, error) {
+func GetMaileableUsersByIDs(ids []int64, isMention bool) ([]*User, error) {
 	if len(ids) == 0 {
 		return nil, nil
 	}
 	ous := make([]*User, 0, len(ids))
+
+	if isMention {
+		return ous, x.In("id", ids).
+			Where("`type` = ?", UserTypeIndividual).
+			And("`prohibit_login` = ?", false).
+			And("`is_active` = ?", true).
+			And("`email_notifications_preference` IN ( ?, ?)", EmailNotificationsEnabled, EmailNotificationsOnMention).
+			Find(&ous)
+	}
+
 	return ous, x.In("id", ids).
 		Where("`type` = ?", UserTypeIndividual).
 		And("`prohibit_login` = ?", false).
@@ -1558,8 +1565,8 @@ func GetUserByEmailContext(ctx DBContext, email string) (*User, error) {
 	// Finally, if email address is the protected email address:
 	if strings.HasSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress)) {
 		username := strings.TrimSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress))
-		user := &User{LowerName: username}
-		has, err := ctx.e.Get(user)
+		user := &User{}
+		has, err := ctx.e.Where("lower_name=?", username).Get(user)
 		if err != nil {
 			return nil, err
 		}
diff --git a/models/user_heatmap_test.go b/models/user_heatmap_test.go
index c2825d9ff0..c9d33db29b 100644
--- a/models/user_heatmap_test.go
+++ b/models/user_heatmap_test.go
@@ -17,7 +17,7 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
 		CountResult int
 		JSONResult  string
 	}{
-		{2, 1, `[{"timestamp":1571616000,"contributions":1}]`},
+		{2, 1, `[{"timestamp":1603152000,"contributions":1}]`},
 		{3, 0, `[]`},
 	}
 	// Prepare
diff --git a/models/user_mail.go b/models/user_mail.go
index af9602e714..60354e23ff 100644
--- a/models/user_mail.go
+++ b/models/user_mail.go
@@ -71,8 +71,8 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) {
 // GetEmailAddressByID gets a user's email address by ID
 func GetEmailAddressByID(uid, id int64) (*EmailAddress, error) {
 	// User ID is required for security reasons
-	email := &EmailAddress{ID: id, UID: uid}
-	if has, err := x.Get(email); err != nil {
+	email := &EmailAddress{UID: uid}
+	if has, err := x.ID(id).Get(email); err != nil {
 		return nil, err
 	} else if !has {
 		return nil, nil
@@ -126,7 +126,7 @@ func isEmailUsed(e Engine, email string) (bool, error) {
 		return true, nil
 	}
 
-	return e.Get(&EmailAddress{Email: email})
+	return e.Where("email=?", email).Get(&EmailAddress{})
 }
 
 // IsEmailUsed returns true if the email has been used.
@@ -251,8 +251,8 @@ func MakeEmailPrimary(email *EmailAddress) error {
 		return ErrEmailNotActivated
 	}
 
-	user := &User{ID: email.UID}
-	has, err = x.Get(user)
+	user := &User{}
+	has, err = x.ID(email.UID).Get(user)
 	if err != nil {
 		return err
 	} else if !has {
diff --git a/models/user_openid.go b/models/user_openid.go
index 49edc1db21..503c2a52d1 100644
--- a/models/user_openid.go
+++ b/models/user_openid.go
@@ -111,8 +111,8 @@ func GetUserByOpenID(uri string) (*User, error) {
 	log.Trace("Normalized OpenID URI: " + uri)
 
 	// Otherwise, check in openid table
-	oid := &UserOpenID{URI: uri}
-	has, err := x.Get(oid)
+	oid := &UserOpenID{}
+	has, err := x.Where("uri=?", uri).Get(oid)
 	if err != nil {
 		return nil, err
 	}
diff --git a/models/user_test.go b/models/user_test.go
index 02b1893c43..607a08e677 100644
--- a/models/user_test.go
+++ b/models/user_test.go
@@ -389,3 +389,20 @@ func TestGetUserIDsByNames(t *testing.T) {
 	assert.Error(t, err)
 	assert.Equal(t, []int64(nil), IDs)
 }
+
+func TestGetMaileableUsersByIDs(t *testing.T) {
+	results, err := GetMaileableUsersByIDs([]int64{1, 4}, false)
+	assert.NoError(t, err)
+	assert.Equal(t, 1, len(results))
+	if len(results) > 1 {
+		assert.Equal(t, results[0].ID, 1)
+	}
+
+	results, err = GetMaileableUsersByIDs([]int64{1, 4}, true)
+	assert.NoError(t, err)
+	assert.Equal(t, 2, len(results))
+	if len(results) > 2 {
+		assert.Equal(t, results[0].ID, 1)
+		assert.Equal(t, results[1].ID, 4)
+	}
+}
diff --git a/models/webhook.go b/models/webhook.go
index 5f3a285691..54cd9b6565 100644
--- a/models/webhook.go
+++ b/models/webhook.go
@@ -15,7 +15,7 @@ import (
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/timeutil"
 
-	gouuid "github.com/satori/go.uuid"
+	gouuid "github.com/google/uuid"
 )
 
 // HookContentType is the content type of a web hook
@@ -769,7 +769,7 @@ func createHookTask(e Engine, t *HookTask) error {
 	if err != nil {
 		return err
 	}
-	t.UUID = gouuid.NewV4().String()
+	t.UUID = gouuid.New().String()
 	t.PayloadContent = string(data)
 	_, err = e.Insert(t)
 	return err
diff --git a/modules/analyze/code_langauge.go b/modules/analyze/code_langauge.go
index 3bd2d512f9..baec2cebc5 100644
--- a/modules/analyze/code_langauge.go
+++ b/modules/analyze/code_langauge.go
@@ -10,8 +10,8 @@ import (
 	"github.com/go-enry/go-enry/v2"
 )
 
-// GetCodeLanguageWithCallback detects code language based on file name and content using callback
-func GetCodeLanguageWithCallback(filename string, contentFunc func() ([]byte, error)) string {
+// GetCodeLanguage detects code language based on file name and content
+func GetCodeLanguage(filename string, content []byte) string {
 	if language, ok := enry.GetLanguageByExtension(filename); ok {
 		return language
 	}
@@ -20,17 +20,9 @@ func GetCodeLanguageWithCallback(filename string, contentFunc func() ([]byte, er
 		return language
 	}
 
-	content, err := contentFunc()
-	if err != nil {
+	if len(content) == 0 {
 		return enry.OtherLanguage
 	}
 
 	return enry.GetLanguage(filepath.Base(filename), content)
 }
-
-// GetCodeLanguage detects code language based on file name and content
-func GetCodeLanguage(filename string, content []byte) string {
-	return GetCodeLanguageWithCallback(filename, func() ([]byte, error) {
-		return content, nil
-	})
-}
diff --git a/modules/auth/admin.go b/modules/auth/admin.go
index af7197d2ae..9caf81e07f 100644
--- a/modules/auth/admin.go
+++ b/modules/auth/admin.go
@@ -51,7 +51,8 @@ func (f *AdminEditUserForm) Validate(ctx *macaron.Context, errs binding.Errors)
 
 // AdminDashboardForm form for admin dashboard operations
 type AdminDashboardForm struct {
-	Op string `binding:"required"`
+	Op   string `binding:"required"`
+	From string
 }
 
 // Validate validates form fields
diff --git a/modules/auth/oauth2/oauth2.go b/modules/auth/oauth2/oauth2.go
index a50c639885..2c982e1dca 100644
--- a/modules/auth/oauth2/oauth2.go
+++ b/modules/auth/oauth2/oauth2.go
@@ -6,10 +6,12 @@ package oauth2
 
 import (
 	"net/http"
+	"net/url"
 
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
 
+	uuid "github.com/google/uuid"
 	"github.com/lafriks/xormstore"
 	"github.com/markbates/goth"
 	"github.com/markbates/goth/gothic"
@@ -25,7 +27,6 @@ import (
 	"github.com/markbates/goth/providers/openidConnect"
 	"github.com/markbates/goth/providers/twitter"
 	"github.com/markbates/goth/providers/yandex"
-	uuid "github.com/satori/go.uuid"
 	"xorm.io/xorm"
 )
 
@@ -61,7 +62,7 @@ func Init(x *xorm.Engine) error {
 	gothic.Store = store
 
 	gothic.SetState = func(req *http.Request) string {
-		return uuid.NewV4().String()
+		return uuid.New().String()
 	}
 
 	gothic.GetProviderName = func(req *http.Request) (string, error) {
@@ -119,7 +120,7 @@ func RemoveProvider(providerName string) {
 
 // used to create different types of goth providers
 func createProvider(providerName, providerType, clientID, clientSecret, openIDConnectAutoDiscoveryURL string, customURLMapping *CustomURLMapping) (goth.Provider, error) {
-	callbackURL := setting.AppURL + "user/oauth2/" + providerName + "/callback"
+	callbackURL := setting.AppURL + "user/oauth2/" + url.PathEscape(providerName) + "/callback"
 
 	var provider goth.Provider
 	var err error
diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go
index 6c3421e4f7..c51adadba1 100644
--- a/modules/auth/repo_form.go
+++ b/modules/auth/repo_form.go
@@ -97,6 +97,9 @@ func (f MigrateRepoForm) ParseRemoteAddr(user *models.User) (string, error) {
 			u.User = url.UserPassword(f.AuthUsername, f.AuthPassword)
 		}
 		remoteAddr = u.String()
+		if u.Scheme == "git" && u.Port() != "" && (strings.Contains(remoteAddr, "%0d") || strings.Contains(remoteAddr, "%0a")) {
+			return "", models.ErrInvalidCloneAddr{IsURLError: true}
+		}
 	} else if !user.CanImportLocal() {
 		return "", models.ErrInvalidCloneAddr{IsPermissionDenied: true}
 	} else if !com.IsDir(remoteAddr) {
diff --git a/modules/auth/sso/oauth2.go b/modules/auth/sso/oauth2.go
index e677490b80..3f530f036f 100644
--- a/modules/auth/sso/oauth2.go
+++ b/modules/auth/sso/oauth2.go
@@ -93,7 +93,7 @@ func (o *OAuth2) userIDFromToken(ctx *macaron.Context) int64 {
 	}
 	t, err := models.GetAccessTokenBySHA(tokenSHA)
 	if err != nil {
-		if models.IsErrAccessTokenNotExist(err) || models.IsErrAccessTokenEmpty(err) {
+		if !models.IsErrAccessTokenNotExist(err) && !models.IsErrAccessTokenEmpty(err) {
 			log.Error("GetAccessTokenBySHA: %v", err)
 		}
 		return 0
@@ -121,7 +121,7 @@ func (o *OAuth2) VerifyAuthData(ctx *macaron.Context, sess session.Store) *model
 		return nil
 	}
 
-	if !isAPIPath(ctx) && !isAttachmentDownload(ctx) {
+	if isInternalPath(ctx) || !isAPIPath(ctx) && !isAttachmentDownload(ctx) {
 		return nil
 	}
 
diff --git a/modules/auth/sso/reverseproxy.go b/modules/auth/sso/reverseproxy.go
index feb5364518..1b543ce104 100644
--- a/modules/auth/sso/reverseproxy.go
+++ b/modules/auth/sso/reverseproxy.go
@@ -14,7 +14,7 @@ import (
 
 	"gitea.com/macaron/macaron"
 	"gitea.com/macaron/session"
-	gouuid "github.com/satori/go.uuid"
+	gouuid "github.com/google/uuid"
 )
 
 // Ensure the struct implements the interface.
@@ -92,7 +92,7 @@ func (r *ReverseProxy) newUser(ctx *macaron.Context) *models.User {
 		return nil
 	}
 
-	email := gouuid.NewV4().String() + "@localhost"
+	email := gouuid.New().String() + "@localhost"
 	if setting.Service.EnableReverseProxyEmail {
 		webAuthEmail := ctx.Req.Header.Get(setting.ReverseProxyAuthEmail)
 		if len(webAuthEmail) > 0 {
diff --git a/modules/auth/sso/sso.go b/modules/auth/sso/sso.go
index cf8148d89b..c2e36f3f5e 100644
--- a/modules/auth/sso/sso.go
+++ b/modules/auth/sso/sso.go
@@ -100,6 +100,11 @@ func isAPIPath(ctx *macaron.Context) bool {
 	return strings.HasPrefix(ctx.Req.URL.Path, "/api/")
 }
 
+// isInternalPath returns true if the specified URL is an internal API path
+func isInternalPath(ctx *macaron.Context) bool {
+	return strings.HasPrefix(ctx.Req.URL.Path, "/api/internal/")
+}
+
 // isAttachmentDownload check if request is a file download (GET) with URL to an attachment
 func isAttachmentDownload(ctx *macaron.Context) bool {
 	return strings.HasPrefix(ctx.Req.URL.Path, "/attachments/") && ctx.Req.Method == "GET"
diff --git a/modules/auth/sso/sspi_windows.go b/modules/auth/sso/sspi_windows.go
index 3153fc63cd..00f15d97be 100644
--- a/modules/auth/sso/sspi_windows.go
+++ b/modules/auth/sso/sspi_windows.go
@@ -17,8 +17,8 @@ import (
 	"gitea.com/macaron/macaron"
 	"gitea.com/macaron/session"
 
+	gouuid "github.com/google/uuid"
 	"github.com/quasoft/websspi"
-	gouuid "github.com/satori/go.uuid"
 )
 
 const (
@@ -148,6 +148,8 @@ func (s *SSPI) shouldAuthenticate(ctx *macaron.Context) (shouldAuth bool) {
 		} else if ctx.Req.FormValue("auth_with_sspi") == "1" {
 			shouldAuth = true
 		}
+	} else if isInternalPath(ctx) {
+		shouldAuth = false
 	} else if isAPIPath(ctx) || isAttachmentDownload(ctx) {
 		shouldAuth = true
 	}
@@ -157,12 +159,12 @@ func (s *SSPI) shouldAuthenticate(ctx *macaron.Context) (shouldAuth bool) {
 // newUser creates a new user object for the purpose of automatic registration
 // and populates its name and email with the information present in request headers.
 func (s *SSPI) newUser(ctx *macaron.Context, username string, cfg *models.SSPIConfig) (*models.User, error) {
-	email := gouuid.NewV4().String() + "@localhost.localdomain"
+	email := gouuid.New().String() + "@localhost.localdomain"
 	user := &models.User{
 		Name:                         username,
 		Email:                        email,
 		KeepEmailPrivate:             true,
-		Passwd:                       gouuid.NewV4().String(),
+		Passwd:                       gouuid.New().String(),
 		IsActive:                     cfg.AutoActivateUsers,
 		Language:                     cfg.DefaultLanguage,
 		UseCustomAvatar:              true,
diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go
index 228e17dce5..a87404fe8c 100644
--- a/modules/auth/user_form.go
+++ b/modules/auth/user_form.go
@@ -196,14 +196,14 @@ func (f *AccessTokenForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
 
 // UpdateProfileForm form for updating profile
 type UpdateProfileForm struct {
-	Name             string `binding:"AlphaDashDot;MaxSize(40)"`
-	FullName         string `binding:"MaxSize(100)"`
-	Email            string `binding:"Required;Email;MaxSize(254)"`
-	KeepEmailPrivate bool
-	Website          string `binding:"ValidUrl;MaxSize(255)"`
-	Location         string `binding:"MaxSize(50)"`
-	Language         string `binding:"Size(5)"`
-	Description      string `binding:"MaxSize(255)"`
+	Name                string `binding:"AlphaDashDot;MaxSize(40)"`
+	FullName            string `binding:"MaxSize(100)"`
+	KeepEmailPrivate    bool
+	Website             string `binding:"ValidUrl;MaxSize(255)"`
+	Location            string `binding:"MaxSize(50)"`
+	Language            string `binding:"Size(5)"`
+	Description         string `binding:"MaxSize(255)"`
+	KeepActivityPrivate bool
 }
 
 // Validate validates the fields
diff --git a/modules/avatar/avatar.go b/modules/avatar/avatar.go
index cf3da6df5e..f4c0655fa9 100644
--- a/modules/avatar/avatar.go
+++ b/modules/avatar/avatar.go
@@ -89,6 +89,6 @@ func Prepare(data []byte) (*image.Image, error) {
 		}
 	}
 
-	img = resize.Resize(AvatarSize, AvatarSize, img, resize.NearestNeighbor)
+	img = resize.Resize(AvatarSize, AvatarSize, img, resize.Bilinear)
 	return &img, nil
 }
diff --git a/modules/cache/last_commit.go b/modules/cache/last_commit.go
index 4f17cd8fa5..660a9250d6 100644
--- a/modules/cache/last_commit.go
+++ b/modules/cache/last_commit.go
@@ -5,6 +5,7 @@
 package cache
 
 import (
+	"crypto/sha256"
 	"fmt"
 
 	"code.gitea.io/gitea/modules/git"
@@ -34,9 +35,14 @@ func NewLastCommitCache(repoPath string, gitRepo *git.Repository, ttl int64) *La
 	}
 }
 
+func (c LastCommitCache) getCacheKey(repoPath, ref, entryPath string) string {
+	hashBytes := sha256.Sum256([]byte(fmt.Sprintf("%s:%s:%s", repoPath, ref, entryPath)))
+	return fmt.Sprintf("last_commit:%x", hashBytes)
+}
+
 // Get get the last commit information by commit id and entry path
 func (c LastCommitCache) Get(ref, entryPath string) (*object.Commit, error) {
-	v := c.Cache.Get(fmt.Sprintf("last_commit:%s:%s:%s", c.repoPath, ref, entryPath))
+	v := c.Cache.Get(c.getCacheKey(c.repoPath, ref, entryPath))
 	if vs, ok := v.(string); ok {
 		log.Trace("LastCommitCache hit level 1: [%s:%s:%s]", ref, entryPath, vs)
 		if commit, ok := c.commitCache[vs]; ok {
@@ -60,5 +66,5 @@ func (c LastCommitCache) Get(ref, entryPath string) (*object.Commit, error) {
 // Put put the last commit id with commit and entry path
 func (c LastCommitCache) Put(ref, entryPath, commitID string) error {
 	log.Trace("LastCommitCache save: [%s:%s:%s]", ref, entryPath, commitID)
-	return c.Cache.Put(fmt.Sprintf("last_commit:%s:%s:%s", c.repoPath, ref, entryPath), commitID, c.ttl)
+	return c.Cache.Put(c.getCacheKey(c.repoPath, ref, entryPath), commitID, c.ttl)
 }
diff --git a/modules/context/api.go b/modules/context/api.go
index 4e189ce077..a843e79e4a 100644
--- a/modules/context/api.go
+++ b/modules/context/api.go
@@ -7,6 +7,7 @@ package context
 
 import (
 	"fmt"
+	"net/http"
 	"net/url"
 	"strings"
 
@@ -64,18 +65,22 @@ type APINotFound struct{}
 // swagger:response redirect
 type APIRedirect struct{}
 
-// Error responses error message to client with given message.
+// Error responds with an error message to client with given obj as the message.
 // If status is 500, also it prints error to log.
 func (ctx *APIContext) Error(status int, title string, obj interface{}) {
 	var message string
 	if err, ok := obj.(error); ok {
 		message = err.Error()
 	} else {
-		message = obj.(string)
+		message = fmt.Sprintf("%s", obj)
 	}
 
-	if status == 500 {
-		log.Error("%s: %s", title, message)
+	if status == http.StatusInternalServerError {
+		log.ErrorWithSkip(1, "%s: %s", title, message)
+
+		if macaron.Env == macaron.PROD {
+			message = ""
+		}
 	}
 
 	ctx.JSON(status, APIError{
@@ -84,6 +89,22 @@ func (ctx *APIContext) Error(status int, title string, obj interface{}) {
 	})
 }
 
+// InternalServerError responds with an error message to the client with the error as a message
+// and the file and line of the caller.
+func (ctx *APIContext) InternalServerError(err error) {
+	log.ErrorWithSkip(1, "InternalServerError: %v", err)
+
+	var message string
+	if macaron.Env != macaron.PROD {
+		message = err.Error()
+	}
+
+	ctx.JSON(http.StatusInternalServerError, APIError{
+		Message: message,
+		URL:     setting.API.SwaggerURL,
+	})
+}
+
 func genAPILinks(curURL *url.URL, total, pageSize, curPage int) []string {
 	page := NewPagination(total, pageSize, curPage, 0)
 	paginater := page.Paginater
@@ -230,3 +251,61 @@ func (ctx *APIContext) NotFound(objs ...interface{}) {
 		"errors":            errors,
 	})
 }
+
+// RepoRefForAPI handles repository reference names when the ref name is not explicitly given
+func RepoRefForAPI() macaron.Handler {
+	return func(ctx *APIContext) {
+		// Empty repository does not have reference information.
+		if ctx.Repo.Repository.IsEmpty {
+			return
+		}
+
+		var err error
+
+		if ctx.Repo.GitRepo == nil {
+			repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
+			ctx.Repo.GitRepo, err = git.OpenRepository(repoPath)
+			if err != nil {
+				ctx.InternalServerError(err)
+				return
+			}
+			// We opened it, we should close it
+			defer func() {
+				// If it's been set to nil then assume someone else has closed it.
+				if ctx.Repo.GitRepo != nil {
+					ctx.Repo.GitRepo.Close()
+				}
+			}()
+		}
+
+		refName := getRefName(ctx.Context, RepoRefAny)
+
+		if ctx.Repo.GitRepo.IsBranchExist(refName) {
+			ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
+			if err != nil {
+				ctx.InternalServerError(err)
+				return
+			}
+			ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
+		} else if ctx.Repo.GitRepo.IsTagExist(refName) {
+			ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetTagCommit(refName)
+			if err != nil {
+				ctx.InternalServerError(err)
+				return
+			}
+			ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
+		} else if len(refName) == 40 {
+			ctx.Repo.CommitID = refName
+			ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
+			if err != nil {
+				ctx.NotFound("GetCommit", err)
+				return
+			}
+		} else {
+			ctx.NotFound(fmt.Errorf("not exist: '%s'", ctx.Params("*")))
+			return
+		}
+
+		ctx.Next()
+	}
+}
diff --git a/modules/context/auth.go b/modules/context/auth.go
index 7410db75a5..86922aae59 100644
--- a/modules/context/auth.go
+++ b/modules/context/auth.go
@@ -49,7 +49,9 @@ func Toggle(options *ToggleOptions) macaron.Handler {
 				if ctx.Req.URL.Path != "/user/settings/change_password" {
 					ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
 					ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
-					ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)
+					if ctx.Req.URL.Path != "/user/events" {
+						ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)
+					}
 					ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
 					return
 				}
diff --git a/modules/context/repo.go b/modules/context/repo.go
index 5ebed0eb7e..a749ab04eb 100644
--- a/modules/context/repo.go
+++ b/modules/context/repo.go
@@ -690,7 +690,6 @@ func RepoRefByType(refType RepoRefType) macaron.Handler {
 			err     error
 		)
 
-		// For API calls.
 		if ctx.Repo.GitRepo == nil {
 			repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
 			ctx.Repo.GitRepo, err = git.OpenRepository(repoPath)
@@ -759,7 +758,7 @@ func RepoRefByType(refType RepoRefType) macaron.Handler {
 
 				ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
 				if err != nil {
-					ctx.NotFound("GetCommit", nil)
+					ctx.NotFound("GetCommit", err)
 					return
 				}
 			} else {
diff --git a/modules/convert/convert.go b/modules/convert/convert.go
index ec18b13056..84b61eb40e 100644
--- a/modules/convert/convert.go
+++ b/modules/convert/convert.go
@@ -1,4 +1,5 @@
 // Copyright 2015 The Gogs Authors. All rights reserved.
+// Copyright 2018 The Gitea Authors. All rights reserved.
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
@@ -67,8 +68,12 @@ func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit, bp *models.
 	}
 
 	if user != nil {
+		permission, err := models.GetUserRepoPermission(repo, user)
+		if err != nil {
+			return nil, err
+		}
 		branch.UserCanPush = bp.CanUserPush(user.ID)
-		branch.UserCanMerge = bp.IsUserMergeWhitelisted(user.ID)
+		branch.UserCanMerge = bp.IsUserMergeWhitelisted(user.ID, permission)
 	}
 
 	return branch, nil
@@ -331,9 +336,11 @@ func ToTeam(team *models.Team) *api.Team {
 // signed shall only be set if requester is logged in. authed shall only be set if user is site admin or user himself
 func ToUser(user *models.User, signed, authed bool) *api.User {
 	result := &api.User{
+		ID:        user.ID,
 		UserName:  user.Name,
-		AvatarURL: user.AvatarLink(),
 		FullName:  markup.Sanitize(user.FullName),
+		Email:     user.GetEmail(),
+		AvatarURL: user.AvatarLink(),
 		Created:   user.CreatedUnix.AsTime(),
 	}
 	// hide primary email if API caller is anonymous or user keep email private
@@ -342,7 +349,6 @@ func ToUser(user *models.User, signed, authed bool) *api.User {
 	}
 	// only site admin will get these information and possibly user himself
 	if authed {
-		result.ID = user.ID
 		result.IsAdmin = user.IsAdmin
 		result.LastLogin = user.LastLoginUnix.AsTime()
 		result.Language = user.Language
diff --git a/modules/convert/pull_review.go b/modules/convert/pull_review.go
index 619f9f070e..032d3617fc 100644
--- a/modules/convert/pull_review.go
+++ b/modules/convert/pull_review.go
@@ -103,7 +103,7 @@ func ToPullReviewCommentList(review *models.Review, doer *models.User) ([]*api.P
 					OrigCommitID: comment.OldRef,
 					DiffHunk:     patch2diff(comment.Patch),
 					HTMLURL:      comment.HTMLURL(),
-					HTMLPullURL:  review.Issue.APIURL(),
+					HTMLPullURL:  review.Issue.HTMLURL(),
 				}
 
 				if comment.Line < 0 {
diff --git a/modules/convert/utils.go b/modules/convert/utils.go
index 66fb21be67..ddb8a8820d 100644
--- a/modules/convert/utils.go
+++ b/modules/convert/utils.go
@@ -11,7 +11,7 @@ import (
 // ToCorrectPageSize makes sure page size is in allowed range.
 func ToCorrectPageSize(size int) int {
 	if size <= 0 {
-		size = 10
+		size = setting.API.DefaultPagingNum
 	} else if size > setting.API.MaxResponseItems {
 		size = setting.API.MaxResponseItems
 	}
diff --git a/modules/emoji/emoji.go b/modules/emoji/emoji.go
index 2a51e61fcf..169ee0a182 100644
--- a/modules/emoji/emoji.go
+++ b/modules/emoji/emoji.go
@@ -6,6 +6,7 @@
 package emoji
 
 import (
+	"sort"
 	"strings"
 	"sync"
 )
@@ -19,6 +20,7 @@ type Emoji struct {
 	Description    string
 	Aliases        []string
 	UnicodeVersion string
+	SkinTones      bool
 }
 
 var (
@@ -48,6 +50,12 @@ func loadMap() {
 		// process emoji codes and aliases
 		codePairs := make([]string, 0)
 		aliasPairs := make([]string, 0)
+
+		// sort from largest to small so we match combined emoji first
+		sort.Slice(GemojiData, func(i, j int) bool {
+			return len(GemojiData[i].Emoji) > len(GemojiData[j].Emoji)
+		})
+
 		for i, e := range GemojiData {
 			if e.Emoji == "" || len(e.Aliases) == 0 {
 				continue
@@ -72,6 +80,7 @@ func loadMap() {
 		codeReplacer = strings.NewReplacer(codePairs...)
 		aliasReplacer = strings.NewReplacer(aliasPairs...)
 	})
+
 }
 
 // FromCode retrieves the emoji data based on the provided unicode code (ie,
@@ -117,3 +126,39 @@ func ReplaceAliases(s string) string {
 	loadMap()
 	return aliasReplacer.Replace(s)
 }
+
+// FindEmojiSubmatchIndex returns index pair of longest emoji in a string
+func FindEmojiSubmatchIndex(s string) []int {
+	loadMap()
+	found := make(map[int]int)
+	keys := make([]int, 0)
+
+	//see if there are any emoji in string before looking for position of specific ones
+	//no performance difference when there is a match but 10x faster when there are not
+	if s == ReplaceCodes(s) {
+		return nil
+	}
+
+	// get index of first emoji occurrence while also checking for longest combination
+	for j := range GemojiData {
+		i := strings.Index(s, GemojiData[j].Emoji)
+		if i != -1 {
+			if _, ok := found[i]; !ok {
+				if len(keys) == 0 || i < keys[0] {
+					found[i] = j
+					keys = []int{i}
+				}
+				if i == 0 {
+					break
+				}
+			}
+		}
+	}
+
+	if len(keys) > 0 {
+		index := keys[0]
+		return []int{index, index + len(GemojiData[found[index]].Emoji)}
+	}
+
+	return nil
+}
diff --git a/modules/emoji/emoji_data.go b/modules/emoji/emoji_data.go
index 36f6dec27e..1fb08767bb 100644
--- a/modules/emoji/emoji_data.go
+++ b/modules/emoji/emoji_data.go
@@ -8,1727 +8,3102 @@ package emoji
 // Sourced from https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json
 //
 var GemojiData = Gemoji{
-	{"\U0001f44d", "thumbs up", []string{"+1", "thumbsup"}, "6.0"},
-	{"\U0001f44e", "thumbs down", []string{"-1", "thumbsdown"}, "6.0"},
-	{"\U0001f4af", "hundred points", []string{"100"}, "6.0"},
-	{"\U0001f522", "input numbers", []string{"1234"}, "6.0"},
-	{"\U0001f947", "1st place medal", []string{"1st_place_medal"}, "9.0"},
-	{"\U0001f948", "2nd place medal", []string{"2nd_place_medal"}, "9.0"},
-	{"\U0001f949", "3rd place medal", []string{"3rd_place_medal"}, "9.0"},
-	{"\U0001f3b1", "pool 8 ball", []string{"8ball"}, "6.0"},
-	{"\U0001f170\ufe0f", "A button (blood type)", []string{"a"}, "6.0"},
-	{"\U0001f18e", "AB button (blood type)", []string{"ab"}, "6.0"},
-	{"\U0001f9ee", "abacus", []string{"abacus"}, "11.0"},
-	{"\U0001f524", "input latin letters", []string{"abc"}, "6.0"},
-	{"\U0001f521", "input latin lowercase", []string{"abcd"}, "6.0"},
-	{"\U0001f251", "Japanese โ€œacceptableโ€ button", []string{"accept"}, "6.0"},
-	{"\U0001fa79", "adhesive bandage", []string{"adhesive_bandage"}, "12.0"},
-	{"\U0001f9d1", "person", []string{"adult"}, "11.0"},
-	{"\U0001f6a1", "aerial tramway", []string{"aerial_tramway"}, "6.0"},
-	{"\U0001f1e6\U0001f1eb", "flag: Afghanistan", []string{"afghanistan"}, "6.0"},
-	{"\u2708\ufe0f", "airplane", []string{"airplane"}, ""},
-	{"\U0001f1e6\U0001f1fd", "flag: ร…land Islands", []string{"aland_islands"}, "6.0"},
-	{"\u23f0", "alarm clock", []string{"alarm_clock"}, "6.0"},
-	{"\U0001f1e6\U0001f1f1", "flag: Albania", []string{"albania"}, "6.0"},
-	{"\u2697\ufe0f", "alembic", []string{"alembic"}, "4.1"},
-	{"\U0001f1e9\U0001f1ff", "flag: Algeria", []string{"algeria"}, "6.0"},
-	{"\U0001f47d", "alien", []string{"alien"}, "6.0"},
-	{"\U0001f691", "ambulance", []string{"ambulance"}, "6.0"},
-	{"\U0001f1e6\U0001f1f8", "flag: American Samoa", []string{"american_samoa"}, "6.0"},
-	{"\U0001f3fa", "amphora", []string{"amphora"}, "8.0"},
-	{"\u2693", "anchor", []string{"anchor"}, "4.1"},
-	{"\U0001f1e6\U0001f1e9", "flag: Andorra", []string{"andorra"}, "6.0"},
-	{"\U0001f47c", "baby angel", []string{"angel"}, "6.0"},
-	{"\U0001f4a2", "anger symbol", []string{"anger"}, "6.0"},
-	{"\U0001f1e6\U0001f1f4", "flag: Angola", []string{"angola"}, "6.0"},
-	{"\U0001f620", "angry face", []string{"angry"}, "6.0"},
-	{"\U0001f1e6\U0001f1ee", "flag: Anguilla", []string{"anguilla"}, "6.0"},
-	{"\U0001f627", "anguished face", []string{"anguished"}, "6.1"},
-	{"\U0001f41c", "ant", []string{"ant"}, "6.0"},
-	{"\U0001f1e6\U0001f1f6", "flag: Antarctica", []string{"antarctica"}, "6.0"},
-	{"\U0001f1e6\U0001f1ec", "flag: Antigua & Barbuda", []string{"antigua_barbuda"}, "6.0"},
-	{"\U0001f34e", "red apple", []string{"apple"}, "6.0"},
-	{"\u2652", "Aquarius", []string{"aquarius"}, ""},
-	{"\U0001f1e6\U0001f1f7", "flag: Argentina", []string{"argentina"}, "6.0"},
-	{"\u2648", "Aries", []string{"aries"}, ""},
-	{"\U0001f1e6\U0001f1f2", "flag: Armenia", []string{"armenia"}, "6.0"},
-	{"\u25c0\ufe0f", "reverse button", []string{"arrow_backward"}, ""},
-	{"\u23ec", "fast down button", []string{"arrow_double_down"}, "6.0"},
-	{"\u23eb", "fast up button", []string{"arrow_double_up"}, "6.0"},
-	{"\u2b07\ufe0f", "down arrow", []string{"arrow_down"}, "4.0"},
-	{"\U0001f53d", "downwards button", []string{"arrow_down_small"}, "6.0"},
-	{"\u25b6\ufe0f", "play button", []string{"arrow_forward"}, ""},
-	{"\u2935\ufe0f", "right arrow curving down", []string{"arrow_heading_down"}, ""},
-	{"\u2934\ufe0f", "right arrow curving up", []string{"arrow_heading_up"}, ""},
-	{"\u2b05\ufe0f", "left arrow", []string{"arrow_left"}, "4.0"},
-	{"\u2199\ufe0f", "down-left arrow", []string{"arrow_lower_left"}, ""},
-	{"\u2198\ufe0f", "down-right arrow", []string{"arrow_lower_right"}, ""},
-	{"\u27a1\ufe0f", "right arrow", []string{"arrow_right"}, ""},
-	{"\u21aa\ufe0f", "left arrow curving right", []string{"arrow_right_hook"}, ""},
-	{"\u2b06\ufe0f", "up arrow", []string{"arrow_up"}, "4.0"},
-	{"\u2195\ufe0f", "up-down arrow", []string{"arrow_up_down"}, ""},
-	{"\U0001f53c", "upwards button", []string{"arrow_up_small"}, "6.0"},
-	{"\u2196\ufe0f", "up-left arrow", []string{"arrow_upper_left"}, ""},
-	{"\u2197\ufe0f", "up-right arrow", []string{"arrow_upper_right"}, ""},
-	{"\U0001f503", "clockwise vertical arrows", []string{"arrows_clockwise"}, "6.0"},
-	{"\U0001f504", "counterclockwise arrows button", []string{"arrows_counterclockwise"}, "6.0"},
-	{"\U0001f3a8", "artist palette", []string{"art"}, "6.0"},
-	{"\U0001f69b", "articulated lorry", []string{"articulated_lorry"}, "6.0"},
-	{"\U0001f6f0\ufe0f", "satellite", []string{"artificial_satellite"}, "7.0"},
-	{"\U0001f9d1\u200d\U0001f3a8", "artist", []string{"artist"}, "12.1"},
-	{"\U0001f1e6\U0001f1fc", "flag: Aruba", []string{"aruba"}, "6.0"},
-	{"\U0001f1e6\U0001f1e8", "flag: Ascension Island", []string{"ascension_island"}, "11.0"},
-	{"\U0001f632", "astonished face", []string{"astonished"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f680", "astronaut", []string{"astronaut"}, "12.1"},
-	{"\U0001f45f", "running shoe", []string{"athletic_shoe"}, "6.0"},
-	{"\U0001f3e7", "ATM sign", []string{"atm"}, "6.0"},
-	{"\u269b\ufe0f", "atom symbol", []string{"atom_symbol"}, "4.1"},
-	{"\U0001f1e6\U0001f1fa", "flag: Australia", []string{"australia"}, "6.0"},
-	{"\U0001f1e6\U0001f1f9", "flag: Austria", []string{"austria"}, "6.0"},
-	{"\U0001f6fa", "auto rickshaw", []string{"auto_rickshaw"}, "12.0"},
-	{"\U0001f951", "avocado", []string{"avocado"}, "9.0"},
-	{"\U0001fa93", "axe", []string{"axe"}, "12.0"},
-	{"\U0001f1e6\U0001f1ff", "flag: Azerbaijan", []string{"azerbaijan"}, "6.0"},
-	{"\U0001f171\ufe0f", "B button (blood type)", []string{"b"}, "6.0"},
-	{"\U0001f476", "baby", []string{"baby"}, "6.0"},
-	{"\U0001f37c", "baby bottle", []string{"baby_bottle"}, "6.0"},
-	{"\U0001f424", "baby chick", []string{"baby_chick"}, "6.0"},
-	{"\U0001f6bc", "baby symbol", []string{"baby_symbol"}, "6.0"},
-	{"\U0001f519", "BACK arrow", []string{"back"}, "6.0"},
-	{"\U0001f953", "bacon", []string{"bacon"}, "9.0"},
-	{"\U0001f9a1", "badger", []string{"badger"}, "11.0"},
-	{"\U0001f3f8", "badminton", []string{"badminton"}, "8.0"},
-	{"\U0001f96f", "bagel", []string{"bagel"}, "11.0"},
-	{"\U0001f6c4", "baggage claim", []string{"baggage_claim"}, "6.0"},
-	{"\U0001f956", "baguette bread", []string{"baguette_bread"}, "9.0"},
-	{"\U0001f1e7\U0001f1f8", "flag: Bahamas", []string{"bahamas"}, "6.0"},
-	{"\U0001f1e7\U0001f1ed", "flag: Bahrain", []string{"bahrain"}, "6.0"},
-	{"\u2696\ufe0f", "balance scale", []string{"balance_scale"}, "4.1"},
-	{"\U0001f468\u200d\U0001f9b2", "man: bald", []string{"bald_man"}, "11.0"},
-	{"\U0001f469\u200d\U0001f9b2", "woman: bald", []string{"bald_woman"}, "11.0"},
-	{"\U0001fa70", "ballet shoes", []string{"ballet_shoes"}, "12.0"},
-	{"\U0001f388", "balloon", []string{"balloon"}, "6.0"},
-	{"\U0001f5f3\ufe0f", "ballot box with ballot", []string{"ballot_box"}, "7.0"},
-	{"\u2611\ufe0f", "check box with check", []string{"ballot_box_with_check"}, ""},
-	{"\U0001f38d", "pine decoration", []string{"bamboo"}, "6.0"},
-	{"\U0001f34c", "banana", []string{"banana"}, "6.0"},
-	{"\u203c\ufe0f", "double exclamation mark", []string{"bangbang"}, ""},
-	{"\U0001f1e7\U0001f1e9", "flag: Bangladesh", []string{"bangladesh"}, "6.0"},
-	{"\U0001fa95", "banjo", []string{"banjo"}, "12.0"},
-	{"\U0001f3e6", "bank", []string{"bank"}, "6.0"},
-	{"\U0001f4ca", "bar chart", []string{"bar_chart"}, "6.0"},
-	{"\U0001f1e7\U0001f1e7", "flag: Barbados", []string{"barbados"}, "6.0"},
-	{"\U0001f488", "barber pole", []string{"barber"}, "6.0"},
-	{"\u26be", "baseball", []string{"baseball"}, "5.2"},
-	{"\U0001f9fa", "basket", []string{"basket"}, "11.0"},
-	{"\U0001f3c0", "basketball", []string{"basketball"}, "6.0"},
-	{"\U0001f987", "bat", []string{"bat"}, "9.0"},
-	{"\U0001f6c0", "person taking bath", []string{"bath"}, "6.0"},
-	{"\U0001f6c1", "bathtub", []string{"bathtub"}, "6.0"},
-	{"\U0001f50b", "battery", []string{"battery"}, "6.0"},
-	{"\U0001f3d6\ufe0f", "beach with umbrella", []string{"beach_umbrella"}, "7.0"},
-	{"\U0001f43b", "bear", []string{"bear"}, "6.0"},
-	{"\U0001f9d4", "man: beard", []string{"bearded_person"}, "11.0"},
-	{"\U0001f6cf\ufe0f", "bed", []string{"bed"}, "7.0"},
-	{"\U0001f41d", "honeybee", []string{"bee", "honeybee"}, "6.0"},
-	{"\U0001f37a", "beer mug", []string{"beer"}, "6.0"},
-	{"\U0001f37b", "clinking beer mugs", []string{"beers"}, "6.0"},
-	{"\U0001f530", "Japanese symbol for beginner", []string{"beginner"}, "6.0"},
-	{"\U0001f1e7\U0001f1fe", "flag: Belarus", []string{"belarus"}, "6.0"},
-	{"\U0001f1e7\U0001f1ea", "flag: Belgium", []string{"belgium"}, "6.0"},
-	{"\U0001f1e7\U0001f1ff", "flag: Belize", []string{"belize"}, "6.0"},
-	{"\U0001f514", "bell", []string{"bell"}, "6.0"},
-	{"\U0001f6ce\ufe0f", "bellhop bell", []string{"bellhop_bell"}, "7.0"},
-	{"\U0001f1e7\U0001f1ef", "flag: Benin", []string{"benin"}, "6.0"},
-	{"\U0001f371", "bento box", []string{"bento"}, "6.0"},
-	{"\U0001f1e7\U0001f1f2", "flag: Bermuda", []string{"bermuda"}, "6.0"},
-	{"\U0001f9c3", "beverage box", []string{"beverage_box"}, "12.0"},
-	{"\U0001f1e7\U0001f1f9", "flag: Bhutan", []string{"bhutan"}, "6.0"},
-	{"\U0001f6b4", "person biking", []string{"bicyclist"}, "6.0"},
-	{"\U0001f6b2", "bicycle", []string{"bike"}, "6.0"},
-	{"\U0001f6b4\u200d\u2642\ufe0f", "man biking", []string{"biking_man"}, "11.0"},
-	{"\U0001f6b4\u200d\u2640\ufe0f", "woman biking", []string{"biking_woman"}, "6.0"},
-	{"\U0001f459", "bikini", []string{"bikini"}, "6.0"},
-	{"\U0001f9e2", "billed cap", []string{"billed_cap"}, "11.0"},
-	{"\u2623\ufe0f", "biohazard", []string{"biohazard"}, ""},
-	{"\U0001f426", "bird", []string{"bird"}, "6.0"},
-	{"\U0001f382", "birthday cake", []string{"birthday"}, "6.0"},
-	{"\u26ab", "black circle", []string{"black_circle"}, "4.1"},
-	{"\U0001f3f4", "black flag", []string{"black_flag"}, "7.0"},
-	{"\U0001f5a4", "black heart", []string{"black_heart"}, "9.0"},
-	{"\U0001f0cf", "joker", []string{"black_joker"}, "6.0"},
-	{"\u2b1b", "black large square", []string{"black_large_square"}, "5.1"},
-	{"\u25fe", "black medium-small square", []string{"black_medium_small_square"}, "3.2"},
-	{"\u25fc\ufe0f", "black medium square", []string{"black_medium_square"}, "3.2"},
-	{"\u2712\ufe0f", "black nib", []string{"black_nib"}, ""},
-	{"\u25aa\ufe0f", "black small square", []string{"black_small_square"}, ""},
-	{"\U0001f532", "black square button", []string{"black_square_button"}, "6.0"},
-	{"\U0001f471\u200d\u2642\ufe0f", "man: blond hair", []string{"blond_haired_man"}, "11.0"},
-	{"\U0001f471", "person: blond hair", []string{"blond_haired_person"}, "6.0"},
-	{"\U0001f471\u200d\u2640\ufe0f", "woman: blond hair", []string{"blond_haired_woman", "blonde_woman"}, "6.0"},
-	{"\U0001f33c", "blossom", []string{"blossom"}, "6.0"},
-	{"\U0001f421", "blowfish", []string{"blowfish"}, "6.0"},
-	{"\U0001f4d8", "blue book", []string{"blue_book"}, "6.0"},
-	{"\U0001f699", "sport utility vehicle", []string{"blue_car"}, "6.0"},
-	{"\U0001f499", "blue heart", []string{"blue_heart"}, "6.0"},
-	{"\U0001f7e6", "blue square", []string{"blue_square"}, "12.0"},
-	{"\U0001f60a", "smiling face with smiling eyes", []string{"blush"}, "6.0"},
-	{"\U0001f417", "boar", []string{"boar"}, "6.0"},
-	{"\u26f5", "sailboat", []string{"boat", "sailboat"}, "5.2"},
-	{"\U0001f1e7\U0001f1f4", "flag: Bolivia", []string{"bolivia"}, "6.0"},
-	{"\U0001f4a3", "bomb", []string{"bomb"}, "6.0"},
-	{"\U0001f9b4", "bone", []string{"bone"}, "11.0"},
-	{"\U0001f4d6", "open book", []string{"book", "open_book"}, "6.0"},
-	{"\U0001f516", "bookmark", []string{"bookmark"}, "6.0"},
-	{"\U0001f4d1", "bookmark tabs", []string{"bookmark_tabs"}, "6.0"},
-	{"\U0001f4da", "books", []string{"books"}, "6.0"},
-	{"\U0001f4a5", "collision", []string{"boom", "collision"}, "6.0"},
-	{"\U0001f462", "womanโ€™s boot", []string{"boot"}, "6.0"},
-	{"\U0001f1e7\U0001f1e6", "flag: Bosnia & Herzegovina", []string{"bosnia_herzegovina"}, "6.0"},
-	{"\U0001f1e7\U0001f1fc", "flag: Botswana", []string{"botswana"}, "6.0"},
-	{"\u26f9\ufe0f\u200d\u2642\ufe0f", "man bouncing ball", []string{"bouncing_ball_man", "basketball_man"}, "11.0"},
-	{"\u26f9\ufe0f", "person bouncing ball", []string{"bouncing_ball_person"}, "5.2"},
-	{"\u26f9\ufe0f\u200d\u2640\ufe0f", "woman bouncing ball", []string{"bouncing_ball_woman", "basketball_woman"}, "7.0"},
-	{"\U0001f490", "bouquet", []string{"bouquet"}, "6.0"},
-	{"\U0001f1e7\U0001f1fb", "flag: Bouvet Island", []string{"bouvet_island"}, "11.0"},
-	{"\U0001f647", "person bowing", []string{"bow"}, "6.0"},
-	{"\U0001f3f9", "bow and arrow", []string{"bow_and_arrow"}, "8.0"},
-	{"\U0001f647\u200d\u2642\ufe0f", "man bowing", []string{"bowing_man"}, "11.0"},
-	{"\U0001f647\u200d\u2640\ufe0f", "woman bowing", []string{"bowing_woman"}, "6.0"},
-	{"\U0001f963", "bowl with spoon", []string{"bowl_with_spoon"}, "11.0"},
-	{"\U0001f3b3", "bowling", []string{"bowling"}, "6.0"},
-	{"\U0001f94a", "boxing glove", []string{"boxing_glove"}, "9.0"},
-	{"\U0001f466", "boy", []string{"boy"}, "6.0"},
-	{"\U0001f9e0", "brain", []string{"brain"}, "11.0"},
-	{"\U0001f1e7\U0001f1f7", "flag: Brazil", []string{"brazil"}, "6.0"},
-	{"\U0001f35e", "bread", []string{"bread"}, "6.0"},
-	{"\U0001f931", "breast-feeding", []string{"breast_feeding"}, "11.0"},
-	{"\U0001f9f1", "brick", []string{"bricks"}, "11.0"},
-	{"\U0001f309", "bridge at night", []string{"bridge_at_night"}, "6.0"},
-	{"\U0001f4bc", "briefcase", []string{"briefcase"}, "6.0"},
-	{"\U0001f1ee\U0001f1f4", "flag: British Indian Ocean Territory", []string{"british_indian_ocean_territory"}, "6.0"},
-	{"\U0001f1fb\U0001f1ec", "flag: British Virgin Islands", []string{"british_virgin_islands"}, "6.0"},
-	{"\U0001f966", "broccoli", []string{"broccoli"}, "11.0"},
-	{"\U0001f494", "broken heart", []string{"broken_heart"}, "6.0"},
-	{"\U0001f9f9", "broom", []string{"broom"}, "11.0"},
-	{"\U0001f7e4", "brown circle", []string{"brown_circle"}, "12.0"},
-	{"\U0001f90e", "brown heart", []string{"brown_heart"}, "12.0"},
-	{"\U0001f7eb", "brown square", []string{"brown_square"}, "12.0"},
-	{"\U0001f1e7\U0001f1f3", "flag: Brunei", []string{"brunei"}, "6.0"},
-	{"\U0001f41b", "bug", []string{"bug"}, "6.0"},
-	{"\U0001f3d7\ufe0f", "building construction", []string{"building_construction"}, "7.0"},
-	{"\U0001f4a1", "light bulb", []string{"bulb"}, "6.0"},
-	{"\U0001f1e7\U0001f1ec", "flag: Bulgaria", []string{"bulgaria"}, "6.0"},
-	{"\U0001f685", "bullet train", []string{"bullettrain_front"}, "6.0"},
-	{"\U0001f684", "high-speed train", []string{"bullettrain_side"}, "6.0"},
-	{"\U0001f1e7\U0001f1eb", "flag: Burkina Faso", []string{"burkina_faso"}, "6.0"},
-	{"\U0001f32f", "burrito", []string{"burrito"}, "8.0"},
-	{"\U0001f1e7\U0001f1ee", "flag: Burundi", []string{"burundi"}, "6.0"},
-	{"\U0001f68c", "bus", []string{"bus"}, "6.0"},
-	{"\U0001f574\ufe0f", "person in suit levitating", []string{"business_suit_levitating"}, "7.0"},
-	{"\U0001f68f", "bus stop", []string{"busstop"}, "6.0"},
-	{"\U0001f464", "bust in silhouette", []string{"bust_in_silhouette"}, "6.0"},
-	{"\U0001f465", "busts in silhouette", []string{"busts_in_silhouette"}, "6.0"},
-	{"\U0001f9c8", "butter", []string{"butter"}, "12.0"},
-	{"\U0001f98b", "butterfly", []string{"butterfly"}, "9.0"},
-	{"\U0001f335", "cactus", []string{"cactus"}, "6.0"},
-	{"\U0001f370", "shortcake", []string{"cake"}, "6.0"},
-	{"\U0001f4c6", "tear-off calendar", []string{"calendar"}, "6.0"},
-	{"\U0001f919", "call me hand", []string{"call_me_hand"}, "9.0"},
-	{"\U0001f4f2", "mobile phone with arrow", []string{"calling"}, "6.0"},
-	{"\U0001f1f0\U0001f1ed", "flag: Cambodia", []string{"cambodia"}, "6.0"},
-	{"\U0001f42b", "two-hump camel", []string{"camel"}, "6.0"},
-	{"\U0001f4f7", "camera", []string{"camera"}, "6.0"},
-	{"\U0001f4f8", "camera with flash", []string{"camera_flash"}, "7.0"},
-	{"\U0001f1e8\U0001f1f2", "flag: Cameroon", []string{"cameroon"}, "6.0"},
-	{"\U0001f3d5\ufe0f", "camping", []string{"camping"}, "7.0"},
-	{"\U0001f1e8\U0001f1e6", "flag: Canada", []string{"canada"}, "6.0"},
-	{"\U0001f1ee\U0001f1e8", "flag: Canary Islands", []string{"canary_islands"}, "6.0"},
-	{"\u264b", "Cancer", []string{"cancer"}, ""},
-	{"\U0001f56f\ufe0f", "candle", []string{"candle"}, "7.0"},
-	{"\U0001f36c", "candy", []string{"candy"}, "6.0"},
-	{"\U0001f96b", "canned food", []string{"canned_food"}, "11.0"},
-	{"\U0001f6f6", "canoe", []string{"canoe"}, "9.0"},
-	{"\U0001f1e8\U0001f1fb", "flag: Cape Verde", []string{"cape_verde"}, "6.0"},
-	{"\U0001f520", "input latin uppercase", []string{"capital_abcd"}, "6.0"},
-	{"\u2651", "Capricorn", []string{"capricorn"}, ""},
-	{"\U0001f697", "automobile", []string{"car", "red_car"}, "6.0"},
-	{"\U0001f5c3\ufe0f", "card file box", []string{"card_file_box"}, "7.0"},
-	{"\U0001f4c7", "card index", []string{"card_index"}, "6.0"},
-	{"\U0001f5c2\ufe0f", "card index dividers", []string{"card_index_dividers"}, "7.0"},
-	{"\U0001f1e7\U0001f1f6", "flag: Caribbean Netherlands", []string{"caribbean_netherlands"}, "6.0"},
-	{"\U0001f3a0", "carousel horse", []string{"carousel_horse"}, "6.0"},
-	{"\U0001f955", "carrot", []string{"carrot"}, "9.0"},
-	{"\U0001f938", "person cartwheeling", []string{"cartwheeling"}, "11.0"},
-	{"\U0001f431", "cat face", []string{"cat"}, "6.0"},
-	{"\U0001f408", "cat", []string{"cat2"}, "6.0"},
-	{"\U0001f1f0\U0001f1fe", "flag: Cayman Islands", []string{"cayman_islands"}, "6.0"},
-	{"\U0001f4bf", "optical disk", []string{"cd"}, "6.0"},
-	{"\U0001f1e8\U0001f1eb", "flag: Central African Republic", []string{"central_african_republic"}, "6.0"},
-	{"\U0001f1ea\U0001f1e6", "flag: Ceuta & Melilla", []string{"ceuta_melilla"}, "11.0"},
-	{"\U0001f1f9\U0001f1e9", "flag: Chad", []string{"chad"}, "6.0"},
-	{"\u26d3\ufe0f", "chains", []string{"chains"}, "5.2"},
-	{"\U0001fa91", "chair", []string{"chair"}, "12.0"},
-	{"\U0001f37e", "bottle with popping cork", []string{"champagne"}, "8.0"},
-	{"\U0001f4b9", "chart increasing with yen", []string{"chart"}, "6.0"},
-	{"\U0001f4c9", "chart decreasing", []string{"chart_with_downwards_trend"}, "6.0"},
-	{"\U0001f4c8", "chart increasing", []string{"chart_with_upwards_trend"}, "6.0"},
-	{"\U0001f3c1", "chequered flag", []string{"checkered_flag"}, "6.0"},
-	{"\U0001f9c0", "cheese wedge", []string{"cheese"}, "8.0"},
-	{"\U0001f352", "cherries", []string{"cherries"}, "6.0"},
-	{"\U0001f338", "cherry blossom", []string{"cherry_blossom"}, "6.0"},
-	{"\u265f\ufe0f", "chess pawn", []string{"chess_pawn"}, "11.0"},
-	{"\U0001f330", "chestnut", []string{"chestnut"}, "6.0"},
-	{"\U0001f414", "chicken", []string{"chicken"}, "6.0"},
-	{"\U0001f9d2", "child", []string{"child"}, "11.0"},
-	{"\U0001f6b8", "children crossing", []string{"children_crossing"}, "6.0"},
-	{"\U0001f1e8\U0001f1f1", "flag: Chile", []string{"chile"}, "6.0"},
-	{"\U0001f43f\ufe0f", "chipmunk", []string{"chipmunk"}, "7.0"},
-	{"\U0001f36b", "chocolate bar", []string{"chocolate_bar"}, "6.0"},
-	{"\U0001f962", "chopsticks", []string{"chopsticks"}, "11.0"},
-	{"\U0001f1e8\U0001f1fd", "flag: Christmas Island", []string{"christmas_island"}, "6.0"},
-	{"\U0001f384", "Christmas tree", []string{"christmas_tree"}, "6.0"},
-	{"\u26ea", "church", []string{"church"}, "5.2"},
-	{"\U0001f3a6", "cinema", []string{"cinema"}, "6.0"},
-	{"\U0001f3aa", "circus tent", []string{"circus_tent"}, "6.0"},
-	{"\U0001f307", "sunset", []string{"city_sunrise"}, "6.0"},
-	{"\U0001f306", "cityscape at dusk", []string{"city_sunset"}, "6.0"},
-	{"\U0001f3d9\ufe0f", "cityscape", []string{"cityscape"}, "7.0"},
-	{"\U0001f191", "CL button", []string{"cl"}, "6.0"},
-	{"\U0001f5dc\ufe0f", "clamp", []string{"clamp"}, "7.0"},
-	{"\U0001f44f", "clapping hands", []string{"clap"}, "6.0"},
-	{"\U0001f3ac", "clapper board", []string{"clapper"}, "6.0"},
-	{"\U0001f3db\ufe0f", "classical building", []string{"classical_building"}, "7.0"},
-	{"\U0001f9d7", "person climbing", []string{"climbing"}, "11.0"},
-	{"\U0001f9d7\u200d\u2642\ufe0f", "man climbing", []string{"climbing_man"}, "11.0"},
-	{"\U0001f9d7\u200d\u2640\ufe0f", "woman climbing", []string{"climbing_woman"}, "11.0"},
-	{"\U0001f942", "clinking glasses", []string{"clinking_glasses"}, "9.0"},
-	{"\U0001f4cb", "clipboard", []string{"clipboard"}, "6.0"},
-	{"\U0001f1e8\U0001f1f5", "flag: Clipperton Island", []string{"clipperton_island"}, "11.0"},
-	{"\U0001f550", "one oโ€™clock", []string{"clock1"}, "6.0"},
-	{"\U0001f559", "ten oโ€™clock", []string{"clock10"}, "6.0"},
-	{"\U0001f565", "ten-thirty", []string{"clock1030"}, "6.0"},
-	{"\U0001f55a", "eleven oโ€™clock", []string{"clock11"}, "6.0"},
-	{"\U0001f566", "eleven-thirty", []string{"clock1130"}, "6.0"},
-	{"\U0001f55b", "twelve oโ€™clock", []string{"clock12"}, "6.0"},
-	{"\U0001f567", "twelve-thirty", []string{"clock1230"}, "6.0"},
-	{"\U0001f55c", "one-thirty", []string{"clock130"}, "6.0"},
-	{"\U0001f551", "two oโ€™clock", []string{"clock2"}, "6.0"},
-	{"\U0001f55d", "two-thirty", []string{"clock230"}, "6.0"},
-	{"\U0001f552", "three oโ€™clock", []string{"clock3"}, "6.0"},
-	{"\U0001f55e", "three-thirty", []string{"clock330"}, "6.0"},
-	{"\U0001f553", "four oโ€™clock", []string{"clock4"}, "6.0"},
-	{"\U0001f55f", "four-thirty", []string{"clock430"}, "6.0"},
-	{"\U0001f554", "five oโ€™clock", []string{"clock5"}, "6.0"},
-	{"\U0001f560", "five-thirty", []string{"clock530"}, "6.0"},
-	{"\U0001f555", "six oโ€™clock", []string{"clock6"}, "6.0"},
-	{"\U0001f561", "six-thirty", []string{"clock630"}, "6.0"},
-	{"\U0001f556", "seven oโ€™clock", []string{"clock7"}, "6.0"},
-	{"\U0001f562", "seven-thirty", []string{"clock730"}, "6.0"},
-	{"\U0001f557", "eight oโ€™clock", []string{"clock8"}, "6.0"},
-	{"\U0001f563", "eight-thirty", []string{"clock830"}, "6.0"},
-	{"\U0001f558", "nine oโ€™clock", []string{"clock9"}, "6.0"},
-	{"\U0001f564", "nine-thirty", []string{"clock930"}, "6.0"},
-	{"\U0001f4d5", "closed book", []string{"closed_book"}, "6.0"},
-	{"\U0001f510", "locked with key", []string{"closed_lock_with_key"}, "6.0"},
-	{"\U0001f302", "closed umbrella", []string{"closed_umbrella"}, "6.0"},
-	{"\u2601\ufe0f", "cloud", []string{"cloud"}, ""},
-	{"\U0001f329\ufe0f", "cloud with lightning", []string{"cloud_with_lightning"}, "7.0"},
-	{"\u26c8\ufe0f", "cloud with lightning and rain", []string{"cloud_with_lightning_and_rain"}, "5.2"},
-	{"\U0001f327\ufe0f", "cloud with rain", []string{"cloud_with_rain"}, "7.0"},
-	{"\U0001f328\ufe0f", "cloud with snow", []string{"cloud_with_snow"}, "7.0"},
-	{"\U0001f921", "clown face", []string{"clown_face"}, "9.0"},
-	{"\u2663\ufe0f", "club suit", []string{"clubs"}, ""},
-	{"\U0001f1e8\U0001f1f3", "flag: China", []string{"cn"}, "6.0"},
-	{"\U0001f9e5", "coat", []string{"coat"}, "11.0"},
-	{"\U0001f378", "cocktail glass", []string{"cocktail"}, "6.0"},
-	{"\U0001f965", "coconut", []string{"coconut"}, "11.0"},
-	{"\U0001f1e8\U0001f1e8", "flag: Cocos (Keeling) Islands", []string{"cocos_islands"}, "6.0"},
-	{"\u2615", "hot beverage", []string{"coffee"}, "4.0"},
-	{"\u26b0\ufe0f", "coffin", []string{"coffin"}, "4.1"},
-	{"\U0001f976", "cold face", []string{"cold_face"}, "11.0"},
-	{"\U0001f630", "anxious face with sweat", []string{"cold_sweat"}, "6.0"},
-	{"\U0001f1e8\U0001f1f4", "flag: Colombia", []string{"colombia"}, "6.0"},
-	{"\u2604\ufe0f", "comet", []string{"comet"}, ""},
-	{"\U0001f1f0\U0001f1f2", "flag: Comoros", []string{"comoros"}, "6.0"},
-	{"\U0001f9ed", "compass", []string{"compass"}, "11.0"},
-	{"\U0001f4bb", "laptop", []string{"computer"}, "6.0"},
-	{"\U0001f5b1\ufe0f", "computer mouse", []string{"computer_mouse"}, "7.0"},
-	{"\U0001f38a", "confetti ball", []string{"confetti_ball"}, "6.0"},
-	{"\U0001f616", "confounded face", []string{"confounded"}, "6.0"},
-	{"\U0001f615", "confused face", []string{"confused"}, "6.1"},
-	{"\U0001f1e8\U0001f1ec", "flag: Congo - Brazzaville", []string{"congo_brazzaville"}, "6.0"},
-	{"\U0001f1e8\U0001f1e9", "flag: Congo - Kinshasa", []string{"congo_kinshasa"}, "6.0"},
-	{"\u3297\ufe0f", "Japanese โ€œcongratulationsโ€ button", []string{"congratulations"}, ""},
-	{"\U0001f6a7", "construction", []string{"construction"}, "6.0"},
-	{"\U0001f477", "construction worker", []string{"construction_worker"}, "6.0"},
-	{"\U0001f477\u200d\u2642\ufe0f", "man construction worker", []string{"construction_worker_man"}, "11.0"},
-	{"\U0001f477\u200d\u2640\ufe0f", "woman construction worker", []string{"construction_worker_woman"}, "6.0"},
-	{"\U0001f39b\ufe0f", "control knobs", []string{"control_knobs"}, "7.0"},
-	{"\U0001f3ea", "convenience store", []string{"convenience_store"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f373", "cook", []string{"cook"}, "12.1"},
-	{"\U0001f1e8\U0001f1f0", "flag: Cook Islands", []string{"cook_islands"}, "6.0"},
-	{"\U0001f36a", "cookie", []string{"cookie"}, "6.0"},
-	{"\U0001f192", "COOL button", []string{"cool"}, "6.0"},
-	{"\U0001f33d", "ear of corn", []string{"corn"}, "6.0"},
-	{"\U0001f1e8\U0001f1f7", "flag: Costa Rica", []string{"costa_rica"}, "6.0"},
-	{"\U0001f1e8\U0001f1ee", "flag: Cรดte dโ€™Ivoire", []string{"cote_divoire"}, "6.0"},
-	{"\U0001f6cb\ufe0f", "couch and lamp", []string{"couch_and_lamp"}, "7.0"},
-	{"\U0001f46b", "woman and man holding hands", []string{"couple"}, "6.0"},
-	{"\U0001f491", "couple with heart", []string{"couple_with_heart"}, "6.0"},
-	{"\U0001f468\u200d\u2764\ufe0f\u200d\U0001f468", "couple with heart: man, man", []string{"couple_with_heart_man_man"}, "6.0"},
-	{"\U0001f469\u200d\u2764\ufe0f\u200d\U0001f468", "couple with heart: woman, man", []string{"couple_with_heart_woman_man"}, "11.0"},
-	{"\U0001f469\u200d\u2764\ufe0f\u200d\U0001f469", "couple with heart: woman, woman", []string{"couple_with_heart_woman_woman"}, "6.0"},
-	{"\U0001f48f", "kiss", []string{"couplekiss"}, "6.0"},
-	{"\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468", "kiss: man, man", []string{"couplekiss_man_man"}, "6.0"},
-	{"\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468", "kiss: woman, man", []string{"couplekiss_man_woman"}, "11.0"},
-	{"\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469", "kiss: woman, woman", []string{"couplekiss_woman_woman"}, "6.0"},
-	{"\U0001f42e", "cow face", []string{"cow"}, "6.0"},
-	{"\U0001f404", "cow", []string{"cow2"}, "6.0"},
-	{"\U0001f920", "cowboy hat face", []string{"cowboy_hat_face"}, "9.0"},
-	{"\U0001f980", "crab", []string{"crab"}, "8.0"},
-	{"\U0001f58d\ufe0f", "crayon", []string{"crayon"}, "7.0"},
-	{"\U0001f4b3", "credit card", []string{"credit_card"}, "6.0"},
-	{"\U0001f319", "crescent moon", []string{"crescent_moon"}, "6.0"},
-	{"\U0001f997", "cricket", []string{"cricket"}, "11.0"},
-	{"\U0001f3cf", "cricket game", []string{"cricket_game"}, "8.0"},
-	{"\U0001f1ed\U0001f1f7", "flag: Croatia", []string{"croatia"}, "6.0"},
-	{"\U0001f40a", "crocodile", []string{"crocodile"}, "6.0"},
-	{"\U0001f950", "croissant", []string{"croissant"}, "9.0"},
-	{"\U0001f91e", "crossed fingers", []string{"crossed_fingers"}, "9.0"},
-	{"\U0001f38c", "crossed flags", []string{"crossed_flags"}, "6.0"},
-	{"\u2694\ufe0f", "crossed swords", []string{"crossed_swords"}, "4.1"},
-	{"\U0001f451", "crown", []string{"crown"}, "6.0"},
-	{"\U0001f622", "crying face", []string{"cry"}, "6.0"},
-	{"\U0001f63f", "crying cat", []string{"crying_cat_face"}, "6.0"},
-	{"\U0001f52e", "crystal ball", []string{"crystal_ball"}, "6.0"},
-	{"\U0001f1e8\U0001f1fa", "flag: Cuba", []string{"cuba"}, "6.0"},
-	{"\U0001f952", "cucumber", []string{"cucumber"}, "9.0"},
-	{"\U0001f964", "cup with straw", []string{"cup_with_straw"}, "11.0"},
-	{"\U0001f9c1", "cupcake", []string{"cupcake"}, "11.0"},
-	{"\U0001f498", "heart with arrow", []string{"cupid"}, "6.0"},
-	{"\U0001f1e8\U0001f1fc", "flag: Curaรงao", []string{"curacao"}, "6.0"},
-	{"\U0001f94c", "curling stone", []string{"curling_stone"}, "11.0"},
-	{"\U0001f468\u200d\U0001f9b1", "man: curly hair", []string{"curly_haired_man"}, "11.0"},
-	{"\U0001f469\u200d\U0001f9b1", "woman: curly hair", []string{"curly_haired_woman"}, "11.0"},
-	{"\u27b0", "curly loop", []string{"curly_loop"}, "6.0"},
-	{"\U0001f4b1", "currency exchange", []string{"currency_exchange"}, "6.0"},
-	{"\U0001f35b", "curry rice", []string{"curry"}, "6.0"},
-	{"\U0001f92c", "face with symbols on mouth", []string{"cursing_face"}, "11.0"},
-	{"\U0001f36e", "custard", []string{"custard"}, "6.0"},
-	{"\U0001f6c3", "customs", []string{"customs"}, "6.0"},
-	{"\U0001f969", "cut of meat", []string{"cut_of_meat"}, "11.0"},
-	{"\U0001f300", "cyclone", []string{"cyclone"}, "6.0"},
-	{"\U0001f1e8\U0001f1fe", "flag: Cyprus", []string{"cyprus"}, "6.0"},
-	{"\U0001f1e8\U0001f1ff", "flag: Czechia", []string{"czech_republic"}, "6.0"},
-	{"\U0001f5e1\ufe0f", "dagger", []string{"dagger"}, "7.0"},
-	{"\U0001f46f", "people with bunny ears", []string{"dancers"}, "6.0"},
-	{"\U0001f46f\u200d\u2642\ufe0f", "men with bunny ears", []string{"dancing_men"}, "6.0"},
-	{"\U0001f46f\u200d\u2640\ufe0f", "women with bunny ears", []string{"dancing_women"}, "11.0"},
-	{"\U0001f361", "dango", []string{"dango"}, "6.0"},
-	{"\U0001f576\ufe0f", "sunglasses", []string{"dark_sunglasses"}, "7.0"},
-	{"\U0001f3af", "direct hit", []string{"dart"}, "6.0"},
-	{"\U0001f4a8", "dashing away", []string{"dash"}, "6.0"},
-	{"\U0001f4c5", "calendar", []string{"date"}, "6.0"},
-	{"\U0001f1e9\U0001f1ea", "flag: Germany", []string{"de"}, "6.0"},
-	{"\U0001f9cf\u200d\u2642\ufe0f", "deaf man", []string{"deaf_man"}, "12.0"},
-	{"\U0001f9cf", "deaf person", []string{"deaf_person"}, "12.0"},
-	{"\U0001f9cf\u200d\u2640\ufe0f", "deaf woman", []string{"deaf_woman"}, "12.0"},
-	{"\U0001f333", "deciduous tree", []string{"deciduous_tree"}, "6.0"},
-	{"\U0001f98c", "deer", []string{"deer"}, "9.0"},
-	{"\U0001f1e9\U0001f1f0", "flag: Denmark", []string{"denmark"}, "6.0"},
-	{"\U0001f3ec", "department store", []string{"department_store"}, "6.0"},
-	{"\U0001f3da\ufe0f", "derelict house", []string{"derelict_house"}, "7.0"},
-	{"\U0001f3dc\ufe0f", "desert", []string{"desert"}, "7.0"},
-	{"\U0001f3dd\ufe0f", "desert island", []string{"desert_island"}, "7.0"},
-	{"\U0001f5a5\ufe0f", "desktop computer", []string{"desktop_computer"}, "7.0"},
-	{"\U0001f575\ufe0f", "detective", []string{"detective"}, "7.0"},
-	{"\U0001f4a0", "diamond with a dot", []string{"diamond_shape_with_a_dot_inside"}, "6.0"},
-	{"\u2666\ufe0f", "diamond suit", []string{"diamonds"}, ""},
-	{"\U0001f1e9\U0001f1ec", "flag: Diego Garcia", []string{"diego_garcia"}, "11.0"},
-	{"\U0001f61e", "disappointed face", []string{"disappointed"}, "6.0"},
-	{"\U0001f625", "sad but relieved face", []string{"disappointed_relieved"}, "6.0"},
-	{"\U0001f93f", "diving mask", []string{"diving_mask"}, "12.0"},
-	{"\U0001fa94", "diya lamp", []string{"diya_lamp"}, "12.0"},
-	{"\U0001f4ab", "dizzy", []string{"dizzy"}, "6.0"},
-	{"\U0001f635", "dizzy face", []string{"dizzy_face"}, "6.0"},
-	{"\U0001f1e9\U0001f1ef", "flag: Djibouti", []string{"djibouti"}, "6.0"},
-	{"\U0001f9ec", "dna", []string{"dna"}, "11.0"},
-	{"\U0001f6af", "no littering", []string{"do_not_litter"}, "6.0"},
-	{"\U0001f436", "dog face", []string{"dog"}, "6.0"},
-	{"\U0001f415", "dog", []string{"dog2"}, "6.0"},
-	{"\U0001f4b5", "dollar banknote", []string{"dollar"}, "6.0"},
-	{"\U0001f38e", "Japanese dolls", []string{"dolls"}, "6.0"},
-	{"\U0001f42c", "dolphin", []string{"dolphin", "flipper"}, "6.0"},
-	{"\U0001f1e9\U0001f1f2", "flag: Dominica", []string{"dominica"}, "6.0"},
-	{"\U0001f1e9\U0001f1f4", "flag: Dominican Republic", []string{"dominican_republic"}, "6.0"},
-	{"\U0001f6aa", "door", []string{"door"}, "6.0"},
-	{"\U0001f369", "doughnut", []string{"doughnut"}, "6.0"},
-	{"\U0001f54a\ufe0f", "dove", []string{"dove"}, "7.0"},
-	{"\U0001f409", "dragon", []string{"dragon"}, "6.0"},
-	{"\U0001f432", "dragon face", []string{"dragon_face"}, "6.0"},
-	{"\U0001f457", "dress", []string{"dress"}, "6.0"},
-	{"\U0001f42a", "camel", []string{"dromedary_camel"}, "6.0"},
-	{"\U0001f924", "drooling face", []string{"drooling_face"}, "9.0"},
-	{"\U0001fa78", "drop of blood", []string{"drop_of_blood"}, "12.0"},
-	{"\U0001f4a7", "droplet", []string{"droplet"}, "6.0"},
-	{"\U0001f941", "drum", []string{"drum"}, ""},
-	{"\U0001f986", "duck", []string{"duck"}, "9.0"},
-	{"\U0001f95f", "dumpling", []string{"dumpling"}, "11.0"},
-	{"\U0001f4c0", "dvd", []string{"dvd"}, "6.0"},
-	{"\U0001f4e7", "e-mail", []string{"e-mail"}, "6.0"},
-	{"\U0001f985", "eagle", []string{"eagle"}, "9.0"},
-	{"\U0001f442", "ear", []string{"ear"}, "6.0"},
-	{"\U0001f33e", "sheaf of rice", []string{"ear_of_rice"}, "6.0"},
-	{"\U0001f9bb", "ear with hearing aid", []string{"ear_with_hearing_aid"}, "12.0"},
-	{"\U0001f30d", "globe showing Europe-Africa", []string{"earth_africa"}, "6.0"},
-	{"\U0001f30e", "globe showing Americas", []string{"earth_americas"}, "6.0"},
-	{"\U0001f30f", "globe showing Asia-Australia", []string{"earth_asia"}, "6.0"},
-	{"\U0001f1ea\U0001f1e8", "flag: Ecuador", []string{"ecuador"}, "6.0"},
-	{"\U0001f95a", "egg", []string{"egg"}, "9.0"},
-	{"\U0001f346", "eggplant", []string{"eggplant"}, "6.0"},
-	{"\U0001f1ea\U0001f1ec", "flag: Egypt", []string{"egypt"}, "6.0"},
-	{"\u2734\ufe0f", "eight-pointed star", []string{"eight_pointed_black_star"}, ""},
-	{"\u2733\ufe0f", "eight-spoked asterisk", []string{"eight_spoked_asterisk"}, ""},
-	{"\u23cf\ufe0f", "eject button", []string{"eject_button"}, "11.0"},
-	{"\U0001f1f8\U0001f1fb", "flag: El Salvador", []string{"el_salvador"}, "6.0"},
-	{"\U0001f50c", "electric plug", []string{"electric_plug"}, "6.0"},
-	{"\U0001f418", "elephant", []string{"elephant"}, "6.0"},
-	{"\U0001f9dd", "elf", []string{"elf"}, "11.0"},
-	{"\U0001f9dd\u200d\u2642\ufe0f", "man elf", []string{"elf_man"}, "11.0"},
-	{"\U0001f9dd\u200d\u2640\ufe0f", "woman elf", []string{"elf_woman"}, "11.0"},
-	{"\u2709\ufe0f", "envelope", []string{"email", "envelope"}, ""},
-	{"\U0001f51a", "END arrow", []string{"end"}, "6.0"},
-	{"\U0001f3f4\U000e0067\U000e0062\U000e0065\U000e006e\U000e0067\U000e007f", "flag: England", []string{"england"}, "11.0"},
-	{"\U0001f4e9", "envelope with arrow", []string{"envelope_with_arrow"}, "6.0"},
-	{"\U0001f1ec\U0001f1f6", "flag: Equatorial Guinea", []string{"equatorial_guinea"}, "6.0"},
-	{"\U0001f1ea\U0001f1f7", "flag: Eritrea", []string{"eritrea"}, "6.0"},
-	{"\U0001f1ea\U0001f1f8", "flag: Spain", []string{"es"}, "6.0"},
-	{"\U0001f1ea\U0001f1ea", "flag: Estonia", []string{"estonia"}, "6.0"},
-	{"\U0001f1ea\U0001f1f9", "flag: Ethiopia", []string{"ethiopia"}, "6.0"},
-	{"\U0001f1ea\U0001f1fa", "flag: European Union", []string{"eu", "european_union"}, "6.0"},
-	{"\U0001f4b6", "euro banknote", []string{"euro"}, "6.0"},
-	{"\U0001f3f0", "castle", []string{"european_castle"}, "6.0"},
-	{"\U0001f3e4", "post office", []string{"european_post_office"}, "6.0"},
-	{"\U0001f332", "evergreen tree", []string{"evergreen_tree"}, "6.0"},
-	{"\u2757", "exclamation mark", []string{"exclamation", "heavy_exclamation_mark"}, "5.2"},
-	{"\U0001f92f", "exploding head", []string{"exploding_head"}, "11.0"},
-	{"\U0001f611", "expressionless face", []string{"expressionless"}, "6.1"},
-	{"\U0001f441\ufe0f", "eye", []string{"eye"}, "7.0"},
-	{"\U0001f441\ufe0f\u200d\U0001f5e8\ufe0f", "eye in speech bubble", []string{"eye_speech_bubble"}, "11.0"},
-	{"\U0001f453", "glasses", []string{"eyeglasses"}, "6.0"},
-	{"\U0001f440", "eyes", []string{"eyes"}, "6.0"},
-	{"\U0001f915", "face with head-bandage", []string{"face_with_head_bandage"}, "8.0"},
-	{"\U0001f912", "face with thermometer", []string{"face_with_thermometer"}, "8.0"},
-	{"\U0001f926", "person facepalming", []string{"facepalm"}, "11.0"},
-	{"\U0001f3ed", "factory", []string{"factory"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f3ed", "factory worker", []string{"factory_worker"}, "12.1"},
-	{"\U0001f9da", "fairy", []string{"fairy"}, "11.0"},
-	{"\U0001f9da\u200d\u2642\ufe0f", "man fairy", []string{"fairy_man"}, "11.0"},
-	{"\U0001f9da\u200d\u2640\ufe0f", "woman fairy", []string{"fairy_woman"}, "11.0"},
-	{"\U0001f9c6", "falafel", []string{"falafel"}, "12.0"},
-	{"\U0001f1eb\U0001f1f0", "flag: Falkland Islands", []string{"falkland_islands"}, "6.0"},
-	{"\U0001f342", "fallen leaf", []string{"fallen_leaf"}, "6.0"},
-	{"\U0001f46a", "family", []string{"family"}, "6.0"},
-	{"\U0001f468\u200d\U0001f466", "family: man, boy", []string{"family_man_boy"}, "6.0"},
-	{"\U0001f468\u200d\U0001f466\u200d\U0001f466", "family: man, boy, boy", []string{"family_man_boy_boy"}, "6.0"},
-	{"\U0001f468\u200d\U0001f467", "family: man, girl", []string{"family_man_girl"}, "6.0"},
-	{"\U0001f468\u200d\U0001f467\u200d\U0001f466", "family: man, girl, boy", []string{"family_man_girl_boy"}, "6.0"},
-	{"\U0001f468\u200d\U0001f467\u200d\U0001f467", "family: man, girl, girl", []string{"family_man_girl_girl"}, "6.0"},
-	{"\U0001f468\u200d\U0001f468\u200d\U0001f466", "family: man, man, boy", []string{"family_man_man_boy"}, "6.0"},
-	{"\U0001f468\u200d\U0001f468\u200d\U0001f466\u200d\U0001f466", "family: man, man, boy, boy", []string{"family_man_man_boy_boy"}, "6.0"},
-	{"\U0001f468\u200d\U0001f468\u200d\U0001f467", "family: man, man, girl", []string{"family_man_man_girl"}, "6.0"},
-	{"\U0001f468\u200d\U0001f468\u200d\U0001f467\u200d\U0001f466", "family: man, man, girl, boy", []string{"family_man_man_girl_boy"}, "6.0"},
-	{"\U0001f468\u200d\U0001f468\u200d\U0001f467\u200d\U0001f467", "family: man, man, girl, girl", []string{"family_man_man_girl_girl"}, "6.0"},
-	{"\U0001f468\u200d\U0001f469\u200d\U0001f466", "family: man, woman, boy", []string{"family_man_woman_boy"}, "11.0"},
-	{"\U0001f468\u200d\U0001f469\u200d\U0001f466\u200d\U0001f466", "family: man, woman, boy, boy", []string{"family_man_woman_boy_boy"}, "6.0"},
-	{"\U0001f468\u200d\U0001f469\u200d\U0001f467", "family: man, woman, girl", []string{"family_man_woman_girl"}, "6.0"},
-	{"\U0001f468\u200d\U0001f469\u200d\U0001f467\u200d\U0001f466", "family: man, woman, girl, boy", []string{"family_man_woman_girl_boy"}, "6.0"},
-	{"\U0001f468\u200d\U0001f469\u200d\U0001f467\u200d\U0001f467", "family: man, woman, girl, girl", []string{"family_man_woman_girl_girl"}, "6.0"},
-	{"\U0001f469\u200d\U0001f466", "family: woman, boy", []string{"family_woman_boy"}, "6.0"},
-	{"\U0001f469\u200d\U0001f466\u200d\U0001f466", "family: woman, boy, boy", []string{"family_woman_boy_boy"}, "6.0"},
-	{"\U0001f469\u200d\U0001f467", "family: woman, girl", []string{"family_woman_girl"}, "6.0"},
-	{"\U0001f469\u200d\U0001f467\u200d\U0001f466", "family: woman, girl, boy", []string{"family_woman_girl_boy"}, "6.0"},
-	{"\U0001f469\u200d\U0001f467\u200d\U0001f467", "family: woman, girl, girl", []string{"family_woman_girl_girl"}, "6.0"},
-	{"\U0001f469\u200d\U0001f469\u200d\U0001f466", "family: woman, woman, boy", []string{"family_woman_woman_boy"}, "6.0"},
-	{"\U0001f469\u200d\U0001f469\u200d\U0001f466\u200d\U0001f466", "family: woman, woman, boy, boy", []string{"family_woman_woman_boy_boy"}, "6.0"},
-	{"\U0001f469\u200d\U0001f469\u200d\U0001f467", "family: woman, woman, girl", []string{"family_woman_woman_girl"}, "6.0"},
-	{"\U0001f469\u200d\U0001f469\u200d\U0001f467\u200d\U0001f466", "family: woman, woman, girl, boy", []string{"family_woman_woman_girl_boy"}, "6.0"},
-	{"\U0001f469\u200d\U0001f469\u200d\U0001f467\u200d\U0001f467", "family: woman, woman, girl, girl", []string{"family_woman_woman_girl_girl"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f33e", "farmer", []string{"farmer"}, "12.1"},
-	{"\U0001f1eb\U0001f1f4", "flag: Faroe Islands", []string{"faroe_islands"}, "6.0"},
-	{"\u23e9", "fast-forward button", []string{"fast_forward"}, "6.0"},
-	{"\U0001f4e0", "fax machine", []string{"fax"}, "6.0"},
-	{"\U0001f628", "fearful face", []string{"fearful"}, "6.0"},
-	{"\U0001f43e", "paw prints", []string{"feet", "paw_prints"}, "6.0"},
-	{"\U0001f575\ufe0f\u200d\u2640\ufe0f", "woman detective", []string{"female_detective"}, "6.0"},
-	{"\u2640\ufe0f", "female sign", []string{"female_sign"}, "11.0"},
-	{"\U0001f3a1", "ferris wheel", []string{"ferris_wheel"}, "6.0"},
-	{"\u26f4\ufe0f", "ferry", []string{"ferry"}, "5.2"},
-	{"\U0001f3d1", "field hockey", []string{"field_hockey"}, "8.0"},
-	{"\U0001f1eb\U0001f1ef", "flag: Fiji", []string{"fiji"}, "6.0"},
-	{"\U0001f5c4\ufe0f", "file cabinet", []string{"file_cabinet"}, "7.0"},
-	{"\U0001f4c1", "file folder", []string{"file_folder"}, "6.0"},
-	{"\U0001f4fd\ufe0f", "film projector", []string{"film_projector"}, "7.0"},
-	{"\U0001f39e\ufe0f", "film frames", []string{"film_strip"}, "7.0"},
-	{"\U0001f1eb\U0001f1ee", "flag: Finland", []string{"finland"}, "6.0"},
-	{"\U0001f525", "fire", []string{"fire"}, "6.0"},
-	{"\U0001f692", "fire engine", []string{"fire_engine"}, "6.0"},
-	{"\U0001f9ef", "fire extinguisher", []string{"fire_extinguisher"}, "11.0"},
-	{"\U0001f9e8", "firecracker", []string{"firecracker"}, "11.0"},
-	{"\U0001f9d1\u200d\U0001f692", "firefighter", []string{"firefighter"}, "12.1"},
-	{"\U0001f386", "fireworks", []string{"fireworks"}, "6.0"},
-	{"\U0001f313", "first quarter moon", []string{"first_quarter_moon"}, "6.0"},
-	{"\U0001f31b", "first quarter moon face", []string{"first_quarter_moon_with_face"}, "6.0"},
-	{"\U0001f41f", "fish", []string{"fish"}, "6.0"},
-	{"\U0001f365", "fish cake with swirl", []string{"fish_cake"}, "6.0"},
-	{"\U0001f3a3", "fishing pole", []string{"fishing_pole_and_fish"}, "6.0"},
-	{"\U0001f91b", "left-facing fist", []string{"fist_left"}, "9.0"},
-	{"\U0001f44a", "oncoming fist", []string{"fist_oncoming", "facepunch", "punch"}, "6.0"},
-	{"\u270a", "raised fist", []string{"fist_raised", "fist"}, "6.0"},
-	{"\U0001f91c", "right-facing fist", []string{"fist_right"}, "9.0"},
-	{"\U0001f38f", "carp streamer", []string{"flags"}, "6.0"},
-	{"\U0001f9a9", "flamingo", []string{"flamingo"}, "12.0"},
-	{"\U0001f526", "flashlight", []string{"flashlight"}, "6.0"},
-	{"\U0001f97f", "flat shoe", []string{"flat_shoe"}, "11.0"},
-	{"\u269c\ufe0f", "fleur-de-lis", []string{"fleur_de_lis"}, "4.1"},
-	{"\U0001f6ec", "airplane arrival", []string{"flight_arrival"}, "7.0"},
-	{"\U0001f6eb", "airplane departure", []string{"flight_departure"}, "7.0"},
-	{"\U0001f4be", "floppy disk", []string{"floppy_disk"}, "6.0"},
-	{"\U0001f3b4", "flower playing cards", []string{"flower_playing_cards"}, "6.0"},
-	{"\U0001f633", "flushed face", []string{"flushed"}, "6.0"},
-	{"\U0001f94f", "flying disc", []string{"flying_disc"}, "11.0"},
-	{"\U0001f6f8", "flying saucer", []string{"flying_saucer"}, "11.0"},
-	{"\U0001f32b\ufe0f", "fog", []string{"fog"}, "7.0"},
-	{"\U0001f301", "foggy", []string{"foggy"}, "6.0"},
-	{"\U0001f9b6", "foot", []string{"foot"}, "11.0"},
-	{"\U0001f3c8", "american football", []string{"football"}, "6.0"},
-	{"\U0001f463", "footprints", []string{"footprints"}, "6.0"},
-	{"\U0001f374", "fork and knife", []string{"fork_and_knife"}, "6.0"},
-	{"\U0001f960", "fortune cookie", []string{"fortune_cookie"}, "11.0"},
-	{"\u26f2", "fountain", []string{"fountain"}, "5.2"},
-	{"\U0001f58b\ufe0f", "fountain pen", []string{"fountain_pen"}, "7.0"},
-	{"\U0001f340", "four leaf clover", []string{"four_leaf_clover"}, "6.0"},
-	{"\U0001f98a", "fox", []string{"fox_face"}, "9.0"},
-	{"\U0001f1eb\U0001f1f7", "flag: France", []string{"fr"}, "6.0"},
-	{"\U0001f5bc\ufe0f", "framed picture", []string{"framed_picture"}, "7.0"},
-	{"\U0001f193", "FREE button", []string{"free"}, "6.0"},
-	{"\U0001f1ec\U0001f1eb", "flag: French Guiana", []string{"french_guiana"}, "6.0"},
-	{"\U0001f1f5\U0001f1eb", "flag: French Polynesia", []string{"french_polynesia"}, "6.0"},
-	{"\U0001f1f9\U0001f1eb", "flag: French Southern Territories", []string{"french_southern_territories"}, "6.0"},
-	{"\U0001f373", "cooking", []string{"fried_egg"}, "6.0"},
-	{"\U0001f364", "fried shrimp", []string{"fried_shrimp"}, "6.0"},
-	{"\U0001f35f", "french fries", []string{"fries"}, "6.0"},
-	{"\U0001f438", "frog", []string{"frog"}, "6.0"},
-	{"\U0001f626", "frowning face with open mouth", []string{"frowning"}, "6.1"},
-	{"\u2639\ufe0f", "frowning face", []string{"frowning_face"}, ""},
-	{"\U0001f64d\u200d\u2642\ufe0f", "man frowning", []string{"frowning_man"}, "6.0"},
-	{"\U0001f64d", "person frowning", []string{"frowning_person"}, "6.0"},
-	{"\U0001f64d\u200d\u2640\ufe0f", "woman frowning", []string{"frowning_woman"}, "11.0"},
-	{"\u26fd", "fuel pump", []string{"fuelpump"}, "5.2"},
-	{"\U0001f315", "full moon", []string{"full_moon"}, "6.0"},
-	{"\U0001f31d", "full moon face", []string{"full_moon_with_face"}, "6.0"},
-	{"\u26b1\ufe0f", "funeral urn", []string{"funeral_urn"}, "4.1"},
-	{"\U0001f1ec\U0001f1e6", "flag: Gabon", []string{"gabon"}, "6.0"},
-	{"\U0001f1ec\U0001f1f2", "flag: Gambia", []string{"gambia"}, "6.0"},
-	{"\U0001f3b2", "game die", []string{"game_die"}, "6.0"},
-	{"\U0001f9c4", "garlic", []string{"garlic"}, "12.0"},
-	{"\U0001f1ec\U0001f1e7", "flag: United Kingdom", []string{"gb", "uk"}, "6.0"},
-	{"\u2699\ufe0f", "gear", []string{"gear"}, "4.1"},
-	{"\U0001f48e", "gem stone", []string{"gem"}, "6.0"},
-	{"\u264a", "Gemini", []string{"gemini"}, ""},
-	{"\U0001f9de", "genie", []string{"genie"}, "11.0"},
-	{"\U0001f9de\u200d\u2642\ufe0f", "man genie", []string{"genie_man"}, "11.0"},
-	{"\U0001f9de\u200d\u2640\ufe0f", "woman genie", []string{"genie_woman"}, "11.0"},
-	{"\U0001f1ec\U0001f1ea", "flag: Georgia", []string{"georgia"}, "6.0"},
-	{"\U0001f1ec\U0001f1ed", "flag: Ghana", []string{"ghana"}, "6.0"},
-	{"\U0001f47b", "ghost", []string{"ghost"}, "6.0"},
-	{"\U0001f1ec\U0001f1ee", "flag: Gibraltar", []string{"gibraltar"}, "6.0"},
-	{"\U0001f381", "wrapped gift", []string{"gift"}, "6.0"},
-	{"\U0001f49d", "heart with ribbon", []string{"gift_heart"}, "6.0"},
-	{"\U0001f992", "giraffe", []string{"giraffe"}, "11.0"},
-	{"\U0001f467", "girl", []string{"girl"}, "6.0"},
-	{"\U0001f310", "globe with meridians", []string{"globe_with_meridians"}, "6.0"},
-	{"\U0001f9e4", "gloves", []string{"gloves"}, "11.0"},
-	{"\U0001f945", "goal net", []string{"goal_net"}, "9.0"},
-	{"\U0001f410", "goat", []string{"goat"}, "6.0"},
-	{"\U0001f97d", "goggles", []string{"goggles"}, "11.0"},
-	{"\u26f3", "flag in hole", []string{"golf"}, "5.2"},
-	{"\U0001f3cc\ufe0f", "person golfing", []string{"golfing"}, "7.0"},
-	{"\U0001f3cc\ufe0f\u200d\u2642\ufe0f", "man golfing", []string{"golfing_man"}, "11.0"},
-	{"\U0001f3cc\ufe0f\u200d\u2640\ufe0f", "woman golfing", []string{"golfing_woman"}, ""},
-	{"\U0001f98d", "gorilla", []string{"gorilla"}, "9.0"},
-	{"\U0001f347", "grapes", []string{"grapes"}, "6.0"},
-	{"\U0001f1ec\U0001f1f7", "flag: Greece", []string{"greece"}, "6.0"},
-	{"\U0001f34f", "green apple", []string{"green_apple"}, "6.0"},
-	{"\U0001f4d7", "green book", []string{"green_book"}, "6.0"},
-	{"\U0001f7e2", "green circle", []string{"green_circle"}, "12.0"},
-	{"\U0001f49a", "green heart", []string{"green_heart"}, "6.0"},
-	{"\U0001f957", "green salad", []string{"green_salad"}, "9.0"},
-	{"\U0001f7e9", "green square", []string{"green_square"}, "12.0"},
-	{"\U0001f1ec\U0001f1f1", "flag: Greenland", []string{"greenland"}, "6.0"},
-	{"\U0001f1ec\U0001f1e9", "flag: Grenada", []string{"grenada"}, "6.0"},
-	{"\u2755", "white exclamation mark", []string{"grey_exclamation"}, "6.0"},
-	{"\u2754", "white question mark", []string{"grey_question"}, "6.0"},
-	{"\U0001f62c", "grimacing face", []string{"grimacing"}, "6.1"},
-	{"\U0001f601", "beaming face with smiling eyes", []string{"grin"}, "6.0"},
-	{"\U0001f600", "grinning face", []string{"grinning"}, "6.1"},
-	{"\U0001f1ec\U0001f1f5", "flag: Guadeloupe", []string{"guadeloupe"}, "6.0"},
-	{"\U0001f1ec\U0001f1fa", "flag: Guam", []string{"guam"}, "6.0"},
-	{"\U0001f482", "guard", []string{"guard"}, "6.0"},
-	{"\U0001f482\u200d\u2642\ufe0f", "man guard", []string{"guardsman"}, "11.0"},
-	{"\U0001f482\u200d\u2640\ufe0f", "woman guard", []string{"guardswoman"}, "6.0"},
-	{"\U0001f1ec\U0001f1f9", "flag: Guatemala", []string{"guatemala"}, "6.0"},
-	{"\U0001f1ec\U0001f1ec", "flag: Guernsey", []string{"guernsey"}, "6.0"},
-	{"\U0001f9ae", "guide dog", []string{"guide_dog"}, "12.0"},
-	{"\U0001f1ec\U0001f1f3", "flag: Guinea", []string{"guinea"}, "6.0"},
-	{"\U0001f1ec\U0001f1fc", "flag: Guinea-Bissau", []string{"guinea_bissau"}, "6.0"},
-	{"\U0001f3b8", "guitar", []string{"guitar"}, "6.0"},
-	{"\U0001f52b", "pistol", []string{"gun"}, "6.0"},
-	{"\U0001f1ec\U0001f1fe", "flag: Guyana", []string{"guyana"}, "6.0"},
-	{"\U0001f487", "person getting haircut", []string{"haircut"}, "6.0"},
-	{"\U0001f487\u200d\u2642\ufe0f", "man getting haircut", []string{"haircut_man"}, "6.0"},
-	{"\U0001f487\u200d\u2640\ufe0f", "woman getting haircut", []string{"haircut_woman"}, "11.0"},
-	{"\U0001f1ed\U0001f1f9", "flag: Haiti", []string{"haiti"}, "6.0"},
-	{"\U0001f354", "hamburger", []string{"hamburger"}, "6.0"},
-	{"\U0001f528", "hammer", []string{"hammer"}, "6.0"},
-	{"\u2692\ufe0f", "hammer and pick", []string{"hammer_and_pick"}, "4.1"},
-	{"\U0001f6e0\ufe0f", "hammer and wrench", []string{"hammer_and_wrench"}, "7.0"},
-	{"\U0001f439", "hamster", []string{"hamster"}, "6.0"},
-	{"\u270b", "raised hand", []string{"hand", "raised_hand"}, "6.0"},
-	{"\U0001f92d", "face with hand over mouth", []string{"hand_over_mouth"}, "11.0"},
-	{"\U0001f45c", "handbag", []string{"handbag"}, "6.0"},
-	{"\U0001f93e", "person playing handball", []string{"handball_person"}, "11.0"},
-	{"\U0001f91d", "handshake", []string{"handshake"}, "9.0"},
-	{"\U0001f4a9", "pile of poo", []string{"hankey", "poop", "shit"}, "6.0"},
-	{"\U0001f425", "front-facing baby chick", []string{"hatched_chick"}, "6.0"},
-	{"\U0001f423", "hatching chick", []string{"hatching_chick"}, "6.0"},
-	{"\U0001f3a7", "headphone", []string{"headphones"}, "6.0"},
-	{"\U0001f9d1\u200d\u2695\ufe0f", "health worker", []string{"health_worker"}, "12.1"},
-	{"\U0001f649", "hear-no-evil monkey", []string{"hear_no_evil"}, "6.0"},
-	{"\U0001f1ed\U0001f1f2", "flag: Heard & McDonald Islands", []string{"heard_mcdonald_islands"}, "11.0"},
-	{"\u2764\ufe0f", "red heart", []string{"heart"}, ""},
-	{"\U0001f49f", "heart decoration", []string{"heart_decoration"}, "6.0"},
-	{"\U0001f60d", "smiling face with heart-eyes", []string{"heart_eyes"}, "6.0"},
-	{"\U0001f63b", "smiling cat with heart-eyes", []string{"heart_eyes_cat"}, "6.0"},
-	{"\U0001f493", "beating heart", []string{"heartbeat"}, "6.0"},
-	{"\U0001f497", "growing heart", []string{"heartpulse"}, "6.0"},
-	{"\u2665\ufe0f", "heart suit", []string{"hearts"}, ""},
-	{"\u2714\ufe0f", "check mark", []string{"heavy_check_mark"}, ""},
-	{"\u2797", "divide", []string{"heavy_division_sign"}, "6.0"},
-	{"\U0001f4b2", "heavy dollar sign", []string{"heavy_dollar_sign"}, "6.0"},
-	{"\u2763\ufe0f", "heart exclamation", []string{"heavy_heart_exclamation"}, ""},
-	{"\u2796", "minus", []string{"heavy_minus_sign"}, "6.0"},
-	{"\u2716\ufe0f", "multiply", []string{"heavy_multiplication_x"}, ""},
-	{"\u2795", "plus", []string{"heavy_plus_sign"}, "6.0"},
-	{"\U0001f994", "hedgehog", []string{"hedgehog"}, "11.0"},
-	{"\U0001f681", "helicopter", []string{"helicopter"}, "6.0"},
-	{"\U0001f33f", "herb", []string{"herb"}, "6.0"},
-	{"\U0001f33a", "hibiscus", []string{"hibiscus"}, "6.0"},
-	{"\U0001f506", "bright button", []string{"high_brightness"}, "6.0"},
-	{"\U0001f460", "high-heeled shoe", []string{"high_heel"}, "6.0"},
-	{"\U0001f97e", "hiking boot", []string{"hiking_boot"}, "11.0"},
-	{"\U0001f6d5", "hindu temple", []string{"hindu_temple"}, "12.0"},
-	{"\U0001f99b", "hippopotamus", []string{"hippopotamus"}, "11.0"},
-	{"\U0001f52a", "kitchen knife", []string{"hocho", "knife"}, "6.0"},
-	{"\U0001f573\ufe0f", "hole", []string{"hole"}, "7.0"},
-	{"\U0001f1ed\U0001f1f3", "flag: Honduras", []string{"honduras"}, "6.0"},
-	{"\U0001f36f", "honey pot", []string{"honey_pot"}, "6.0"},
-	{"\U0001f1ed\U0001f1f0", "flag: Hong Kong SAR China", []string{"hong_kong"}, "6.0"},
-	{"\U0001f434", "horse face", []string{"horse"}, "6.0"},
-	{"\U0001f3c7", "horse racing", []string{"horse_racing"}, "6.0"},
-	{"\U0001f3e5", "hospital", []string{"hospital"}, "6.0"},
-	{"\U0001f975", "hot face", []string{"hot_face"}, "11.0"},
-	{"\U0001f336\ufe0f", "hot pepper", []string{"hot_pepper"}, "7.0"},
-	{"\U0001f32d", "hot dog", []string{"hotdog"}, "8.0"},
-	{"\U0001f3e8", "hotel", []string{"hotel"}, "6.0"},
-	{"\u2668\ufe0f", "hot springs", []string{"hotsprings"}, ""},
-	{"\u231b", "hourglass done", []string{"hourglass"}, ""},
-	{"\u23f3", "hourglass not done", []string{"hourglass_flowing_sand"}, "6.0"},
-	{"\U0001f3e0", "house", []string{"house"}, "6.0"},
-	{"\U0001f3e1", "house with garden", []string{"house_with_garden"}, "6.0"},
-	{"\U0001f3d8\ufe0f", "houses", []string{"houses"}, "7.0"},
-	{"\U0001f917", "hugging face", []string{"hugs"}, "8.0"},
-	{"\U0001f1ed\U0001f1fa", "flag: Hungary", []string{"hungary"}, "6.0"},
-	{"\U0001f62f", "hushed face", []string{"hushed"}, "6.1"},
-	{"\U0001f368", "ice cream", []string{"ice_cream"}, "6.0"},
-	{"\U0001f9ca", "ice", []string{"ice_cube"}, "12.0"},
-	{"\U0001f3d2", "ice hockey", []string{"ice_hockey"}, "8.0"},
-	{"\u26f8\ufe0f", "ice skate", []string{"ice_skate"}, "5.2"},
-	{"\U0001f366", "soft ice cream", []string{"icecream"}, "6.0"},
-	{"\U0001f1ee\U0001f1f8", "flag: Iceland", []string{"iceland"}, "6.0"},
-	{"\U0001f194", "ID button", []string{"id"}, "6.0"},
-	{"\U0001f250", "Japanese โ€œbargainโ€ button", []string{"ideograph_advantage"}, "6.0"},
-	{"\U0001f47f", "angry face with horns", []string{"imp"}, "6.0"},
-	{"\U0001f4e5", "inbox tray", []string{"inbox_tray"}, "6.0"},
-	{"\U0001f4e8", "incoming envelope", []string{"incoming_envelope"}, "6.0"},
-	{"\U0001f1ee\U0001f1f3", "flag: India", []string{"india"}, "6.0"},
-	{"\U0001f1ee\U0001f1e9", "flag: Indonesia", []string{"indonesia"}, "6.0"},
-	{"\u267e\ufe0f", "infinity", []string{"infinity"}, "11.0"},
-	{"\u2139\ufe0f", "information", []string{"information_source"}, "3.0"},
-	{"\U0001f607", "smiling face with halo", []string{"innocent"}, "6.0"},
-	{"\u2049\ufe0f", "exclamation question mark", []string{"interrobang"}, "3.0"},
-	{"\U0001f4f1", "mobile phone", []string{"iphone"}, "6.0"},
-	{"\U0001f1ee\U0001f1f7", "flag: Iran", []string{"iran"}, "6.0"},
-	{"\U0001f1ee\U0001f1f6", "flag: Iraq", []string{"iraq"}, "6.0"},
-	{"\U0001f1ee\U0001f1ea", "flag: Ireland", []string{"ireland"}, "6.0"},
-	{"\U0001f1ee\U0001f1f2", "flag: Isle of Man", []string{"isle_of_man"}, "6.0"},
-	{"\U0001f1ee\U0001f1f1", "flag: Israel", []string{"israel"}, "6.0"},
-	{"\U0001f1ee\U0001f1f9", "flag: Italy", []string{"it"}, "6.0"},
-	{"\U0001f3ee", "red paper lantern", []string{"izakaya_lantern", "lantern"}, "6.0"},
-	{"\U0001f383", "jack-o-lantern", []string{"jack_o_lantern"}, "6.0"},
-	{"\U0001f1ef\U0001f1f2", "flag: Jamaica", []string{"jamaica"}, "6.0"},
-	{"\U0001f5fe", "map of Japan", []string{"japan"}, "6.0"},
-	{"\U0001f3ef", "Japanese castle", []string{"japanese_castle"}, "6.0"},
-	{"\U0001f47a", "goblin", []string{"japanese_goblin"}, "6.0"},
-	{"\U0001f479", "ogre", []string{"japanese_ogre"}, "6.0"},
-	{"\U0001f456", "jeans", []string{"jeans"}, "6.0"},
-	{"\U0001f1ef\U0001f1ea", "flag: Jersey", []string{"jersey"}, "6.0"},
-	{"\U0001f9e9", "puzzle piece", []string{"jigsaw"}, "11.0"},
-	{"\U0001f1ef\U0001f1f4", "flag: Jordan", []string{"jordan"}, "6.0"},
-	{"\U0001f602", "face with tears of joy", []string{"joy"}, "6.0"},
-	{"\U0001f639", "cat with tears of joy", []string{"joy_cat"}, "6.0"},
-	{"\U0001f579\ufe0f", "joystick", []string{"joystick"}, "7.0"},
-	{"\U0001f1ef\U0001f1f5", "flag: Japan", []string{"jp"}, "6.0"},
-	{"\U0001f9d1\u200d\u2696\ufe0f", "judge", []string{"judge"}, "12.1"},
-	{"\U0001f939", "person juggling", []string{"juggling_person"}, "11.0"},
-	{"\U0001f54b", "kaaba", []string{"kaaba"}, "8.0"},
-	{"\U0001f998", "kangaroo", []string{"kangaroo"}, "11.0"},
-	{"\U0001f1f0\U0001f1ff", "flag: Kazakhstan", []string{"kazakhstan"}, "6.0"},
-	{"\U0001f1f0\U0001f1ea", "flag: Kenya", []string{"kenya"}, "6.0"},
-	{"\U0001f511", "key", []string{"key"}, "6.0"},
-	{"\u2328\ufe0f", "keyboard", []string{"keyboard"}, ""},
-	{"\U0001f6f4", "kick scooter", []string{"kick_scooter"}, "9.0"},
-	{"\U0001f458", "kimono", []string{"kimono"}, "6.0"},
-	{"\U0001f1f0\U0001f1ee", "flag: Kiribati", []string{"kiribati"}, "6.0"},
-	{"\U0001f48b", "kiss mark", []string{"kiss"}, "6.0"},
-	{"\U0001f617", "kissing face", []string{"kissing"}, "6.1"},
-	{"\U0001f63d", "kissing cat", []string{"kissing_cat"}, "6.0"},
-	{"\U0001f61a", "kissing face with closed eyes", []string{"kissing_closed_eyes"}, "6.0"},
-	{"\U0001f618", "face blowing a kiss", []string{"kissing_heart"}, "6.0"},
-	{"\U0001f619", "kissing face with smiling eyes", []string{"kissing_smiling_eyes"}, "6.1"},
-	{"\U0001fa81", "kite", []string{"kite"}, "12.0"},
-	{"\U0001f95d", "kiwi fruit", []string{"kiwi_fruit"}, "9.0"},
-	{"\U0001f9ce\u200d\u2642\ufe0f", "man kneeling", []string{"kneeling_man"}, "12.0"},
-	{"\U0001f9ce", "person kneeling", []string{"kneeling_person"}, "12.0"},
-	{"\U0001f9ce\u200d\u2640\ufe0f", "woman kneeling", []string{"kneeling_woman"}, "12.0"},
-	{"\U0001f428", "koala", []string{"koala"}, "6.0"},
-	{"\U0001f201", "Japanese โ€œhereโ€ button", []string{"koko"}, "6.0"},
-	{"\U0001f1fd\U0001f1f0", "flag: Kosovo", []string{"kosovo"}, "6.0"},
-	{"\U0001f1f0\U0001f1f7", "flag: South Korea", []string{"kr"}, "6.0"},
-	{"\U0001f1f0\U0001f1fc", "flag: Kuwait", []string{"kuwait"}, "6.0"},
-	{"\U0001f1f0\U0001f1ec", "flag: Kyrgyzstan", []string{"kyrgyzstan"}, "6.0"},
-	{"\U0001f97c", "lab coat", []string{"lab_coat"}, "11.0"},
-	{"\U0001f3f7\ufe0f", "label", []string{"label"}, "7.0"},
-	{"\U0001f94d", "lacrosse", []string{"lacrosse"}, "11.0"},
-	{"\U0001f41e", "lady beetle", []string{"lady_beetle"}, "6.0"},
-	{"\U0001f1f1\U0001f1e6", "flag: Laos", []string{"laos"}, "6.0"},
-	{"\U0001f535", "blue circle", []string{"large_blue_circle"}, "6.0"},
-	{"\U0001f537", "large blue diamond", []string{"large_blue_diamond"}, "6.0"},
-	{"\U0001f536", "large orange diamond", []string{"large_orange_diamond"}, "6.0"},
-	{"\U0001f317", "last quarter moon", []string{"last_quarter_moon"}, "6.0"},
-	{"\U0001f31c", "last quarter moon face", []string{"last_quarter_moon_with_face"}, "6.0"},
-	{"\u271d\ufe0f", "latin cross", []string{"latin_cross"}, ""},
-	{"\U0001f1f1\U0001f1fb", "flag: Latvia", []string{"latvia"}, "6.0"},
-	{"\U0001f606", "grinning squinting face", []string{"laughing", "satisfied", "laugh"}, "6.0"},
-	{"\U0001f96c", "leafy green", []string{"leafy_green"}, "11.0"},
-	{"\U0001f343", "leaf fluttering in wind", []string{"leaves"}, "6.0"},
-	{"\U0001f1f1\U0001f1e7", "flag: Lebanon", []string{"lebanon"}, "6.0"},
-	{"\U0001f4d2", "ledger", []string{"ledger"}, "6.0"},
-	{"\U0001f6c5", "left luggage", []string{"left_luggage"}, "6.0"},
-	{"\u2194\ufe0f", "left-right arrow", []string{"left_right_arrow"}, ""},
-	{"\U0001f5e8\ufe0f", "left speech bubble", []string{"left_speech_bubble"}, "11.0"},
-	{"\u21a9\ufe0f", "right arrow curving left", []string{"leftwards_arrow_with_hook"}, ""},
-	{"\U0001f9b5", "leg", []string{"leg"}, "11.0"},
-	{"\U0001f34b", "lemon", []string{"lemon"}, "6.0"},
-	{"\u264c", "Leo", []string{"leo"}, ""},
-	{"\U0001f406", "leopard", []string{"leopard"}, "6.0"},
-	{"\U0001f1f1\U0001f1f8", "flag: Lesotho", []string{"lesotho"}, "6.0"},
-	{"\U0001f39a\ufe0f", "level slider", []string{"level_slider"}, "7.0"},
-	{"\U0001f1f1\U0001f1f7", "flag: Liberia", []string{"liberia"}, "6.0"},
-	{"\u264e", "Libra", []string{"libra"}, ""},
-	{"\U0001f1f1\U0001f1fe", "flag: Libya", []string{"libya"}, "6.0"},
-	{"\U0001f1f1\U0001f1ee", "flag: Liechtenstein", []string{"liechtenstein"}, "6.0"},
-	{"\U0001f688", "light rail", []string{"light_rail"}, "6.0"},
-	{"\U0001f517", "link", []string{"link"}, "6.0"},
-	{"\U0001f981", "lion", []string{"lion"}, "8.0"},
-	{"\U0001f444", "mouth", []string{"lips"}, "6.0"},
-	{"\U0001f484", "lipstick", []string{"lipstick"}, "6.0"},
-	{"\U0001f1f1\U0001f1f9", "flag: Lithuania", []string{"lithuania"}, "6.0"},
-	{"\U0001f98e", "lizard", []string{"lizard"}, "9.0"},
-	{"\U0001f999", "llama", []string{"llama"}, "11.0"},
-	{"\U0001f99e", "lobster", []string{"lobster"}, "11.0"},
-	{"\U0001f512", "locked", []string{"lock"}, "6.0"},
-	{"\U0001f50f", "locked with pen", []string{"lock_with_ink_pen"}, "6.0"},
-	{"\U0001f36d", "lollipop", []string{"lollipop"}, "6.0"},
-	{"\u27bf", "double curly loop", []string{"loop"}, "6.0"},
-	{"\U0001f9f4", "lotion bottle", []string{"lotion_bottle"}, "11.0"},
-	{"\U0001f9d8", "person in lotus position", []string{"lotus_position"}, "11.0"},
-	{"\U0001f9d8\u200d\u2642\ufe0f", "man in lotus position", []string{"lotus_position_man"}, "11.0"},
-	{"\U0001f9d8\u200d\u2640\ufe0f", "woman in lotus position", []string{"lotus_position_woman"}, "11.0"},
-	{"\U0001f50a", "speaker high volume", []string{"loud_sound"}, "6.0"},
-	{"\U0001f4e2", "loudspeaker", []string{"loudspeaker"}, "6.0"},
-	{"\U0001f3e9", "love hotel", []string{"love_hotel"}, "6.0"},
-	{"\U0001f48c", "love letter", []string{"love_letter"}, "6.0"},
-	{"\U0001f91f", "love-you gesture", []string{"love_you_gesture"}, "11.0"},
-	{"\U0001f505", "dim button", []string{"low_brightness"}, "6.0"},
-	{"\U0001f9f3", "luggage", []string{"luggage"}, "11.0"},
-	{"\U0001f1f1\U0001f1fa", "flag: Luxembourg", []string{"luxembourg"}, "6.0"},
-	{"\U0001f925", "lying face", []string{"lying_face"}, "9.0"},
-	{"\u24c2\ufe0f", "circled M", []string{"m"}, ""},
-	{"\U0001f1f2\U0001f1f4", "flag: Macao SAR China", []string{"macau"}, "6.0"},
-	{"\U0001f1f2\U0001f1f0", "flag: North Macedonia", []string{"macedonia"}, "6.0"},
-	{"\U0001f1f2\U0001f1ec", "flag: Madagascar", []string{"madagascar"}, "6.0"},
-	{"\U0001f50d", "magnifying glass tilted left", []string{"mag"}, "6.0"},
-	{"\U0001f50e", "magnifying glass tilted right", []string{"mag_right"}, "6.0"},
-	{"\U0001f9d9", "mage", []string{"mage"}, "11.0"},
-	{"\U0001f9d9\u200d\u2642\ufe0f", "man mage", []string{"mage_man"}, "11.0"},
-	{"\U0001f9d9\u200d\u2640\ufe0f", "woman mage", []string{"mage_woman"}, "11.0"},
-	{"\U0001f9f2", "magnet", []string{"magnet"}, "11.0"},
-	{"\U0001f004", "mahjong red dragon", []string{"mahjong"}, ""},
-	{"\U0001f4eb", "closed mailbox with raised flag", []string{"mailbox"}, "6.0"},
-	{"\U0001f4ea", "closed mailbox with lowered flag", []string{"mailbox_closed"}, "6.0"},
-	{"\U0001f4ec", "open mailbox with raised flag", []string{"mailbox_with_mail"}, "6.0"},
-	{"\U0001f4ed", "open mailbox with lowered flag", []string{"mailbox_with_no_mail"}, "6.0"},
-	{"\U0001f1f2\U0001f1fc", "flag: Malawi", []string{"malawi"}, "6.0"},
-	{"\U0001f1f2\U0001f1fe", "flag: Malaysia", []string{"malaysia"}, "6.0"},
-	{"\U0001f1f2\U0001f1fb", "flag: Maldives", []string{"maldives"}, "6.0"},
-	{"\U0001f575\ufe0f\u200d\u2642\ufe0f", "man detective", []string{"male_detective"}, "11.0"},
-	{"\u2642\ufe0f", "male sign", []string{"male_sign"}, "11.0"},
-	{"\U0001f1f2\U0001f1f1", "flag: Mali", []string{"mali"}, "6.0"},
-	{"\U0001f1f2\U0001f1f9", "flag: Malta", []string{"malta"}, "6.0"},
-	{"\U0001f468", "man", []string{"man"}, "6.0"},
-	{"\U0001f468\u200d\U0001f3a8", "man artist", []string{"man_artist"}, ""},
-	{"\U0001f468\u200d\U0001f680", "man astronaut", []string{"man_astronaut"}, ""},
-	{"\U0001f938\u200d\u2642\ufe0f", "man cartwheeling", []string{"man_cartwheeling"}, ""},
-	{"\U0001f468\u200d\U0001f373", "man cook", []string{"man_cook"}, ""},
-	{"\U0001f57a", "man dancing", []string{"man_dancing"}, "9.0"},
-	{"\U0001f926\u200d\u2642\ufe0f", "man facepalming", []string{"man_facepalming"}, "9.0"},
-	{"\U0001f468\u200d\U0001f3ed", "man factory worker", []string{"man_factory_worker"}, ""},
-	{"\U0001f468\u200d\U0001f33e", "man farmer", []string{"man_farmer"}, ""},
-	{"\U0001f468\u200d\U0001f692", "man firefighter", []string{"man_firefighter"}, ""},
-	{"\U0001f468\u200d\u2695\ufe0f", "man health worker", []string{"man_health_worker"}, ""},
-	{"\U0001f468\u200d\U0001f9bd", "man in manual wheelchair", []string{"man_in_manual_wheelchair"}, "12.0"},
-	{"\U0001f468\u200d\U0001f9bc", "man in motorized wheelchair", []string{"man_in_motorized_wheelchair"}, "12.0"},
-	{"\U0001f468\u200d\u2696\ufe0f", "man judge", []string{"man_judge"}, ""},
-	{"\U0001f939\u200d\u2642\ufe0f", "man juggling", []string{"man_juggling"}, "9.0"},
-	{"\U0001f468\u200d\U0001f527", "man mechanic", []string{"man_mechanic"}, ""},
-	{"\U0001f468\u200d\U0001f4bc", "man office worker", []string{"man_office_worker"}, ""},
-	{"\U0001f468\u200d\u2708\ufe0f", "man pilot", []string{"man_pilot"}, ""},
-	{"\U0001f93e\u200d\u2642\ufe0f", "man playing handball", []string{"man_playing_handball"}, "9.0"},
-	{"\U0001f93d\u200d\u2642\ufe0f", "man playing water polo", []string{"man_playing_water_polo"}, "9.0"},
-	{"\U0001f468\u200d\U0001f52c", "man scientist", []string{"man_scientist"}, ""},
-	{"\U0001f937\u200d\u2642\ufe0f", "man shrugging", []string{"man_shrugging"}, "9.0"},
-	{"\U0001f468\u200d\U0001f3a4", "man singer", []string{"man_singer"}, ""},
-	{"\U0001f468\u200d\U0001f393", "man student", []string{"man_student"}, ""},
-	{"\U0001f468\u200d\U0001f3eb", "man teacher", []string{"man_teacher"}, ""},
-	{"\U0001f468\u200d\U0001f4bb", "man technologist", []string{"man_technologist"}, ""},
-	{"\U0001f472", "person with skullcap", []string{"man_with_gua_pi_mao"}, "6.0"},
-	{"\U0001f468\u200d\U0001f9af", "man with white cane", []string{"man_with_probing_cane"}, "12.0"},
-	{"\U0001f473\u200d\u2642\ufe0f", "man wearing turban", []string{"man_with_turban"}, "11.0"},
-	{"\U0001f96d", "mango", []string{"mango"}, "11.0"},
-	{"\U0001f45e", "manโ€™s shoe", []string{"mans_shoe", "shoe"}, "6.0"},
-	{"\U0001f570\ufe0f", "mantelpiece clock", []string{"mantelpiece_clock"}, "7.0"},
-	{"\U0001f9bd", "manual wheelchair", []string{"manual_wheelchair"}, "12.0"},
-	{"\U0001f341", "maple leaf", []string{"maple_leaf"}, "6.0"},
-	{"\U0001f1f2\U0001f1ed", "flag: Marshall Islands", []string{"marshall_islands"}, "6.0"},
-	{"\U0001f94b", "martial arts uniform", []string{"martial_arts_uniform"}, "9.0"},
-	{"\U0001f1f2\U0001f1f6", "flag: Martinique", []string{"martinique"}, "6.0"},
-	{"\U0001f637", "face with medical mask", []string{"mask"}, "6.0"},
-	{"\U0001f486", "person getting massage", []string{"massage"}, "6.0"},
-	{"\U0001f486\u200d\u2642\ufe0f", "man getting massage", []string{"massage_man"}, "6.0"},
-	{"\U0001f486\u200d\u2640\ufe0f", "woman getting massage", []string{"massage_woman"}, "11.0"},
-	{"\U0001f9c9", "mate", []string{"mate"}, "12.0"},
-	{"\U0001f1f2\U0001f1f7", "flag: Mauritania", []string{"mauritania"}, "6.0"},
-	{"\U0001f1f2\U0001f1fa", "flag: Mauritius", []string{"mauritius"}, "6.0"},
-	{"\U0001f1fe\U0001f1f9", "flag: Mayotte", []string{"mayotte"}, "6.0"},
-	{"\U0001f356", "meat on bone", []string{"meat_on_bone"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f527", "mechanic", []string{"mechanic"}, "12.1"},
-	{"\U0001f9be", "mechanical arm", []string{"mechanical_arm"}, "12.0"},
-	{"\U0001f9bf", "mechanical leg", []string{"mechanical_leg"}, "12.0"},
-	{"\U0001f396\ufe0f", "military medal", []string{"medal_military"}, "7.0"},
-	{"\U0001f3c5", "sports medal", []string{"medal_sports"}, "7.0"},
-	{"\u2695\ufe0f", "medical symbol", []string{"medical_symbol"}, "11.0"},
-	{"\U0001f4e3", "megaphone", []string{"mega"}, "6.0"},
-	{"\U0001f348", "melon", []string{"melon"}, "6.0"},
-	{"\U0001f4dd", "memo", []string{"memo", "pencil"}, "6.0"},
-	{"\U0001f93c\u200d\u2642\ufe0f", "men wrestling", []string{"men_wrestling"}, "9.0"},
-	{"\U0001f54e", "menorah", []string{"menorah"}, "8.0"},
-	{"\U0001f6b9", "menโ€™s room", []string{"mens"}, "6.0"},
-	{"\U0001f9dc\u200d\u2640\ufe0f", "mermaid", []string{"mermaid"}, "11.0"},
-	{"\U0001f9dc\u200d\u2642\ufe0f", "merman", []string{"merman"}, "11.0"},
-	{"\U0001f9dc", "merperson", []string{"merperson"}, "11.0"},
-	{"\U0001f918", "sign of the horns", []string{"metal"}, "8.0"},
-	{"\U0001f687", "metro", []string{"metro"}, "6.0"},
-	{"\U0001f1f2\U0001f1fd", "flag: Mexico", []string{"mexico"}, "6.0"},
-	{"\U0001f9a0", "microbe", []string{"microbe"}, "11.0"},
-	{"\U0001f1eb\U0001f1f2", "flag: Micronesia", []string{"micronesia"}, "6.0"},
-	{"\U0001f3a4", "microphone", []string{"microphone"}, "6.0"},
-	{"\U0001f52c", "microscope", []string{"microscope"}, "6.0"},
-	{"\U0001f595", "middle finger", []string{"middle_finger", "fu"}, "7.0"},
-	{"\U0001f95b", "glass of milk", []string{"milk_glass"}, "9.0"},
-	{"\U0001f30c", "milky way", []string{"milky_way"}, "6.0"},
-	{"\U0001f690", "minibus", []string{"minibus"}, "6.0"},
-	{"\U0001f4bd", "computer disk", []string{"minidisc"}, "6.0"},
-	{"\U0001f4f4", "mobile phone off", []string{"mobile_phone_off"}, "6.0"},
-	{"\U0001f1f2\U0001f1e9", "flag: Moldova", []string{"moldova"}, "6.0"},
-	{"\U0001f1f2\U0001f1e8", "flag: Monaco", []string{"monaco"}, "6.0"},
-	{"\U0001f911", "money-mouth face", []string{"money_mouth_face"}, "8.0"},
-	{"\U0001f4b8", "money with wings", []string{"money_with_wings"}, "6.0"},
-	{"\U0001f4b0", "money bag", []string{"moneybag"}, "6.0"},
-	{"\U0001f1f2\U0001f1f3", "flag: Mongolia", []string{"mongolia"}, "6.0"},
-	{"\U0001f412", "monkey", []string{"monkey"}, "6.0"},
-	{"\U0001f435", "monkey face", []string{"monkey_face"}, "6.0"},
-	{"\U0001f9d0", "face with monocle", []string{"monocle_face"}, "11.0"},
-	{"\U0001f69d", "monorail", []string{"monorail"}, "6.0"},
-	{"\U0001f1f2\U0001f1ea", "flag: Montenegro", []string{"montenegro"}, "6.0"},
-	{"\U0001f1f2\U0001f1f8", "flag: Montserrat", []string{"montserrat"}, "6.0"},
-	{"\U0001f314", "waxing gibbous moon", []string{"moon", "waxing_gibbous_moon"}, "6.0"},
-	{"\U0001f96e", "moon cake", []string{"moon_cake"}, "11.0"},
-	{"\U0001f1f2\U0001f1e6", "flag: Morocco", []string{"morocco"}, "6.0"},
-	{"\U0001f393", "graduation cap", []string{"mortar_board"}, "6.0"},
-	{"\U0001f54c", "mosque", []string{"mosque"}, "8.0"},
-	{"\U0001f99f", "mosquito", []string{"mosquito"}, "11.0"},
-	{"\U0001f6e5\ufe0f", "motor boat", []string{"motor_boat"}, "7.0"},
-	{"\U0001f6f5", "motor scooter", []string{"motor_scooter"}, "9.0"},
-	{"\U0001f3cd\ufe0f", "motorcycle", []string{"motorcycle"}, "7.0"},
-	{"\U0001f9bc", "motorized wheelchair", []string{"motorized_wheelchair"}, "12.0"},
-	{"\U0001f6e3\ufe0f", "motorway", []string{"motorway"}, "7.0"},
-	{"\U0001f5fb", "mount fuji", []string{"mount_fuji"}, "6.0"},
-	{"\u26f0\ufe0f", "mountain", []string{"mountain"}, "5.2"},
-	{"\U0001f6b5", "person mountain biking", []string{"mountain_bicyclist"}, "6.0"},
-	{"\U0001f6b5\u200d\u2642\ufe0f", "man mountain biking", []string{"mountain_biking_man"}, "11.0"},
-	{"\U0001f6b5\u200d\u2640\ufe0f", "woman mountain biking", []string{"mountain_biking_woman"}, "6.0"},
-	{"\U0001f6a0", "mountain cableway", []string{"mountain_cableway"}, "6.0"},
-	{"\U0001f69e", "mountain railway", []string{"mountain_railway"}, "6.0"},
-	{"\U0001f3d4\ufe0f", "snow-capped mountain", []string{"mountain_snow"}, "7.0"},
-	{"\U0001f42d", "mouse face", []string{"mouse"}, "6.0"},
-	{"\U0001f401", "mouse", []string{"mouse2"}, "6.0"},
-	{"\U0001f3a5", "movie camera", []string{"movie_camera"}, "6.0"},
-	{"\U0001f5ff", "moai", []string{"moyai"}, "6.0"},
-	{"\U0001f1f2\U0001f1ff", "flag: Mozambique", []string{"mozambique"}, "6.0"},
-	{"\U0001f936", "Mrs. Claus", []string{"mrs_claus"}, "9.0"},
-	{"\U0001f4aa", "flexed biceps", []string{"muscle"}, "6.0"},
-	{"\U0001f344", "mushroom", []string{"mushroom"}, "6.0"},
-	{"\U0001f3b9", "musical keyboard", []string{"musical_keyboard"}, "6.0"},
-	{"\U0001f3b5", "musical note", []string{"musical_note"}, "6.0"},
-	{"\U0001f3bc", "musical score", []string{"musical_score"}, "6.0"},
-	{"\U0001f507", "muted speaker", []string{"mute"}, "6.0"},
-	{"\U0001f1f2\U0001f1f2", "flag: Myanmar (Burma)", []string{"myanmar"}, "6.0"},
-	{"\U0001f485", "nail polish", []string{"nail_care"}, "6.0"},
-	{"\U0001f4db", "name badge", []string{"name_badge"}, "6.0"},
-	{"\U0001f1f3\U0001f1e6", "flag: Namibia", []string{"namibia"}, "6.0"},
-	{"\U0001f3de\ufe0f", "national park", []string{"national_park"}, "7.0"},
-	{"\U0001f1f3\U0001f1f7", "flag: Nauru", []string{"nauru"}, "6.0"},
-	{"\U0001f922", "nauseated face", []string{"nauseated_face"}, "9.0"},
-	{"\U0001f9ff", "nazar amulet", []string{"nazar_amulet"}, "11.0"},
-	{"\U0001f454", "necktie", []string{"necktie"}, "6.0"},
-	{"\u274e", "cross mark button", []string{"negative_squared_cross_mark"}, "6.0"},
-	{"\U0001f1f3\U0001f1f5", "flag: Nepal", []string{"nepal"}, "6.0"},
-	{"\U0001f913", "nerd face", []string{"nerd_face"}, "8.0"},
-	{"\U0001f1f3\U0001f1f1", "flag: Netherlands", []string{"netherlands"}, "6.0"},
-	{"\U0001f610", "neutral face", []string{"neutral_face"}, "6.0"},
-	{"\U0001f195", "NEW button", []string{"new"}, "6.0"},
-	{"\U0001f1f3\U0001f1e8", "flag: New Caledonia", []string{"new_caledonia"}, "6.0"},
-	{"\U0001f311", "new moon", []string{"new_moon"}, "6.0"},
-	{"\U0001f31a", "new moon face", []string{"new_moon_with_face"}, "6.0"},
-	{"\U0001f1f3\U0001f1ff", "flag: New Zealand", []string{"new_zealand"}, "6.0"},
-	{"\U0001f4f0", "newspaper", []string{"newspaper"}, "6.0"},
-	{"\U0001f5de\ufe0f", "rolled-up newspaper", []string{"newspaper_roll"}, "7.0"},
-	{"\u23ed\ufe0f", "next track button", []string{"next_track_button"}, "6.0"},
-	{"\U0001f196", "NG button", []string{"ng"}, "6.0"},
-	{"\U0001f1f3\U0001f1ee", "flag: Nicaragua", []string{"nicaragua"}, "6.0"},
-	{"\U0001f1f3\U0001f1ea", "flag: Niger", []string{"niger"}, "6.0"},
-	{"\U0001f1f3\U0001f1ec", "flag: Nigeria", []string{"nigeria"}, "6.0"},
-	{"\U0001f303", "night with stars", []string{"night_with_stars"}, "6.0"},
-	{"\U0001f1f3\U0001f1fa", "flag: Niue", []string{"niue"}, "6.0"},
-	{"\U0001f515", "bell with slash", []string{"no_bell"}, "6.0"},
-	{"\U0001f6b3", "no bicycles", []string{"no_bicycles"}, "6.0"},
-	{"\u26d4", "no entry", []string{"no_entry"}, "5.2"},
-	{"\U0001f6ab", "prohibited", []string{"no_entry_sign"}, "6.0"},
-	{"\U0001f645", "person gesturing NO", []string{"no_good"}, "6.0"},
-	{"\U0001f645\u200d\u2642\ufe0f", "man gesturing NO", []string{"no_good_man", "ng_man"}, "6.0"},
-	{"\U0001f645\u200d\u2640\ufe0f", "woman gesturing NO", []string{"no_good_woman", "ng_woman"}, "11.0"},
-	{"\U0001f4f5", "no mobile phones", []string{"no_mobile_phones"}, "6.0"},
-	{"\U0001f636", "face without mouth", []string{"no_mouth"}, "6.0"},
-	{"\U0001f6b7", "no pedestrians", []string{"no_pedestrians"}, "6.0"},
-	{"\U0001f6ad", "no smoking", []string{"no_smoking"}, "6.0"},
-	{"\U0001f6b1", "non-potable water", []string{"non-potable_water"}, "6.0"},
-	{"\U0001f1f3\U0001f1eb", "flag: Norfolk Island", []string{"norfolk_island"}, "6.0"},
-	{"\U0001f1f0\U0001f1f5", "flag: North Korea", []string{"north_korea"}, "6.0"},
-	{"\U0001f1f2\U0001f1f5", "flag: Northern Mariana Islands", []string{"northern_mariana_islands"}, "6.0"},
-	{"\U0001f1f3\U0001f1f4", "flag: Norway", []string{"norway"}, "6.0"},
-	{"\U0001f443", "nose", []string{"nose"}, "6.0"},
-	{"\U0001f4d3", "notebook", []string{"notebook"}, "6.0"},
-	{"\U0001f4d4", "notebook with decorative cover", []string{"notebook_with_decorative_cover"}, "6.0"},
-	{"\U0001f3b6", "musical notes", []string{"notes"}, "6.0"},
-	{"\U0001f529", "nut and bolt", []string{"nut_and_bolt"}, "6.0"},
-	{"\u2b55", "hollow red circle", []string{"o"}, "5.2"},
-	{"\U0001f17e\ufe0f", "O button (blood type)", []string{"o2"}, "6.0"},
-	{"\U0001f30a", "water wave", []string{"ocean"}, "6.0"},
-	{"\U0001f419", "octopus", []string{"octopus"}, "6.0"},
-	{"\U0001f362", "oden", []string{"oden"}, "6.0"},
-	{"\U0001f3e2", "office building", []string{"office"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f4bc", "office worker", []string{"office_worker"}, "12.1"},
-	{"\U0001f6e2\ufe0f", "oil drum", []string{"oil_drum"}, "7.0"},
-	{"\U0001f197", "OK button", []string{"ok"}, "6.0"},
-	{"\U0001f44c", "OK hand", []string{"ok_hand"}, "6.0"},
-	{"\U0001f646\u200d\u2642\ufe0f", "man gesturing OK", []string{"ok_man"}, "6.0"},
-	{"\U0001f646", "person gesturing OK", []string{"ok_person"}, "6.0"},
-	{"\U0001f646\u200d\u2640\ufe0f", "woman gesturing OK", []string{"ok_woman"}, "11.0"},
-	{"\U0001f5dd\ufe0f", "old key", []string{"old_key"}, "7.0"},
-	{"\U0001f9d3", "older person", []string{"older_adult"}, "11.0"},
-	{"\U0001f474", "old man", []string{"older_man"}, "6.0"},
-	{"\U0001f475", "old woman", []string{"older_woman"}, "6.0"},
-	{"\U0001f549\ufe0f", "om", []string{"om"}, "7.0"},
-	{"\U0001f1f4\U0001f1f2", "flag: Oman", []string{"oman"}, "6.0"},
-	{"\U0001f51b", "ON! arrow", []string{"on"}, "6.0"},
-	{"\U0001f698", "oncoming automobile", []string{"oncoming_automobile"}, "6.0"},
-	{"\U0001f68d", "oncoming bus", []string{"oncoming_bus"}, "6.0"},
-	{"\U0001f694", "oncoming police car", []string{"oncoming_police_car"}, "6.0"},
-	{"\U0001f696", "oncoming taxi", []string{"oncoming_taxi"}, "6.0"},
-	{"\U0001fa71", "one-piece swimsuit", []string{"one_piece_swimsuit"}, "12.0"},
-	{"\U0001f9c5", "onion", []string{"onion"}, "12.0"},
-	{"\U0001f4c2", "open file folder", []string{"open_file_folder"}, "6.0"},
-	{"\U0001f450", "open hands", []string{"open_hands"}, "6.0"},
-	{"\U0001f62e", "face with open mouth", []string{"open_mouth"}, "6.1"},
-	{"\u2602\ufe0f", "umbrella", []string{"open_umbrella"}, ""},
-	{"\u26ce", "Ophiuchus", []string{"ophiuchus"}, "6.0"},
-	{"\U0001f4d9", "orange book", []string{"orange_book"}, "6.0"},
-	{"\U0001f7e0", "orange circle", []string{"orange_circle"}, "12.0"},
-	{"\U0001f9e1", "orange heart", []string{"orange_heart"}, "11.0"},
-	{"\U0001f7e7", "orange square", []string{"orange_square"}, "12.0"},
-	{"\U0001f9a7", "orangutan", []string{"orangutan"}, "12.0"},
-	{"\u2626\ufe0f", "orthodox cross", []string{"orthodox_cross"}, ""},
-	{"\U0001f9a6", "otter", []string{"otter"}, "12.0"},
-	{"\U0001f4e4", "outbox tray", []string{"outbox_tray"}, "6.0"},
-	{"\U0001f989", "owl", []string{"owl"}, "9.0"},
-	{"\U0001f402", "ox", []string{"ox"}, "6.0"},
-	{"\U0001f9aa", "oyster", []string{"oyster"}, "12.0"},
-	{"\U0001f4e6", "package", []string{"package"}, "6.0"},
-	{"\U0001f4c4", "page facing up", []string{"page_facing_up"}, "6.0"},
-	{"\U0001f4c3", "page with curl", []string{"page_with_curl"}, "6.0"},
-	{"\U0001f4df", "pager", []string{"pager"}, "6.0"},
-	{"\U0001f58c\ufe0f", "paintbrush", []string{"paintbrush"}, "7.0"},
-	{"\U0001f1f5\U0001f1f0", "flag: Pakistan", []string{"pakistan"}, "6.0"},
-	{"\U0001f1f5\U0001f1fc", "flag: Palau", []string{"palau"}, "6.0"},
-	{"\U0001f1f5\U0001f1f8", "flag: Palestinian Territories", []string{"palestinian_territories"}, "6.0"},
-	{"\U0001f334", "palm tree", []string{"palm_tree"}, "6.0"},
-	{"\U0001f932", "palms up together", []string{"palms_up_together"}, "11.0"},
-	{"\U0001f1f5\U0001f1e6", "flag: Panama", []string{"panama"}, "6.0"},
-	{"\U0001f95e", "pancakes", []string{"pancakes"}, "9.0"},
-	{"\U0001f43c", "panda", []string{"panda_face"}, "6.0"},
-	{"\U0001f4ce", "paperclip", []string{"paperclip"}, "6.0"},
-	{"\U0001f587\ufe0f", "linked paperclips", []string{"paperclips"}, "7.0"},
-	{"\U0001f1f5\U0001f1ec", "flag: Papua New Guinea", []string{"papua_new_guinea"}, "6.0"},
-	{"\U0001fa82", "parachute", []string{"parachute"}, "12.0"},
-	{"\U0001f1f5\U0001f1fe", "flag: Paraguay", []string{"paraguay"}, "6.0"},
-	{"\u26f1\ufe0f", "umbrella on ground", []string{"parasol_on_ground"}, "5.2"},
-	{"\U0001f17f\ufe0f", "P button", []string{"parking"}, "5.2"},
-	{"\U0001f99c", "parrot", []string{"parrot"}, "11.0"},
-	{"\u303d\ufe0f", "part alternation mark", []string{"part_alternation_mark"}, "3.2"},
-	{"\u26c5", "sun behind cloud", []string{"partly_sunny"}, "5.2"},
-	{"\U0001f973", "partying face", []string{"partying_face"}, "11.0"},
-	{"\U0001f6f3\ufe0f", "passenger ship", []string{"passenger_ship"}, "7.0"},
-	{"\U0001f6c2", "passport control", []string{"passport_control"}, "6.0"},
-	{"\u23f8\ufe0f", "pause button", []string{"pause_button"}, "7.0"},
-	{"\u262e\ufe0f", "peace symbol", []string{"peace_symbol"}, ""},
-	{"\U0001f351", "peach", []string{"peach"}, "6.0"},
-	{"\U0001f99a", "peacock", []string{"peacock"}, "11.0"},
-	{"\U0001f95c", "peanuts", []string{"peanuts"}, "9.0"},
-	{"\U0001f350", "pear", []string{"pear"}, "6.0"},
-	{"\U0001f58a\ufe0f", "pen", []string{"pen"}, "7.0"},
-	{"\u270f\ufe0f", "pencil", []string{"pencil2"}, ""},
-	{"\U0001f427", "penguin", []string{"penguin"}, "6.0"},
-	{"\U0001f614", "pensive face", []string{"pensive"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands", []string{"people_holding_hands"}, "12.0"},
-	{"\U0001f3ad", "performing arts", []string{"performing_arts"}, "6.0"},
-	{"\U0001f623", "persevering face", []string{"persevere"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f9b2", "person: bald", []string{"person_bald"}, "12.1"},
-	{"\U0001f9d1\u200d\U0001f9b1", "person: curly hair", []string{"person_curly_hair"}, "12.1"},
-	{"\U0001f93a", "person fencing", []string{"person_fencing"}, "9.0"},
-	{"\U0001f9d1\u200d\U0001f9bd", "person in manual wheelchair", []string{"person_in_manual_wheelchair"}, "12.1"},
-	{"\U0001f9d1\u200d\U0001f9bc", "person in motorized wheelchair", []string{"person_in_motorized_wheelchair"}, "12.1"},
-	{"\U0001f935", "person in tuxedo", []string{"person_in_tuxedo"}, "9.0"},
-	{"\U0001f9d1\u200d\U0001f9b0", "person: red hair", []string{"person_red_hair"}, "12.1"},
-	{"\U0001f9d1\u200d\U0001f9b3", "person: white hair", []string{"person_white_hair"}, "12.1"},
-	{"\U0001f9d1\u200d\U0001f9af", "person with white cane", []string{"person_with_probing_cane"}, "12.1"},
-	{"\U0001f473", "person wearing turban", []string{"person_with_turban"}, "6.0"},
-	{"\U0001f470", "person with veil", []string{"person_with_veil"}, "6.0"},
-	{"\U0001f1f5\U0001f1ea", "flag: Peru", []string{"peru"}, "6.0"},
-	{"\U0001f9eb", "petri dish", []string{"petri_dish"}, "11.0"},
-	{"\U0001f1f5\U0001f1ed", "flag: Philippines", []string{"philippines"}, "6.0"},
-	{"\u260e\ufe0f", "telephone", []string{"phone", "telephone"}, ""},
-	{"\u26cf\ufe0f", "pick", []string{"pick"}, "5.2"},
-	{"\U0001f967", "pie", []string{"pie"}, "11.0"},
-	{"\U0001f437", "pig face", []string{"pig"}, "6.0"},
-	{"\U0001f416", "pig", []string{"pig2"}, "6.0"},
-	{"\U0001f43d", "pig nose", []string{"pig_nose"}, "6.0"},
-	{"\U0001f48a", "pill", []string{"pill"}, "6.0"},
-	{"\U0001f9d1\u200d\u2708\ufe0f", "pilot", []string{"pilot"}, "12.1"},
-	{"\U0001f90f", "pinching hand", []string{"pinching_hand"}, "12.0"},
-	{"\U0001f34d", "pineapple", []string{"pineapple"}, "6.0"},
-	{"\U0001f3d3", "ping pong", []string{"ping_pong"}, "8.0"},
-	{"\U0001f3f4\u200d\u2620\ufe0f", "pirate flag", []string{"pirate_flag"}, "11.0"},
-	{"\u2653", "Pisces", []string{"pisces"}, ""},
-	{"\U0001f1f5\U0001f1f3", "flag: Pitcairn Islands", []string{"pitcairn_islands"}, "6.0"},
-	{"\U0001f355", "pizza", []string{"pizza"}, "6.0"},
-	{"\U0001f6d0", "place of worship", []string{"place_of_worship"}, "8.0"},
-	{"\U0001f37d\ufe0f", "fork and knife with plate", []string{"plate_with_cutlery"}, "7.0"},
-	{"\u23ef\ufe0f", "play or pause button", []string{"play_or_pause_button"}, "6.0"},
-	{"\U0001f97a", "pleading face", []string{"pleading_face"}, "11.0"},
-	{"\U0001f447", "backhand index pointing down", []string{"point_down"}, "6.0"},
-	{"\U0001f448", "backhand index pointing left", []string{"point_left"}, "6.0"},
-	{"\U0001f449", "backhand index pointing right", []string{"point_right"}, "6.0"},
-	{"\u261d\ufe0f", "index pointing up", []string{"point_up"}, ""},
-	{"\U0001f446", "backhand index pointing up", []string{"point_up_2"}, "6.0"},
-	{"\U0001f1f5\U0001f1f1", "flag: Poland", []string{"poland"}, "6.0"},
-	{"\U0001f693", "police car", []string{"police_car"}, "6.0"},
-	{"\U0001f46e", "police officer", []string{"police_officer", "cop"}, "6.0"},
-	{"\U0001f46e\u200d\u2642\ufe0f", "man police officer", []string{"policeman"}, "11.0"},
-	{"\U0001f46e\u200d\u2640\ufe0f", "woman police officer", []string{"policewoman"}, "6.0"},
-	{"\U0001f429", "poodle", []string{"poodle"}, "6.0"},
-	{"\U0001f37f", "popcorn", []string{"popcorn"}, "8.0"},
-	{"\U0001f1f5\U0001f1f9", "flag: Portugal", []string{"portugal"}, "6.0"},
-	{"\U0001f3e3", "Japanese post office", []string{"post_office"}, "6.0"},
-	{"\U0001f4ef", "postal horn", []string{"postal_horn"}, "6.0"},
-	{"\U0001f4ee", "postbox", []string{"postbox"}, "6.0"},
-	{"\U0001f6b0", "potable water", []string{"potable_water"}, "6.0"},
-	{"\U0001f954", "potato", []string{"potato"}, "9.0"},
-	{"\U0001f45d", "clutch bag", []string{"pouch"}, "6.0"},
-	{"\U0001f357", "poultry leg", []string{"poultry_leg"}, "6.0"},
-	{"\U0001f4b7", "pound banknote", []string{"pound"}, "6.0"},
-	{"\U0001f63e", "pouting cat", []string{"pouting_cat"}, "6.0"},
-	{"\U0001f64e", "person pouting", []string{"pouting_face"}, "6.0"},
-	{"\U0001f64e\u200d\u2642\ufe0f", "man pouting", []string{"pouting_man"}, "6.0"},
-	{"\U0001f64e\u200d\u2640\ufe0f", "woman pouting", []string{"pouting_woman"}, "11.0"},
-	{"\U0001f64f", "folded hands", []string{"pray"}, "6.0"},
-	{"\U0001f4ff", "prayer beads", []string{"prayer_beads"}, "8.0"},
-	{"\U0001f930", "pregnant woman", []string{"pregnant_woman"}, "9.0"},
-	{"\U0001f968", "pretzel", []string{"pretzel"}, "11.0"},
-	{"\u23ee\ufe0f", "last track button", []string{"previous_track_button"}, "6.0"},
-	{"\U0001f934", "prince", []string{"prince"}, "9.0"},
-	{"\U0001f478", "princess", []string{"princess"}, "6.0"},
-	{"\U0001f5a8\ufe0f", "printer", []string{"printer"}, "7.0"},
-	{"\U0001f9af", "white cane", []string{"probing_cane"}, "12.0"},
-	{"\U0001f1f5\U0001f1f7", "flag: Puerto Rico", []string{"puerto_rico"}, "6.0"},
-	{"\U0001f7e3", "purple circle", []string{"purple_circle"}, "12.0"},
-	{"\U0001f49c", "purple heart", []string{"purple_heart"}, "6.0"},
-	{"\U0001f7ea", "purple square", []string{"purple_square"}, "12.0"},
-	{"\U0001f45b", "purse", []string{"purse"}, "6.0"},
-	{"\U0001f4cc", "pushpin", []string{"pushpin"}, "6.0"},
-	{"\U0001f6ae", "litter in bin sign", []string{"put_litter_in_its_place"}, "6.0"},
-	{"\U0001f1f6\U0001f1e6", "flag: Qatar", []string{"qatar"}, "6.0"},
-	{"\u2753", "question mark", []string{"question"}, "6.0"},
-	{"\U0001f430", "rabbit face", []string{"rabbit"}, "6.0"},
-	{"\U0001f407", "rabbit", []string{"rabbit2"}, "6.0"},
-	{"\U0001f99d", "raccoon", []string{"raccoon"}, "11.0"},
-	{"\U0001f40e", "horse", []string{"racehorse"}, "6.0"},
-	{"\U0001f3ce\ufe0f", "racing car", []string{"racing_car"}, "7.0"},
-	{"\U0001f4fb", "radio", []string{"radio"}, "6.0"},
-	{"\U0001f518", "radio button", []string{"radio_button"}, "6.0"},
-	{"\u2622\ufe0f", "radioactive", []string{"radioactive"}, ""},
-	{"\U0001f621", "pouting face", []string{"rage", "pout"}, "6.0"},
-	{"\U0001f683", "railway car", []string{"railway_car"}, "6.0"},
-	{"\U0001f6e4\ufe0f", "railway track", []string{"railway_track"}, "7.0"},
-	{"\U0001f308", "rainbow", []string{"rainbow"}, "6.0"},
-	{"\U0001f3f3\ufe0f\u200d\U0001f308", "rainbow flag", []string{"rainbow_flag"}, "6.0"},
-	{"\U0001f91a", "raised back of hand", []string{"raised_back_of_hand"}, "9.0"},
-	{"\U0001f928", "face with raised eyebrow", []string{"raised_eyebrow"}, "11.0"},
-	{"\U0001f590\ufe0f", "hand with fingers splayed", []string{"raised_hand_with_fingers_splayed"}, "7.0"},
-	{"\U0001f64c", "raising hands", []string{"raised_hands"}, "6.0"},
-	{"\U0001f64b", "person raising hand", []string{"raising_hand"}, "6.0"},
-	{"\U0001f64b\u200d\u2642\ufe0f", "man raising hand", []string{"raising_hand_man"}, "6.0"},
-	{"\U0001f64b\u200d\u2640\ufe0f", "woman raising hand", []string{"raising_hand_woman"}, "11.0"},
-	{"\U0001f40f", "ram", []string{"ram"}, "6.0"},
-	{"\U0001f35c", "steaming bowl", []string{"ramen"}, "6.0"},
-	{"\U0001f400", "rat", []string{"rat"}, "6.0"},
-	{"\U0001fa92", "razor", []string{"razor"}, "12.0"},
-	{"\U0001f9fe", "receipt", []string{"receipt"}, "11.0"},
-	{"\u23fa\ufe0f", "record button", []string{"record_button"}, "7.0"},
-	{"\u267b\ufe0f", "recycling symbol", []string{"recycle"}, "3.2"},
-	{"\U0001f534", "red circle", []string{"red_circle"}, "6.0"},
-	{"\U0001f9e7", "red envelope", []string{"red_envelope"}, "11.0"},
-	{"\U0001f468\u200d\U0001f9b0", "man: red hair", []string{"red_haired_man"}, "11.0"},
-	{"\U0001f469\u200d\U0001f9b0", "woman: red hair", []string{"red_haired_woman"}, "11.0"},
-	{"\U0001f7e5", "red square", []string{"red_square"}, "12.0"},
-	{"\u263a\ufe0f", "smiling face", []string{"relaxed"}, ""},
-	{"\U0001f60c", "relieved face", []string{"relieved"}, "6.0"},
-	{"\U0001f397\ufe0f", "reminder ribbon", []string{"reminder_ribbon"}, "7.0"},
-	{"\U0001f501", "repeat button", []string{"repeat"}, "6.0"},
-	{"\U0001f502", "repeat single button", []string{"repeat_one"}, "6.0"},
-	{"\u26d1\ufe0f", "rescue workerโ€™s helmet", []string{"rescue_worker_helmet"}, "5.2"},
-	{"\U0001f6bb", "restroom", []string{"restroom"}, "6.0"},
-	{"\U0001f1f7\U0001f1ea", "flag: Rรฉunion", []string{"reunion"}, "6.0"},
-	{"\U0001f49e", "revolving hearts", []string{"revolving_hearts"}, "6.0"},
-	{"\u23ea", "fast reverse button", []string{"rewind"}, "6.0"},
-	{"\U0001f98f", "rhinoceros", []string{"rhinoceros"}, "9.0"},
-	{"\U0001f380", "ribbon", []string{"ribbon"}, "6.0"},
-	{"\U0001f35a", "cooked rice", []string{"rice"}, "6.0"},
-	{"\U0001f359", "rice ball", []string{"rice_ball"}, "6.0"},
-	{"\U0001f358", "rice cracker", []string{"rice_cracker"}, "6.0"},
-	{"\U0001f391", "moon viewing ceremony", []string{"rice_scene"}, "6.0"},
-	{"\U0001f5ef\ufe0f", "right anger bubble", []string{"right_anger_bubble"}, "7.0"},
-	{"\U0001f48d", "ring", []string{"ring"}, "6.0"},
-	{"\U0001fa90", "ringed planet", []string{"ringed_planet"}, "12.0"},
-	{"\U0001f916", "robot", []string{"robot"}, "8.0"},
-	{"\U0001f680", "rocket", []string{"rocket"}, "6.0"},
-	{"\U0001f923", "rolling on the floor laughing", []string{"rofl"}, "9.0"},
-	{"\U0001f644", "face with rolling eyes", []string{"roll_eyes"}, "8.0"},
-	{"\U0001f9fb", "roll of paper", []string{"roll_of_paper"}, "11.0"},
-	{"\U0001f3a2", "roller coaster", []string{"roller_coaster"}, "6.0"},
-	{"\U0001f1f7\U0001f1f4", "flag: Romania", []string{"romania"}, "6.0"},
-	{"\U0001f413", "rooster", []string{"rooster"}, "6.0"},
-	{"\U0001f339", "rose", []string{"rose"}, "6.0"},
-	{"\U0001f3f5\ufe0f", "rosette", []string{"rosette"}, "7.0"},
-	{"\U0001f6a8", "police car light", []string{"rotating_light"}, "6.0"},
-	{"\U0001f4cd", "round pushpin", []string{"round_pushpin"}, "6.0"},
-	{"\U0001f6a3", "person rowing boat", []string{"rowboat"}, "6.0"},
-	{"\U0001f6a3\u200d\u2642\ufe0f", "man rowing boat", []string{"rowing_man"}, "11.0"},
-	{"\U0001f6a3\u200d\u2640\ufe0f", "woman rowing boat", []string{"rowing_woman"}, "6.0"},
-	{"\U0001f1f7\U0001f1fa", "flag: Russia", []string{"ru"}, "6.0"},
-	{"\U0001f3c9", "rugby football", []string{"rugby_football"}, "6.0"},
-	{"\U0001f3c3", "person running", []string{"runner", "running"}, "6.0"},
-	{"\U0001f3c3\u200d\u2642\ufe0f", "man running", []string{"running_man"}, "11.0"},
-	{"\U0001f3bd", "running shirt", []string{"running_shirt_with_sash"}, "6.0"},
-	{"\U0001f3c3\u200d\u2640\ufe0f", "woman running", []string{"running_woman"}, "6.0"},
-	{"\U0001f1f7\U0001f1fc", "flag: Rwanda", []string{"rwanda"}, "6.0"},
-	{"\U0001f202\ufe0f", "Japanese โ€œservice chargeโ€ button", []string{"sa"}, "6.0"},
-	{"\U0001f9f7", "safety pin", []string{"safety_pin"}, "11.0"},
-	{"\U0001f9ba", "safety vest", []string{"safety_vest"}, "12.0"},
-	{"\u2650", "Sagittarius", []string{"sagittarius"}, ""},
-	{"\U0001f376", "sake", []string{"sake"}, "6.0"},
-	{"\U0001f9c2", "salt", []string{"salt"}, "11.0"},
-	{"\U0001f1fc\U0001f1f8", "flag: Samoa", []string{"samoa"}, "6.0"},
-	{"\U0001f1f8\U0001f1f2", "flag: San Marino", []string{"san_marino"}, "6.0"},
-	{"\U0001f461", "womanโ€™s sandal", []string{"sandal"}, "6.0"},
-	{"\U0001f96a", "sandwich", []string{"sandwich"}, "11.0"},
-	{"\U0001f385", "Santa Claus", []string{"santa"}, "6.0"},
-	{"\U0001f1f8\U0001f1f9", "flag: Sรฃo Tomรฉ & Prรญncipe", []string{"sao_tome_principe"}, "6.0"},
-	{"\U0001f97b", "sari", []string{"sari"}, "12.0"},
-	{"\U0001f4e1", "satellite antenna", []string{"satellite"}, "6.0"},
-	{"\U0001f1f8\U0001f1e6", "flag: Saudi Arabia", []string{"saudi_arabia"}, "6.0"},
-	{"\U0001f9d6\u200d\u2642\ufe0f", "man in steamy room", []string{"sauna_man"}, "11.0"},
-	{"\U0001f9d6", "person in steamy room", []string{"sauna_person"}, "11.0"},
-	{"\U0001f9d6\u200d\u2640\ufe0f", "woman in steamy room", []string{"sauna_woman"}, "11.0"},
-	{"\U0001f995", "sauropod", []string{"sauropod"}, "11.0"},
-	{"\U0001f3b7", "saxophone", []string{"saxophone"}, "6.0"},
-	{"\U0001f9e3", "scarf", []string{"scarf"}, "11.0"},
-	{"\U0001f3eb", "school", []string{"school"}, "6.0"},
-	{"\U0001f392", "backpack", []string{"school_satchel"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f52c", "scientist", []string{"scientist"}, "12.1"},
-	{"\u2702\ufe0f", "scissors", []string{"scissors"}, ""},
-	{"\U0001f982", "scorpion", []string{"scorpion"}, "8.0"},
-	{"\u264f", "Scorpio", []string{"scorpius"}, ""},
-	{"\U0001f3f4\U000e0067\U000e0062\U000e0073\U000e0063\U000e0074\U000e007f", "flag: Scotland", []string{"scotland"}, "11.0"},
-	{"\U0001f631", "face screaming in fear", []string{"scream"}, "6.0"},
-	{"\U0001f640", "weary cat", []string{"scream_cat"}, "6.0"},
-	{"\U0001f4dc", "scroll", []string{"scroll"}, "6.0"},
-	{"\U0001f4ba", "seat", []string{"seat"}, "6.0"},
-	{"\u3299\ufe0f", "Japanese โ€œsecretโ€ button", []string{"secret"}, ""},
-	{"\U0001f648", "see-no-evil monkey", []string{"see_no_evil"}, "6.0"},
-	{"\U0001f331", "seedling", []string{"seedling"}, "6.0"},
-	{"\U0001f933", "selfie", []string{"selfie"}, "9.0"},
-	{"\U0001f1f8\U0001f1f3", "flag: Senegal", []string{"senegal"}, "6.0"},
-	{"\U0001f1f7\U0001f1f8", "flag: Serbia", []string{"serbia"}, "6.0"},
-	{"\U0001f415\u200d\U0001f9ba", "service dog", []string{"service_dog"}, "12.0"},
-	{"\U0001f1f8\U0001f1e8", "flag: Seychelles", []string{"seychelles"}, "6.0"},
-	{"\U0001f958", "shallow pan of food", []string{"shallow_pan_of_food"}, ""},
-	{"\u2618\ufe0f", "shamrock", []string{"shamrock"}, "4.1"},
-	{"\U0001f988", "shark", []string{"shark"}, "9.0"},
-	{"\U0001f367", "shaved ice", []string{"shaved_ice"}, "6.0"},
-	{"\U0001f411", "ewe", []string{"sheep"}, "6.0"},
-	{"\U0001f41a", "spiral shell", []string{"shell"}, "6.0"},
-	{"\U0001f6e1\ufe0f", "shield", []string{"shield"}, "7.0"},
-	{"\u26e9\ufe0f", "shinto shrine", []string{"shinto_shrine"}, "5.2"},
-	{"\U0001f6a2", "ship", []string{"ship"}, "6.0"},
-	{"\U0001f455", "t-shirt", []string{"shirt", "tshirt"}, "6.0"},
-	{"\U0001f6cd\ufe0f", "shopping bags", []string{"shopping"}, "7.0"},
-	{"\U0001f6d2", "shopping cart", []string{"shopping_cart"}, "9.0"},
-	{"\U0001fa73", "shorts", []string{"shorts"}, "12.0"},
-	{"\U0001f6bf", "shower", []string{"shower"}, "6.0"},
-	{"\U0001f990", "shrimp", []string{"shrimp"}, "9.0"},
-	{"\U0001f937", "person shrugging", []string{"shrug"}, "11.0"},
-	{"\U0001f92b", "shushing face", []string{"shushing_face"}, "11.0"},
-	{"\U0001f1f8\U0001f1f1", "flag: Sierra Leone", []string{"sierra_leone"}, "6.0"},
-	{"\U0001f4f6", "antenna bars", []string{"signal_strength"}, "6.0"},
-	{"\U0001f1f8\U0001f1ec", "flag: Singapore", []string{"singapore"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f3a4", "singer", []string{"singer"}, "12.1"},
-	{"\U0001f1f8\U0001f1fd", "flag: Sint Maarten", []string{"sint_maarten"}, "6.0"},
-	{"\U0001f52f", "dotted six-pointed star", []string{"six_pointed_star"}, "6.0"},
-	{"\U0001f6f9", "skateboard", []string{"skateboard"}, "11.0"},
-	{"\U0001f3bf", "skis", []string{"ski"}, "6.0"},
-	{"\u26f7\ufe0f", "skier", []string{"skier"}, "5.2"},
-	{"\U0001f480", "skull", []string{"skull"}, "6.0"},
-	{"\u2620\ufe0f", "skull and crossbones", []string{"skull_and_crossbones"}, ""},
-	{"\U0001f9a8", "skunk", []string{"skunk"}, "12.0"},
-	{"\U0001f6f7", "sled", []string{"sled"}, "11.0"},
-	{"\U0001f634", "sleeping face", []string{"sleeping"}, "6.1"},
-	{"\U0001f6cc", "person in bed", []string{"sleeping_bed"}, "7.0"},
-	{"\U0001f62a", "sleepy face", []string{"sleepy"}, "6.0"},
-	{"\U0001f641", "slightly frowning face", []string{"slightly_frowning_face"}, "7.0"},
-	{"\U0001f642", "slightly smiling face", []string{"slightly_smiling_face"}, "7.0"},
-	{"\U0001f3b0", "slot machine", []string{"slot_machine"}, "6.0"},
-	{"\U0001f9a5", "sloth", []string{"sloth"}, "12.0"},
-	{"\U0001f1f8\U0001f1f0", "flag: Slovakia", []string{"slovakia"}, "6.0"},
-	{"\U0001f1f8\U0001f1ee", "flag: Slovenia", []string{"slovenia"}, "6.0"},
-	{"\U0001f6e9\ufe0f", "small airplane", []string{"small_airplane"}, "7.0"},
-	{"\U0001f539", "small blue diamond", []string{"small_blue_diamond"}, "6.0"},
-	{"\U0001f538", "small orange diamond", []string{"small_orange_diamond"}, "6.0"},
-	{"\U0001f53a", "red triangle pointed up", []string{"small_red_triangle"}, "6.0"},
-	{"\U0001f53b", "red triangle pointed down", []string{"small_red_triangle_down"}, "6.0"},
-	{"\U0001f604", "grinning face with smiling eyes", []string{"smile"}, "6.0"},
-	{"\U0001f638", "grinning cat with smiling eyes", []string{"smile_cat"}, "6.0"},
-	{"\U0001f603", "grinning face with big eyes", []string{"smiley"}, "6.0"},
-	{"\U0001f63a", "grinning cat", []string{"smiley_cat"}, "6.0"},
-	{"\U0001f970", "smiling face with hearts", []string{"smiling_face_with_three_hearts"}, "11.0"},
-	{"\U0001f608", "smiling face with horns", []string{"smiling_imp"}, "6.0"},
-	{"\U0001f60f", "smirking face", []string{"smirk"}, "6.0"},
-	{"\U0001f63c", "cat with wry smile", []string{"smirk_cat"}, "6.0"},
-	{"\U0001f6ac", "cigarette", []string{"smoking"}, "6.0"},
-	{"\U0001f40c", "snail", []string{"snail"}, "6.0"},
-	{"\U0001f40d", "snake", []string{"snake"}, "6.0"},
-	{"\U0001f927", "sneezing face", []string{"sneezing_face"}, "9.0"},
-	{"\U0001f3c2", "snowboarder", []string{"snowboarder"}, "6.0"},
-	{"\u2744\ufe0f", "snowflake", []string{"snowflake"}, ""},
-	{"\u26c4", "snowman without snow", []string{"snowman"}, "5.2"},
-	{"\u2603\ufe0f", "snowman", []string{"snowman_with_snow"}, ""},
-	{"\U0001f9fc", "soap", []string{"soap"}, "11.0"},
-	{"\U0001f62d", "loudly crying face", []string{"sob"}, "6.0"},
-	{"\u26bd", "soccer ball", []string{"soccer"}, "5.2"},
-	{"\U0001f9e6", "socks", []string{"socks"}, "11.0"},
-	{"\U0001f94e", "softball", []string{"softball"}, "11.0"},
-	{"\U0001f1f8\U0001f1e7", "flag: Solomon Islands", []string{"solomon_islands"}, "6.0"},
-	{"\U0001f1f8\U0001f1f4", "flag: Somalia", []string{"somalia"}, "6.0"},
-	{"\U0001f51c", "SOON arrow", []string{"soon"}, "6.0"},
-	{"\U0001f198", "SOS button", []string{"sos"}, "6.0"},
-	{"\U0001f509", "speaker medium volume", []string{"sound"}, "6.0"},
-	{"\U0001f1ff\U0001f1e6", "flag: South Africa", []string{"south_africa"}, "6.0"},
-	{"\U0001f1ec\U0001f1f8", "flag: South Georgia & South Sandwich Islands", []string{"south_georgia_south_sandwich_islands"}, "6.0"},
-	{"\U0001f1f8\U0001f1f8", "flag: South Sudan", []string{"south_sudan"}, "6.0"},
-	{"\U0001f47e", "alien monster", []string{"space_invader"}, "6.0"},
-	{"\u2660\ufe0f", "spade suit", []string{"spades"}, ""},
-	{"\U0001f35d", "spaghetti", []string{"spaghetti"}, "6.0"},
-	{"\u2747\ufe0f", "sparkle", []string{"sparkle"}, ""},
-	{"\U0001f387", "sparkler", []string{"sparkler"}, "6.0"},
-	{"\u2728", "sparkles", []string{"sparkles"}, "6.0"},
-	{"\U0001f496", "sparkling heart", []string{"sparkling_heart"}, "6.0"},
-	{"\U0001f64a", "speak-no-evil monkey", []string{"speak_no_evil"}, "6.0"},
-	{"\U0001f508", "speaker low volume", []string{"speaker"}, "6.0"},
-	{"\U0001f5e3\ufe0f", "speaking head", []string{"speaking_head"}, "7.0"},
-	{"\U0001f4ac", "speech balloon", []string{"speech_balloon"}, "6.0"},
-	{"\U0001f6a4", "speedboat", []string{"speedboat"}, "6.0"},
-	{"\U0001f577\ufe0f", "spider", []string{"spider"}, "7.0"},
-	{"\U0001f578\ufe0f", "spider web", []string{"spider_web"}, "7.0"},
-	{"\U0001f5d3\ufe0f", "spiral calendar", []string{"spiral_calendar"}, "7.0"},
-	{"\U0001f5d2\ufe0f", "spiral notepad", []string{"spiral_notepad"}, "7.0"},
-	{"\U0001f9fd", "sponge", []string{"sponge"}, "11.0"},
-	{"\U0001f944", "spoon", []string{"spoon"}, "9.0"},
-	{"\U0001f991", "squid", []string{"squid"}, "9.0"},
-	{"\U0001f1f1\U0001f1f0", "flag: Sri Lanka", []string{"sri_lanka"}, "6.0"},
-	{"\U0001f1e7\U0001f1f1", "flag: St. Barthรฉlemy", []string{"st_barthelemy"}, "6.0"},
-	{"\U0001f1f8\U0001f1ed", "flag: St. Helena", []string{"st_helena"}, "6.0"},
-	{"\U0001f1f0\U0001f1f3", "flag: St. Kitts & Nevis", []string{"st_kitts_nevis"}, "6.0"},
-	{"\U0001f1f1\U0001f1e8", "flag: St. Lucia", []string{"st_lucia"}, "6.0"},
-	{"\U0001f1f2\U0001f1eb", "flag: St. Martin", []string{"st_martin"}, "11.0"},
-	{"\U0001f1f5\U0001f1f2", "flag: St. Pierre & Miquelon", []string{"st_pierre_miquelon"}, "6.0"},
-	{"\U0001f1fb\U0001f1e8", "flag: St. Vincent & Grenadines", []string{"st_vincent_grenadines"}, "6.0"},
-	{"\U0001f3df\ufe0f", "stadium", []string{"stadium"}, "7.0"},
-	{"\U0001f9cd\u200d\u2642\ufe0f", "man standing", []string{"standing_man"}, "12.0"},
-	{"\U0001f9cd", "person standing", []string{"standing_person"}, "12.0"},
-	{"\U0001f9cd\u200d\u2640\ufe0f", "woman standing", []string{"standing_woman"}, "12.0"},
-	{"\u2b50", "star", []string{"star"}, "5.1"},
-	{"\U0001f31f", "glowing star", []string{"star2"}, "6.0"},
-	{"\u262a\ufe0f", "star and crescent", []string{"star_and_crescent"}, ""},
-	{"\u2721\ufe0f", "star of David", []string{"star_of_david"}, ""},
-	{"\U0001f929", "star-struck", []string{"star_struck"}, "11.0"},
-	{"\U0001f320", "shooting star", []string{"stars"}, "6.0"},
-	{"\U0001f689", "station", []string{"station"}, "6.0"},
-	{"\U0001f5fd", "Statue of Liberty", []string{"statue_of_liberty"}, "6.0"},
-	{"\U0001f682", "locomotive", []string{"steam_locomotive"}, "6.0"},
-	{"\U0001fa7a", "stethoscope", []string{"stethoscope"}, "12.0"},
-	{"\U0001f372", "pot of food", []string{"stew"}, "6.0"},
-	{"\u23f9\ufe0f", "stop button", []string{"stop_button"}, "7.0"},
-	{"\U0001f6d1", "stop sign", []string{"stop_sign"}, "9.0"},
-	{"\u23f1\ufe0f", "stopwatch", []string{"stopwatch"}, "6.0"},
-	{"\U0001f4cf", "straight ruler", []string{"straight_ruler"}, "6.0"},
-	{"\U0001f353", "strawberry", []string{"strawberry"}, "6.0"},
-	{"\U0001f61b", "face with tongue", []string{"stuck_out_tongue"}, "6.1"},
-	{"\U0001f61d", "squinting face with tongue", []string{"stuck_out_tongue_closed_eyes"}, "6.0"},
-	{"\U0001f61c", "winking face with tongue", []string{"stuck_out_tongue_winking_eye"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f393", "student", []string{"student"}, "12.1"},
-	{"\U0001f399\ufe0f", "studio microphone", []string{"studio_microphone"}, "7.0"},
-	{"\U0001f959", "stuffed flatbread", []string{"stuffed_flatbread"}, "9.0"},
-	{"\U0001f1f8\U0001f1e9", "flag: Sudan", []string{"sudan"}, "6.0"},
-	{"\U0001f325\ufe0f", "sun behind large cloud", []string{"sun_behind_large_cloud"}, "7.0"},
-	{"\U0001f326\ufe0f", "sun behind rain cloud", []string{"sun_behind_rain_cloud"}, "7.0"},
-	{"\U0001f324\ufe0f", "sun behind small cloud", []string{"sun_behind_small_cloud"}, "7.0"},
-	{"\U0001f31e", "sun with face", []string{"sun_with_face"}, "6.0"},
-	{"\U0001f33b", "sunflower", []string{"sunflower"}, "6.0"},
-	{"\U0001f60e", "smiling face with sunglasses", []string{"sunglasses"}, "6.0"},
-	{"\u2600\ufe0f", "sun", []string{"sunny"}, ""},
-	{"\U0001f305", "sunrise", []string{"sunrise"}, "6.0"},
-	{"\U0001f304", "sunrise over mountains", []string{"sunrise_over_mountains"}, "6.0"},
-	{"\U0001f9b8", "superhero", []string{"superhero"}, "11.0"},
-	{"\U0001f9b8\u200d\u2642\ufe0f", "man superhero", []string{"superhero_man"}, "11.0"},
-	{"\U0001f9b8\u200d\u2640\ufe0f", "woman superhero", []string{"superhero_woman"}, "11.0"},
-	{"\U0001f9b9", "supervillain", []string{"supervillain"}, "11.0"},
-	{"\U0001f9b9\u200d\u2642\ufe0f", "man supervillain", []string{"supervillain_man"}, "11.0"},
-	{"\U0001f9b9\u200d\u2640\ufe0f", "woman supervillain", []string{"supervillain_woman"}, "11.0"},
-	{"\U0001f3c4", "person surfing", []string{"surfer"}, "6.0"},
-	{"\U0001f3c4\u200d\u2642\ufe0f", "man surfing", []string{"surfing_man"}, "11.0"},
-	{"\U0001f3c4\u200d\u2640\ufe0f", "woman surfing", []string{"surfing_woman"}, "7.0"},
-	{"\U0001f1f8\U0001f1f7", "flag: Suriname", []string{"suriname"}, "6.0"},
-	{"\U0001f363", "sushi", []string{"sushi"}, "6.0"},
-	{"\U0001f69f", "suspension railway", []string{"suspension_railway"}, "6.0"},
-	{"\U0001f1f8\U0001f1ef", "flag: Svalbard & Jan Mayen", []string{"svalbard_jan_mayen"}, "11.0"},
-	{"\U0001f9a2", "swan", []string{"swan"}, "11.0"},
-	{"\U0001f1f8\U0001f1ff", "flag: Eswatini", []string{"swaziland"}, "6.0"},
-	{"\U0001f613", "downcast face with sweat", []string{"sweat"}, "6.0"},
-	{"\U0001f4a6", "sweat droplets", []string{"sweat_drops"}, "6.0"},
-	{"\U0001f605", "grinning face with sweat", []string{"sweat_smile"}, "6.0"},
-	{"\U0001f1f8\U0001f1ea", "flag: Sweden", []string{"sweden"}, "6.0"},
-	{"\U0001f360", "roasted sweet potato", []string{"sweet_potato"}, "6.0"},
-	{"\U0001fa72", "briefs", []string{"swim_brief"}, "12.0"},
-	{"\U0001f3ca", "person swimming", []string{"swimmer"}, "6.0"},
-	{"\U0001f3ca\u200d\u2642\ufe0f", "man swimming", []string{"swimming_man"}, "11.0"},
-	{"\U0001f3ca\u200d\u2640\ufe0f", "woman swimming", []string{"swimming_woman"}, "6.0"},
-	{"\U0001f1e8\U0001f1ed", "flag: Switzerland", []string{"switzerland"}, "6.0"},
-	{"\U0001f523", "input symbols", []string{"symbols"}, "6.0"},
-	{"\U0001f54d", "synagogue", []string{"synagogue"}, "8.0"},
-	{"\U0001f1f8\U0001f1fe", "flag: Syria", []string{"syria"}, "6.0"},
-	{"\U0001f489", "syringe", []string{"syringe"}, "6.0"},
-	{"\U0001f996", "T-Rex", []string{"t-rex"}, "11.0"},
-	{"\U0001f32e", "taco", []string{"taco"}, "8.0"},
-	{"\U0001f389", "party popper", []string{"tada", "hooray"}, "6.0"},
-	{"\U0001f1f9\U0001f1fc", "flag: Taiwan", []string{"taiwan"}, "6.0"},
-	{"\U0001f1f9\U0001f1ef", "flag: Tajikistan", []string{"tajikistan"}, "6.0"},
-	{"\U0001f961", "takeout box", []string{"takeout_box"}, "11.0"},
-	{"\U0001f38b", "tanabata tree", []string{"tanabata_tree"}, "6.0"},
-	{"\U0001f34a", "tangerine", []string{"tangerine", "orange", "mandarin"}, "6.0"},
-	{"\U0001f1f9\U0001f1ff", "flag: Tanzania", []string{"tanzania"}, "6.0"},
-	{"\u2649", "Taurus", []string{"taurus"}, ""},
-	{"\U0001f695", "taxi", []string{"taxi"}, "6.0"},
-	{"\U0001f375", "teacup without handle", []string{"tea"}, "6.0"},
-	{"\U0001f9d1\u200d\U0001f3eb", "teacher", []string{"teacher"}, "12.1"},
-	{"\U0001f9d1\u200d\U0001f4bb", "technologist", []string{"technologist"}, "12.1"},
-	{"\U0001f9f8", "teddy bear", []string{"teddy_bear"}, "11.0"},
-	{"\U0001f4de", "telephone receiver", []string{"telephone_receiver"}, "6.0"},
-	{"\U0001f52d", "telescope", []string{"telescope"}, "6.0"},
-	{"\U0001f3be", "tennis", []string{"tennis"}, "6.0"},
-	{"\u26fa", "tent", []string{"tent"}, "5.2"},
-	{"\U0001f9ea", "test tube", []string{"test_tube"}, "11.0"},
-	{"\U0001f1f9\U0001f1ed", "flag: Thailand", []string{"thailand"}, "6.0"},
-	{"\U0001f321\ufe0f", "thermometer", []string{"thermometer"}, "7.0"},
-	{"\U0001f914", "thinking face", []string{"thinking"}, "8.0"},
-	{"\U0001f4ad", "thought balloon", []string{"thought_balloon"}, "6.0"},
-	{"\U0001f9f5", "thread", []string{"thread"}, "11.0"},
-	{"\U0001f3ab", "ticket", []string{"ticket"}, "6.0"},
-	{"\U0001f39f\ufe0f", "admission tickets", []string{"tickets"}, "7.0"},
-	{"\U0001f42f", "tiger face", []string{"tiger"}, "6.0"},
-	{"\U0001f405", "tiger", []string{"tiger2"}, "6.0"},
-	{"\u23f2\ufe0f", "timer clock", []string{"timer_clock"}, "6.0"},
-	{"\U0001f1f9\U0001f1f1", "flag: Timor-Leste", []string{"timor_leste"}, "6.0"},
-	{"\U0001f481\u200d\u2642\ufe0f", "man tipping hand", []string{"tipping_hand_man", "sassy_man"}, "6.0"},
-	{"\U0001f481", "person tipping hand", []string{"tipping_hand_person", "information_desk_person"}, "6.0"},
-	{"\U0001f481\u200d\u2640\ufe0f", "woman tipping hand", []string{"tipping_hand_woman", "sassy_woman"}, "11.0"},
-	{"\U0001f62b", "tired face", []string{"tired_face"}, "6.0"},
-	{"\u2122\ufe0f", "trade mark", []string{"tm"}, ""},
-	{"\U0001f1f9\U0001f1ec", "flag: Togo", []string{"togo"}, "6.0"},
-	{"\U0001f6bd", "toilet", []string{"toilet"}, "6.0"},
-	{"\U0001f1f9\U0001f1f0", "flag: Tokelau", []string{"tokelau"}, "6.0"},
-	{"\U0001f5fc", "Tokyo tower", []string{"tokyo_tower"}, "6.0"},
-	{"\U0001f345", "tomato", []string{"tomato"}, "6.0"},
-	{"\U0001f1f9\U0001f1f4", "flag: Tonga", []string{"tonga"}, "6.0"},
-	{"\U0001f445", "tongue", []string{"tongue"}, "6.0"},
-	{"\U0001f9f0", "toolbox", []string{"toolbox"}, "11.0"},
-	{"\U0001f9b7", "tooth", []string{"tooth"}, "11.0"},
-	{"\U0001f51d", "TOP arrow", []string{"top"}, "6.0"},
-	{"\U0001f3a9", "top hat", []string{"tophat"}, "6.0"},
-	{"\U0001f32a\ufe0f", "tornado", []string{"tornado"}, "7.0"},
-	{"\U0001f1f9\U0001f1f7", "flag: Turkey", []string{"tr"}, "8.0"},
-	{"\U0001f5b2\ufe0f", "trackball", []string{"trackball"}, "7.0"},
-	{"\U0001f69c", "tractor", []string{"tractor"}, "6.0"},
-	{"\U0001f6a5", "horizontal traffic light", []string{"traffic_light"}, "6.0"},
-	{"\U0001f68b", "tram car", []string{"train"}, "6.0"},
-	{"\U0001f686", "train", []string{"train2"}, "6.0"},
-	{"\U0001f68a", "tram", []string{"tram"}, "6.0"},
-	{"\U0001f6a9", "triangular flag", []string{"triangular_flag_on_post"}, "6.0"},
-	{"\U0001f4d0", "triangular ruler", []string{"triangular_ruler"}, "6.0"},
-	{"\U0001f531", "trident emblem", []string{"trident"}, "6.0"},
-	{"\U0001f1f9\U0001f1f9", "flag: Trinidad & Tobago", []string{"trinidad_tobago"}, "6.0"},
-	{"\U0001f1f9\U0001f1e6", "flag: Tristan da Cunha", []string{"tristan_da_cunha"}, "11.0"},
-	{"\U0001f624", "face with steam from nose", []string{"triumph"}, "6.0"},
-	{"\U0001f68e", "trolleybus", []string{"trolleybus"}, "6.0"},
-	{"\U0001f3c6", "trophy", []string{"trophy"}, "6.0"},
-	{"\U0001f379", "tropical drink", []string{"tropical_drink"}, "6.0"},
-	{"\U0001f420", "tropical fish", []string{"tropical_fish"}, "6.0"},
-	{"\U0001f69a", "delivery truck", []string{"truck"}, "6.0"},
-	{"\U0001f3ba", "trumpet", []string{"trumpet"}, "6.0"},
-	{"\U0001f337", "tulip", []string{"tulip"}, "6.0"},
-	{"\U0001f943", "tumbler glass", []string{"tumbler_glass"}, "9.0"},
-	{"\U0001f1f9\U0001f1f3", "flag: Tunisia", []string{"tunisia"}, "6.0"},
-	{"\U0001f983", "turkey", []string{"turkey"}, "8.0"},
-	{"\U0001f1f9\U0001f1f2", "flag: Turkmenistan", []string{"turkmenistan"}, "6.0"},
-	{"\U0001f1f9\U0001f1e8", "flag: Turks & Caicos Islands", []string{"turks_caicos_islands"}, "6.0"},
-	{"\U0001f422", "turtle", []string{"turtle"}, "6.0"},
-	{"\U0001f1f9\U0001f1fb", "flag: Tuvalu", []string{"tuvalu"}, "6.0"},
-	{"\U0001f4fa", "television", []string{"tv"}, "6.0"},
-	{"\U0001f500", "shuffle tracks button", []string{"twisted_rightwards_arrows"}, "6.0"},
-	{"\U0001f495", "two hearts", []string{"two_hearts"}, "6.0"},
-	{"\U0001f46c", "men holding hands", []string{"two_men_holding_hands"}, "6.0"},
-	{"\U0001f46d", "women holding hands", []string{"two_women_holding_hands"}, "6.0"},
-	{"\U0001f239", "Japanese โ€œdiscountโ€ button", []string{"u5272"}, "6.0"},
-	{"\U0001f234", "Japanese โ€œpassing gradeโ€ button", []string{"u5408"}, "6.0"},
-	{"\U0001f23a", "Japanese โ€œopen for businessโ€ button", []string{"u55b6"}, "6.0"},
-	{"\U0001f22f", "Japanese โ€œreservedโ€ button", []string{"u6307"}, ""},
-	{"\U0001f237\ufe0f", "Japanese โ€œmonthly amountโ€ button", []string{"u6708"}, "6.0"},
-	{"\U0001f236", "Japanese โ€œnot free of chargeโ€ button", []string{"u6709"}, "6.0"},
-	{"\U0001f235", "Japanese โ€œno vacancyโ€ button", []string{"u6e80"}, "6.0"},
-	{"\U0001f21a", "Japanese โ€œfree of chargeโ€ button", []string{"u7121"}, ""},
-	{"\U0001f238", "Japanese โ€œapplicationโ€ button", []string{"u7533"}, "6.0"},
-	{"\U0001f232", "Japanese โ€œprohibitedโ€ button", []string{"u7981"}, "6.0"},
-	{"\U0001f233", "Japanese โ€œvacancyโ€ button", []string{"u7a7a"}, "6.0"},
-	{"\U0001f1fa\U0001f1ec", "flag: Uganda", []string{"uganda"}, "6.0"},
-	{"\U0001f1fa\U0001f1e6", "flag: Ukraine", []string{"ukraine"}, "6.0"},
-	{"\u2614", "umbrella with rain drops", []string{"umbrella"}, "4.0"},
-	{"\U0001f612", "unamused face", []string{"unamused"}, "6.0"},
-	{"\U0001f51e", "no one under eighteen", []string{"underage"}, "6.0"},
-	{"\U0001f984", "unicorn", []string{"unicorn"}, "8.0"},
-	{"\U0001f1e6\U0001f1ea", "flag: United Arab Emirates", []string{"united_arab_emirates"}, "6.0"},
-	{"\U0001f1fa\U0001f1f3", "flag: United Nations", []string{"united_nations"}, "11.0"},
-	{"\U0001f513", "unlocked", []string{"unlock"}, "6.0"},
-	{"\U0001f199", "UP! button", []string{"up"}, "6.0"},
-	{"\U0001f643", "upside-down face", []string{"upside_down_face"}, "8.0"},
-	{"\U0001f1fa\U0001f1fe", "flag: Uruguay", []string{"uruguay"}, "6.0"},
-	{"\U0001f1fa\U0001f1f8", "flag: United States", []string{"us"}, "6.0"},
-	{"\U0001f1fa\U0001f1f2", "flag: U.S. Outlying Islands", []string{"us_outlying_islands"}, "11.0"},
-	{"\U0001f1fb\U0001f1ee", "flag: U.S. Virgin Islands", []string{"us_virgin_islands"}, "6.0"},
-	{"\U0001f1fa\U0001f1ff", "flag: Uzbekistan", []string{"uzbekistan"}, "6.0"},
-	{"\u270c\ufe0f", "victory hand", []string{"v"}, ""},
-	{"\U0001f9db", "vampire", []string{"vampire"}, "11.0"},
-	{"\U0001f9db\u200d\u2642\ufe0f", "man vampire", []string{"vampire_man"}, "11.0"},
-	{"\U0001f9db\u200d\u2640\ufe0f", "woman vampire", []string{"vampire_woman"}, "11.0"},
-	{"\U0001f1fb\U0001f1fa", "flag: Vanuatu", []string{"vanuatu"}, "6.0"},
-	{"\U0001f1fb\U0001f1e6", "flag: Vatican City", []string{"vatican_city"}, "6.0"},
-	{"\U0001f1fb\U0001f1ea", "flag: Venezuela", []string{"venezuela"}, "6.0"},
-	{"\U0001f6a6", "vertical traffic light", []string{"vertical_traffic_light"}, "6.0"},
-	{"\U0001f4fc", "videocassette", []string{"vhs"}, "6.0"},
-	{"\U0001f4f3", "vibration mode", []string{"vibration_mode"}, "6.0"},
-	{"\U0001f4f9", "video camera", []string{"video_camera"}, "6.0"},
-	{"\U0001f3ae", "video game", []string{"video_game"}, "6.0"},
-	{"\U0001f1fb\U0001f1f3", "flag: Vietnam", []string{"vietnam"}, "6.0"},
-	{"\U0001f3bb", "violin", []string{"violin"}, "6.0"},
-	{"\u264d", "Virgo", []string{"virgo"}, ""},
-	{"\U0001f30b", "volcano", []string{"volcano"}, "6.0"},
-	{"\U0001f3d0", "volleyball", []string{"volleyball"}, "8.0"},
-	{"\U0001f92e", "face vomiting", []string{"vomiting_face"}, "11.0"},
-	{"\U0001f19a", "VS button", []string{"vs"}, "6.0"},
-	{"\U0001f596", "vulcan salute", []string{"vulcan_salute"}, "7.0"},
-	{"\U0001f9c7", "waffle", []string{"waffle"}, "12.0"},
-	{"\U0001f3f4\U000e0067\U000e0062\U000e0077\U000e006c\U000e0073\U000e007f", "flag: Wales", []string{"wales"}, "11.0"},
-	{"\U0001f6b6", "person walking", []string{"walking"}, "6.0"},
-	{"\U0001f6b6\u200d\u2642\ufe0f", "man walking", []string{"walking_man"}, "11.0"},
-	{"\U0001f6b6\u200d\u2640\ufe0f", "woman walking", []string{"walking_woman"}, "6.0"},
-	{"\U0001f1fc\U0001f1eb", "flag: Wallis & Futuna", []string{"wallis_futuna"}, "6.0"},
-	{"\U0001f318", "waning crescent moon", []string{"waning_crescent_moon"}, "6.0"},
-	{"\U0001f316", "waning gibbous moon", []string{"waning_gibbous_moon"}, "6.0"},
-	{"\u26a0\ufe0f", "warning", []string{"warning"}, "4.0"},
-	{"\U0001f5d1\ufe0f", "wastebasket", []string{"wastebasket"}, "7.0"},
-	{"\u231a", "watch", []string{"watch"}, ""},
-	{"\U0001f403", "water buffalo", []string{"water_buffalo"}, "6.0"},
-	{"\U0001f93d", "person playing water polo", []string{"water_polo"}, "11.0"},
-	{"\U0001f349", "watermelon", []string{"watermelon"}, "6.0"},
-	{"\U0001f44b", "waving hand", []string{"wave"}, "6.0"},
-	{"\u3030\ufe0f", "wavy dash", []string{"wavy_dash"}, ""},
-	{"\U0001f312", "waxing crescent moon", []string{"waxing_crescent_moon"}, "6.0"},
-	{"\U0001f6be", "water closet", []string{"wc"}, "6.0"},
-	{"\U0001f629", "weary face", []string{"weary"}, "6.0"},
-	{"\U0001f492", "wedding", []string{"wedding"}, "6.0"},
-	{"\U0001f3cb\ufe0f", "person lifting weights", []string{"weight_lifting"}, "7.0"},
-	{"\U0001f3cb\ufe0f\u200d\u2642\ufe0f", "man lifting weights", []string{"weight_lifting_man"}, "11.0"},
-	{"\U0001f3cb\ufe0f\u200d\u2640\ufe0f", "woman lifting weights", []string{"weight_lifting_woman"}, "6.0"},
-	{"\U0001f1ea\U0001f1ed", "flag: Western Sahara", []string{"western_sahara"}, "6.0"},
-	{"\U0001f433", "spouting whale", []string{"whale"}, "6.0"},
-	{"\U0001f40b", "whale", []string{"whale2"}, "6.0"},
-	{"\u2638\ufe0f", "wheel of dharma", []string{"wheel_of_dharma"}, ""},
-	{"\u267f", "wheelchair symbol", []string{"wheelchair"}, "4.1"},
-	{"\u2705", "check mark button", []string{"white_check_mark"}, "6.0"},
-	{"\u26aa", "white circle", []string{"white_circle"}, "4.1"},
-	{"\U0001f3f3\ufe0f", "white flag", []string{"white_flag"}, "7.0"},
-	{"\U0001f4ae", "white flower", []string{"white_flower"}, "6.0"},
-	{"\U0001f468\u200d\U0001f9b3", "man: white hair", []string{"white_haired_man"}, "11.0"},
-	{"\U0001f469\u200d\U0001f9b3", "woman: white hair", []string{"white_haired_woman"}, "11.0"},
-	{"\U0001f90d", "white heart", []string{"white_heart"}, "12.0"},
-	{"\u2b1c", "white large square", []string{"white_large_square"}, "5.1"},
-	{"\u25fd", "white medium-small square", []string{"white_medium_small_square"}, "3.2"},
-	{"\u25fb\ufe0f", "white medium square", []string{"white_medium_square"}, "3.2"},
-	{"\u25ab\ufe0f", "white small square", []string{"white_small_square"}, ""},
-	{"\U0001f533", "white square button", []string{"white_square_button"}, "6.0"},
-	{"\U0001f940", "wilted flower", []string{"wilted_flower"}, "9.0"},
-	{"\U0001f390", "wind chime", []string{"wind_chime"}, "6.0"},
-	{"\U0001f32c\ufe0f", "wind face", []string{"wind_face"}, "7.0"},
-	{"\U0001f377", "wine glass", []string{"wine_glass"}, "6.0"},
-	{"\U0001f609", "winking face", []string{"wink"}, "6.0"},
-	{"\U0001f43a", "wolf", []string{"wolf"}, "6.0"},
-	{"\U0001f469", "woman", []string{"woman"}, "6.0"},
-	{"\U0001f469\u200d\U0001f3a8", "woman artist", []string{"woman_artist"}, ""},
-	{"\U0001f469\u200d\U0001f680", "woman astronaut", []string{"woman_astronaut"}, ""},
-	{"\U0001f938\u200d\u2640\ufe0f", "woman cartwheeling", []string{"woman_cartwheeling"}, ""},
-	{"\U0001f469\u200d\U0001f373", "woman cook", []string{"woman_cook"}, ""},
-	{"\U0001f483", "woman dancing", []string{"woman_dancing", "dancer"}, "6.0"},
-	{"\U0001f926\u200d\u2640\ufe0f", "woman facepalming", []string{"woman_facepalming"}, "9.0"},
-	{"\U0001f469\u200d\U0001f3ed", "woman factory worker", []string{"woman_factory_worker"}, ""},
-	{"\U0001f469\u200d\U0001f33e", "woman farmer", []string{"woman_farmer"}, ""},
-	{"\U0001f469\u200d\U0001f692", "woman firefighter", []string{"woman_firefighter"}, ""},
-	{"\U0001f469\u200d\u2695\ufe0f", "woman health worker", []string{"woman_health_worker"}, ""},
-	{"\U0001f469\u200d\U0001f9bd", "woman in manual wheelchair", []string{"woman_in_manual_wheelchair"}, "12.0"},
-	{"\U0001f469\u200d\U0001f9bc", "woman in motorized wheelchair", []string{"woman_in_motorized_wheelchair"}, "12.0"},
-	{"\U0001f469\u200d\u2696\ufe0f", "woman judge", []string{"woman_judge"}, ""},
-	{"\U0001f939\u200d\u2640\ufe0f", "woman juggling", []string{"woman_juggling"}, "9.0"},
-	{"\U0001f469\u200d\U0001f527", "woman mechanic", []string{"woman_mechanic"}, ""},
-	{"\U0001f469\u200d\U0001f4bc", "woman office worker", []string{"woman_office_worker"}, ""},
-	{"\U0001f469\u200d\u2708\ufe0f", "woman pilot", []string{"woman_pilot"}, ""},
-	{"\U0001f93e\u200d\u2640\ufe0f", "woman playing handball", []string{"woman_playing_handball"}, "9.0"},
-	{"\U0001f93d\u200d\u2640\ufe0f", "woman playing water polo", []string{"woman_playing_water_polo"}, "9.0"},
-	{"\U0001f469\u200d\U0001f52c", "woman scientist", []string{"woman_scientist"}, ""},
-	{"\U0001f937\u200d\u2640\ufe0f", "woman shrugging", []string{"woman_shrugging"}, "9.0"},
-	{"\U0001f469\u200d\U0001f3a4", "woman singer", []string{"woman_singer"}, ""},
-	{"\U0001f469\u200d\U0001f393", "woman student", []string{"woman_student"}, ""},
-	{"\U0001f469\u200d\U0001f3eb", "woman teacher", []string{"woman_teacher"}, ""},
-	{"\U0001f469\u200d\U0001f4bb", "woman technologist", []string{"woman_technologist"}, ""},
-	{"\U0001f9d5", "woman with headscarf", []string{"woman_with_headscarf"}, "11.0"},
-	{"\U0001f469\u200d\U0001f9af", "woman with white cane", []string{"woman_with_probing_cane"}, "12.0"},
-	{"\U0001f473\u200d\u2640\ufe0f", "woman wearing turban", []string{"woman_with_turban"}, "6.0"},
-	{"\U0001f45a", "womanโ€™s clothes", []string{"womans_clothes"}, "6.0"},
-	{"\U0001f452", "womanโ€™s hat", []string{"womans_hat"}, "6.0"},
-	{"\U0001f93c\u200d\u2640\ufe0f", "women wrestling", []string{"women_wrestling"}, "9.0"},
-	{"\U0001f6ba", "womenโ€™s room", []string{"womens"}, "6.0"},
-	{"\U0001f974", "woozy face", []string{"woozy_face"}, "11.0"},
-	{"\U0001f5fa\ufe0f", "world map", []string{"world_map"}, "7.0"},
-	{"\U0001f61f", "worried face", []string{"worried"}, "6.1"},
-	{"\U0001f527", "wrench", []string{"wrench"}, "6.0"},
-	{"\U0001f93c", "people wrestling", []string{"wrestling"}, "11.0"},
-	{"\u270d\ufe0f", "writing hand", []string{"writing_hand"}, ""},
-	{"\u274c", "cross mark", []string{"x"}, "6.0"},
-	{"\U0001f9f6", "yarn", []string{"yarn"}, "11.0"},
-	{"\U0001f971", "yawning face", []string{"yawning_face"}, "12.0"},
-	{"\U0001f7e1", "yellow circle", []string{"yellow_circle"}, "12.0"},
-	{"\U0001f49b", "yellow heart", []string{"yellow_heart"}, "6.0"},
-	{"\U0001f7e8", "yellow square", []string{"yellow_square"}, "12.0"},
-	{"\U0001f1fe\U0001f1ea", "flag: Yemen", []string{"yemen"}, "6.0"},
-	{"\U0001f4b4", "yen banknote", []string{"yen"}, "6.0"},
-	{"\u262f\ufe0f", "yin yang", []string{"yin_yang"}, ""},
-	{"\U0001fa80", "yo-yo", []string{"yo_yo"}, "12.0"},
-	{"\U0001f60b", "face savoring food", []string{"yum"}, "6.0"},
-	{"\U0001f1ff\U0001f1f2", "flag: Zambia", []string{"zambia"}, "6.0"},
-	{"\U0001f92a", "zany face", []string{"zany_face"}, "11.0"},
-	{"\u26a1", "high voltage", []string{"zap"}, "4.0"},
-	{"\U0001f993", "zebra", []string{"zebra"}, "11.0"},
-	{"\U0001f1ff\U0001f1fc", "flag: Zimbabwe", []string{"zimbabwe"}, "6.0"},
-	{"\U0001f910", "zipper-mouth face", []string{"zipper_mouth_face"}, "8.0"},
-	{"\U0001f9df", "zombie", []string{"zombie"}, "11.0"},
-	{"\U0001f9df\u200d\u2642\ufe0f", "man zombie", []string{"zombie_man"}, "11.0"},
-	{"\U0001f9df\u200d\u2640\ufe0f", "woman zombie", []string{"zombie_woman"}, "11.0"},
-	{"\U0001f4a4", "zzz", []string{"zzz"}, "6.0"},
+	{"\U0001f44d", "thumbs up", []string{"+1", "thumbsup"}, "6.0", true},
+	{"\U0001f44e", "thumbs down", []string{"-1", "thumbsdown"}, "6.0", true},
+	{"\U0001f4af", "hundred points", []string{"100"}, "6.0", false},
+	{"\U0001f522", "input numbers", []string{"1234"}, "6.0", false},
+	{"\U0001f947", "1st place medal", []string{"1st_place_medal"}, "9.0", false},
+	{"\U0001f948", "2nd place medal", []string{"2nd_place_medal"}, "9.0", false},
+	{"\U0001f949", "3rd place medal", []string{"3rd_place_medal"}, "9.0", false},
+	{"\U0001f3b1", "pool 8 ball", []string{"8ball"}, "6.0", false},
+	{"\U0001f170\ufe0f", "A button (blood type)", []string{"a"}, "6.0", false},
+	{"\U0001f18e", "AB button (blood type)", []string{"ab"}, "6.0", false},
+	{"\U0001f9ee", "abacus", []string{"abacus"}, "11.0", false},
+	{"\U0001f524", "input latin letters", []string{"abc"}, "6.0", false},
+	{"\U0001f521", "input latin lowercase", []string{"abcd"}, "6.0", false},
+	{"\U0001f251", "Japanese โ€œacceptableโ€ button", []string{"accept"}, "6.0", false},
+	{"\U0001fa79", "adhesive bandage", []string{"adhesive_bandage"}, "12.0", false},
+	{"\U0001f9d1", "person", []string{"adult"}, "11.0", true},
+	{"\U0001f6a1", "aerial tramway", []string{"aerial_tramway"}, "6.0", false},
+	{"\U0001f1e6\U0001f1eb", "flag: Afghanistan", []string{"afghanistan"}, "6.0", false},
+	{"\u2708\ufe0f", "airplane", []string{"airplane"}, "", false},
+	{"\U0001f1e6\U0001f1fd", "flag: ร…land Islands", []string{"aland_islands"}, "6.0", false},
+	{"\u23f0", "alarm clock", []string{"alarm_clock"}, "6.0", false},
+	{"\U0001f1e6\U0001f1f1", "flag: Albania", []string{"albania"}, "6.0", false},
+	{"\u2697\ufe0f", "alembic", []string{"alembic"}, "4.1", false},
+	{"\U0001f1e9\U0001f1ff", "flag: Algeria", []string{"algeria"}, "6.0", false},
+	{"\U0001f47d", "alien", []string{"alien"}, "6.0", false},
+	{"\U0001f691", "ambulance", []string{"ambulance"}, "6.0", false},
+	{"\U0001f1e6\U0001f1f8", "flag: American Samoa", []string{"american_samoa"}, "6.0", false},
+	{"\U0001f3fa", "amphora", []string{"amphora"}, "8.0", false},
+	{"\u2693", "anchor", []string{"anchor"}, "4.1", false},
+	{"\U0001f1e6\U0001f1e9", "flag: Andorra", []string{"andorra"}, "6.0", false},
+	{"\U0001f47c", "baby angel", []string{"angel"}, "6.0", true},
+	{"\U0001f4a2", "anger symbol", []string{"anger"}, "6.0", false},
+	{"\U0001f1e6\U0001f1f4", "flag: Angola", []string{"angola"}, "6.0", false},
+	{"\U0001f620", "angry face", []string{"angry"}, "6.0", false},
+	{"\U0001f1e6\U0001f1ee", "flag: Anguilla", []string{"anguilla"}, "6.0", false},
+	{"\U0001f627", "anguished face", []string{"anguished"}, "6.1", false},
+	{"\U0001f41c", "ant", []string{"ant"}, "6.0", false},
+	{"\U0001f1e6\U0001f1f6", "flag: Antarctica", []string{"antarctica"}, "6.0", false},
+	{"\U0001f1e6\U0001f1ec", "flag: Antigua & Barbuda", []string{"antigua_barbuda"}, "6.0", false},
+	{"\U0001f34e", "red apple", []string{"apple"}, "6.0", false},
+	{"\u2652", "Aquarius", []string{"aquarius"}, "", false},
+	{"\U0001f1e6\U0001f1f7", "flag: Argentina", []string{"argentina"}, "6.0", false},
+	{"\u2648", "Aries", []string{"aries"}, "", false},
+	{"\U0001f1e6\U0001f1f2", "flag: Armenia", []string{"armenia"}, "6.0", false},
+	{"\u25c0\ufe0f", "reverse button", []string{"arrow_backward"}, "", false},
+	{"\u23ec", "fast down button", []string{"arrow_double_down"}, "6.0", false},
+	{"\u23eb", "fast up button", []string{"arrow_double_up"}, "6.0", false},
+	{"\u2b07\ufe0f", "down arrow", []string{"arrow_down"}, "4.0", false},
+	{"\U0001f53d", "downwards button", []string{"arrow_down_small"}, "6.0", false},
+	{"\u25b6\ufe0f", "play button", []string{"arrow_forward"}, "", false},
+	{"\u2935\ufe0f", "right arrow curving down", []string{"arrow_heading_down"}, "", false},
+	{"\u2934\ufe0f", "right arrow curving up", []string{"arrow_heading_up"}, "", false},
+	{"\u2b05\ufe0f", "left arrow", []string{"arrow_left"}, "4.0", false},
+	{"\u2199\ufe0f", "down-left arrow", []string{"arrow_lower_left"}, "", false},
+	{"\u2198\ufe0f", "down-right arrow", []string{"arrow_lower_right"}, "", false},
+	{"\u27a1\ufe0f", "right arrow", []string{"arrow_right"}, "", false},
+	{"\u21aa\ufe0f", "left arrow curving right", []string{"arrow_right_hook"}, "", false},
+	{"\u2b06\ufe0f", "up arrow", []string{"arrow_up"}, "4.0", false},
+	{"\u2195\ufe0f", "up-down arrow", []string{"arrow_up_down"}, "", false},
+	{"\U0001f53c", "upwards button", []string{"arrow_up_small"}, "6.0", false},
+	{"\u2196\ufe0f", "up-left arrow", []string{"arrow_upper_left"}, "", false},
+	{"\u2197\ufe0f", "up-right arrow", []string{"arrow_upper_right"}, "", false},
+	{"\U0001f503", "clockwise vertical arrows", []string{"arrows_clockwise"}, "6.0", false},
+	{"\U0001f504", "counterclockwise arrows button", []string{"arrows_counterclockwise"}, "6.0", false},
+	{"\U0001f3a8", "artist palette", []string{"art"}, "6.0", false},
+	{"\U0001f69b", "articulated lorry", []string{"articulated_lorry"}, "6.0", false},
+	{"\U0001f6f0\ufe0f", "satellite", []string{"artificial_satellite"}, "7.0", false},
+	{"\U0001f9d1\u200d\U0001f3a8", "artist", []string{"artist"}, "12.1", true},
+	{"\U0001f1e6\U0001f1fc", "flag: Aruba", []string{"aruba"}, "6.0", false},
+	{"\U0001f1e6\U0001f1e8", "flag: Ascension Island", []string{"ascension_island"}, "11.0", false},
+	{"*\ufe0f\u20e3", "keycap: *", []string{"asterisk"}, "", false},
+	{"\U0001f632", "astonished face", []string{"astonished"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f680", "astronaut", []string{"astronaut"}, "12.1", true},
+	{"\U0001f45f", "running shoe", []string{"athletic_shoe"}, "6.0", false},
+	{"\U0001f3e7", "ATM sign", []string{"atm"}, "6.0", false},
+	{"\u269b\ufe0f", "atom symbol", []string{"atom_symbol"}, "4.1", false},
+	{"\U0001f1e6\U0001f1fa", "flag: Australia", []string{"australia"}, "6.0", false},
+	{"\U0001f1e6\U0001f1f9", "flag: Austria", []string{"austria"}, "6.0", false},
+	{"\U0001f6fa", "auto rickshaw", []string{"auto_rickshaw"}, "12.0", false},
+	{"\U0001f951", "avocado", []string{"avocado"}, "9.0", false},
+	{"\U0001fa93", "axe", []string{"axe"}, "12.0", false},
+	{"\U0001f1e6\U0001f1ff", "flag: Azerbaijan", []string{"azerbaijan"}, "6.0", false},
+	{"\U0001f171\ufe0f", "B button (blood type)", []string{"b"}, "6.0", false},
+	{"\U0001f476", "baby", []string{"baby"}, "6.0", true},
+	{"\U0001f37c", "baby bottle", []string{"baby_bottle"}, "6.0", false},
+	{"\U0001f424", "baby chick", []string{"baby_chick"}, "6.0", false},
+	{"\U0001f6bc", "baby symbol", []string{"baby_symbol"}, "6.0", false},
+	{"\U0001f519", "BACK arrow", []string{"back"}, "6.0", false},
+	{"\U0001f953", "bacon", []string{"bacon"}, "9.0", false},
+	{"\U0001f9a1", "badger", []string{"badger"}, "11.0", false},
+	{"\U0001f3f8", "badminton", []string{"badminton"}, "8.0", false},
+	{"\U0001f96f", "bagel", []string{"bagel"}, "11.0", false},
+	{"\U0001f6c4", "baggage claim", []string{"baggage_claim"}, "6.0", false},
+	{"\U0001f956", "baguette bread", []string{"baguette_bread"}, "9.0", false},
+	{"\U0001f1e7\U0001f1f8", "flag: Bahamas", []string{"bahamas"}, "6.0", false},
+	{"\U0001f1e7\U0001f1ed", "flag: Bahrain", []string{"bahrain"}, "6.0", false},
+	{"\u2696\ufe0f", "balance scale", []string{"balance_scale"}, "4.1", false},
+	{"\U0001f468\u200d\U0001f9b2", "man: bald", []string{"bald_man"}, "11.0", true},
+	{"\U0001f469\u200d\U0001f9b2", "woman: bald", []string{"bald_woman"}, "11.0", true},
+	{"\U0001fa70", "ballet shoes", []string{"ballet_shoes"}, "12.0", false},
+	{"\U0001f388", "balloon", []string{"balloon"}, "6.0", false},
+	{"\U0001f5f3\ufe0f", "ballot box with ballot", []string{"ballot_box"}, "7.0", false},
+	{"\u2611\ufe0f", "check box with check", []string{"ballot_box_with_check"}, "", false},
+	{"\U0001f38d", "pine decoration", []string{"bamboo"}, "6.0", false},
+	{"\U0001f34c", "banana", []string{"banana"}, "6.0", false},
+	{"\u203c\ufe0f", "double exclamation mark", []string{"bangbang"}, "", false},
+	{"\U0001f1e7\U0001f1e9", "flag: Bangladesh", []string{"bangladesh"}, "6.0", false},
+	{"\U0001fa95", "banjo", []string{"banjo"}, "12.0", false},
+	{"\U0001f3e6", "bank", []string{"bank"}, "6.0", false},
+	{"\U0001f4ca", "bar chart", []string{"bar_chart"}, "6.0", false},
+	{"\U0001f1e7\U0001f1e7", "flag: Barbados", []string{"barbados"}, "6.0", false},
+	{"\U0001f488", "barber pole", []string{"barber"}, "6.0", false},
+	{"\u26be", "baseball", []string{"baseball"}, "5.2", false},
+	{"\U0001f9fa", "basket", []string{"basket"}, "11.0", false},
+	{"\U0001f3c0", "basketball", []string{"basketball"}, "6.0", false},
+	{"\U0001f987", "bat", []string{"bat"}, "9.0", false},
+	{"\U0001f6c0", "person taking bath", []string{"bath"}, "6.0", true},
+	{"\U0001f6c1", "bathtub", []string{"bathtub"}, "6.0", false},
+	{"\U0001f50b", "battery", []string{"battery"}, "6.0", false},
+	{"\U0001f3d6\ufe0f", "beach with umbrella", []string{"beach_umbrella"}, "7.0", false},
+	{"\U0001f43b", "bear", []string{"bear"}, "6.0", false},
+	{"\U0001f9d4", "man: beard", []string{"bearded_person"}, "11.0", true},
+	{"\U0001f6cf\ufe0f", "bed", []string{"bed"}, "7.0", false},
+	{"\U0001f41d", "honeybee", []string{"bee", "honeybee"}, "6.0", false},
+	{"\U0001f37a", "beer mug", []string{"beer"}, "6.0", false},
+	{"\U0001f37b", "clinking beer mugs", []string{"beers"}, "6.0", false},
+	{"\U0001f530", "Japanese symbol for beginner", []string{"beginner"}, "6.0", false},
+	{"\U0001f1e7\U0001f1fe", "flag: Belarus", []string{"belarus"}, "6.0", false},
+	{"\U0001f1e7\U0001f1ea", "flag: Belgium", []string{"belgium"}, "6.0", false},
+	{"\U0001f1e7\U0001f1ff", "flag: Belize", []string{"belize"}, "6.0", false},
+	{"\U0001f514", "bell", []string{"bell"}, "6.0", false},
+	{"\U0001f6ce\ufe0f", "bellhop bell", []string{"bellhop_bell"}, "7.0", false},
+	{"\U0001f1e7\U0001f1ef", "flag: Benin", []string{"benin"}, "6.0", false},
+	{"\U0001f371", "bento box", []string{"bento"}, "6.0", false},
+	{"\U0001f1e7\U0001f1f2", "flag: Bermuda", []string{"bermuda"}, "6.0", false},
+	{"\U0001f9c3", "beverage box", []string{"beverage_box"}, "12.0", false},
+	{"\U0001f1e7\U0001f1f9", "flag: Bhutan", []string{"bhutan"}, "6.0", false},
+	{"\U0001f6b4", "person biking", []string{"bicyclist"}, "6.0", true},
+	{"\U0001f6b2", "bicycle", []string{"bike"}, "6.0", false},
+	{"\U0001f6b4\u200d\u2642\ufe0f", "man biking", []string{"biking_man"}, "11.0", true},
+	{"\U0001f6b4\u200d\u2640\ufe0f", "woman biking", []string{"biking_woman"}, "6.0", true},
+	{"\U0001f459", "bikini", []string{"bikini"}, "6.0", false},
+	{"\U0001f9e2", "billed cap", []string{"billed_cap"}, "11.0", false},
+	{"\u2623\ufe0f", "biohazard", []string{"biohazard"}, "", false},
+	{"\U0001f426", "bird", []string{"bird"}, "6.0", false},
+	{"\U0001f382", "birthday cake", []string{"birthday"}, "6.0", false},
+	{"\u26ab", "black circle", []string{"black_circle"}, "4.1", false},
+	{"\U0001f3f4", "black flag", []string{"black_flag"}, "7.0", false},
+	{"\U0001f5a4", "black heart", []string{"black_heart"}, "9.0", false},
+	{"\U0001f0cf", "joker", []string{"black_joker"}, "6.0", false},
+	{"\u2b1b", "black large square", []string{"black_large_square"}, "5.1", false},
+	{"\u25fe", "black medium-small square", []string{"black_medium_small_square"}, "3.2", false},
+	{"\u25fc\ufe0f", "black medium square", []string{"black_medium_square"}, "3.2", false},
+	{"\u2712\ufe0f", "black nib", []string{"black_nib"}, "", false},
+	{"\u25aa\ufe0f", "black small square", []string{"black_small_square"}, "", false},
+	{"\U0001f532", "black square button", []string{"black_square_button"}, "6.0", false},
+	{"\U0001f471\u200d\u2642\ufe0f", "man: blond hair", []string{"blond_haired_man"}, "11.0", true},
+	{"\U0001f471", "person: blond hair", []string{"blond_haired_person"}, "6.0", true},
+	{"\U0001f471\u200d\u2640\ufe0f", "woman: blond hair", []string{"blond_haired_woman", "blonde_woman"}, "6.0", true},
+	{"\U0001f33c", "blossom", []string{"blossom"}, "6.0", false},
+	{"\U0001f421", "blowfish", []string{"blowfish"}, "6.0", false},
+	{"\U0001f4d8", "blue book", []string{"blue_book"}, "6.0", false},
+	{"\U0001f699", "sport utility vehicle", []string{"blue_car"}, "6.0", false},
+	{"\U0001f499", "blue heart", []string{"blue_heart"}, "6.0", false},
+	{"\U0001f7e6", "blue square", []string{"blue_square"}, "12.0", false},
+	{"\U0001f60a", "smiling face with smiling eyes", []string{"blush"}, "6.0", false},
+	{"\U0001f417", "boar", []string{"boar"}, "6.0", false},
+	{"\u26f5", "sailboat", []string{"boat", "sailboat"}, "5.2", false},
+	{"\U0001f1e7\U0001f1f4", "flag: Bolivia", []string{"bolivia"}, "6.0", false},
+	{"\U0001f4a3", "bomb", []string{"bomb"}, "6.0", false},
+	{"\U0001f9b4", "bone", []string{"bone"}, "11.0", false},
+	{"\U0001f4d6", "open book", []string{"book", "open_book"}, "6.0", false},
+	{"\U0001f516", "bookmark", []string{"bookmark"}, "6.0", false},
+	{"\U0001f4d1", "bookmark tabs", []string{"bookmark_tabs"}, "6.0", false},
+	{"\U0001f4da", "books", []string{"books"}, "6.0", false},
+	{"\U0001f4a5", "collision", []string{"boom", "collision"}, "6.0", false},
+	{"\U0001f462", "womanโ€™s boot", []string{"boot"}, "6.0", false},
+	{"\U0001f1e7\U0001f1e6", "flag: Bosnia & Herzegovina", []string{"bosnia_herzegovina"}, "6.0", false},
+	{"\U0001f1e7\U0001f1fc", "flag: Botswana", []string{"botswana"}, "6.0", false},
+	{"\u26f9\ufe0f\u200d\u2642\ufe0f", "man bouncing ball", []string{"bouncing_ball_man", "basketball_man"}, "11.0", true},
+	{"\u26f9\ufe0f", "person bouncing ball", []string{"bouncing_ball_person"}, "5.2", true},
+	{"\u26f9\ufe0f\u200d\u2640\ufe0f", "woman bouncing ball", []string{"bouncing_ball_woman", "basketball_woman"}, "7.0", true},
+	{"\U0001f490", "bouquet", []string{"bouquet"}, "6.0", false},
+	{"\U0001f1e7\U0001f1fb", "flag: Bouvet Island", []string{"bouvet_island"}, "11.0", false},
+	{"\U0001f647", "person bowing", []string{"bow"}, "6.0", true},
+	{"\U0001f3f9", "bow and arrow", []string{"bow_and_arrow"}, "8.0", false},
+	{"\U0001f647\u200d\u2642\ufe0f", "man bowing", []string{"bowing_man"}, "11.0", true},
+	{"\U0001f647\u200d\u2640\ufe0f", "woman bowing", []string{"bowing_woman"}, "6.0", true},
+	{"\U0001f963", "bowl with spoon", []string{"bowl_with_spoon"}, "11.0", false},
+	{"\U0001f3b3", "bowling", []string{"bowling"}, "6.0", false},
+	{"\U0001f94a", "boxing glove", []string{"boxing_glove"}, "9.0", false},
+	{"\U0001f466", "boy", []string{"boy"}, "6.0", true},
+	{"\U0001f9e0", "brain", []string{"brain"}, "11.0", false},
+	{"\U0001f1e7\U0001f1f7", "flag: Brazil", []string{"brazil"}, "6.0", false},
+	{"\U0001f35e", "bread", []string{"bread"}, "6.0", false},
+	{"\U0001f931", "breast-feeding", []string{"breast_feeding"}, "11.0", true},
+	{"\U0001f9f1", "brick", []string{"bricks"}, "11.0", false},
+	{"\U0001f309", "bridge at night", []string{"bridge_at_night"}, "6.0", false},
+	{"\U0001f4bc", "briefcase", []string{"briefcase"}, "6.0", false},
+	{"\U0001f1ee\U0001f1f4", "flag: British Indian Ocean Territory", []string{"british_indian_ocean_territory"}, "6.0", false},
+	{"\U0001f1fb\U0001f1ec", "flag: British Virgin Islands", []string{"british_virgin_islands"}, "6.0", false},
+	{"\U0001f966", "broccoli", []string{"broccoli"}, "11.0", false},
+	{"\U0001f494", "broken heart", []string{"broken_heart"}, "6.0", false},
+	{"\U0001f9f9", "broom", []string{"broom"}, "11.0", false},
+	{"\U0001f7e4", "brown circle", []string{"brown_circle"}, "12.0", false},
+	{"\U0001f90e", "brown heart", []string{"brown_heart"}, "12.0", false},
+	{"\U0001f7eb", "brown square", []string{"brown_square"}, "12.0", false},
+	{"\U0001f1e7\U0001f1f3", "flag: Brunei", []string{"brunei"}, "6.0", false},
+	{"\U0001f41b", "bug", []string{"bug"}, "6.0", false},
+	{"\U0001f3d7\ufe0f", "building construction", []string{"building_construction"}, "7.0", false},
+	{"\U0001f4a1", "light bulb", []string{"bulb"}, "6.0", false},
+	{"\U0001f1e7\U0001f1ec", "flag: Bulgaria", []string{"bulgaria"}, "6.0", false},
+	{"\U0001f685", "bullet train", []string{"bullettrain_front"}, "6.0", false},
+	{"\U0001f684", "high-speed train", []string{"bullettrain_side"}, "6.0", false},
+	{"\U0001f1e7\U0001f1eb", "flag: Burkina Faso", []string{"burkina_faso"}, "6.0", false},
+	{"\U0001f32f", "burrito", []string{"burrito"}, "8.0", false},
+	{"\U0001f1e7\U0001f1ee", "flag: Burundi", []string{"burundi"}, "6.0", false},
+	{"\U0001f68c", "bus", []string{"bus"}, "6.0", false},
+	{"\U0001f574\ufe0f", "person in suit levitating", []string{"business_suit_levitating"}, "7.0", true},
+	{"\U0001f68f", "bus stop", []string{"busstop"}, "6.0", false},
+	{"\U0001f464", "bust in silhouette", []string{"bust_in_silhouette"}, "6.0", false},
+	{"\U0001f465", "busts in silhouette", []string{"busts_in_silhouette"}, "6.0", false},
+	{"\U0001f9c8", "butter", []string{"butter"}, "12.0", false},
+	{"\U0001f98b", "butterfly", []string{"butterfly"}, "9.0", false},
+	{"\U0001f335", "cactus", []string{"cactus"}, "6.0", false},
+	{"\U0001f370", "shortcake", []string{"cake"}, "6.0", false},
+	{"\U0001f4c6", "tear-off calendar", []string{"calendar"}, "6.0", false},
+	{"\U0001f919", "call me hand", []string{"call_me_hand"}, "9.0", true},
+	{"\U0001f4f2", "mobile phone with arrow", []string{"calling"}, "6.0", false},
+	{"\U0001f1f0\U0001f1ed", "flag: Cambodia", []string{"cambodia"}, "6.0", false},
+	{"\U0001f42b", "two-hump camel", []string{"camel"}, "6.0", false},
+	{"\U0001f4f7", "camera", []string{"camera"}, "6.0", false},
+	{"\U0001f4f8", "camera with flash", []string{"camera_flash"}, "7.0", false},
+	{"\U0001f1e8\U0001f1f2", "flag: Cameroon", []string{"cameroon"}, "6.0", false},
+	{"\U0001f3d5\ufe0f", "camping", []string{"camping"}, "7.0", false},
+	{"\U0001f1e8\U0001f1e6", "flag: Canada", []string{"canada"}, "6.0", false},
+	{"\U0001f1ee\U0001f1e8", "flag: Canary Islands", []string{"canary_islands"}, "6.0", false},
+	{"\u264b", "Cancer", []string{"cancer"}, "", false},
+	{"\U0001f56f\ufe0f", "candle", []string{"candle"}, "7.0", false},
+	{"\U0001f36c", "candy", []string{"candy"}, "6.0", false},
+	{"\U0001f96b", "canned food", []string{"canned_food"}, "11.0", false},
+	{"\U0001f6f6", "canoe", []string{"canoe"}, "9.0", false},
+	{"\U0001f1e8\U0001f1fb", "flag: Cape Verde", []string{"cape_verde"}, "6.0", false},
+	{"\U0001f520", "input latin uppercase", []string{"capital_abcd"}, "6.0", false},
+	{"\u2651", "Capricorn", []string{"capricorn"}, "", false},
+	{"\U0001f697", "automobile", []string{"car", "red_car"}, "6.0", false},
+	{"\U0001f5c3\ufe0f", "card file box", []string{"card_file_box"}, "7.0", false},
+	{"\U0001f4c7", "card index", []string{"card_index"}, "6.0", false},
+	{"\U0001f5c2\ufe0f", "card index dividers", []string{"card_index_dividers"}, "7.0", false},
+	{"\U0001f1e7\U0001f1f6", "flag: Caribbean Netherlands", []string{"caribbean_netherlands"}, "6.0", false},
+	{"\U0001f3a0", "carousel horse", []string{"carousel_horse"}, "6.0", false},
+	{"\U0001f955", "carrot", []string{"carrot"}, "9.0", false},
+	{"\U0001f938", "person cartwheeling", []string{"cartwheeling"}, "11.0", true},
+	{"\U0001f431", "cat face", []string{"cat"}, "6.0", false},
+	{"\U0001f408", "cat", []string{"cat2"}, "6.0", false},
+	{"\U0001f1f0\U0001f1fe", "flag: Cayman Islands", []string{"cayman_islands"}, "6.0", false},
+	{"\U0001f4bf", "optical disk", []string{"cd"}, "6.0", false},
+	{"\U0001f1e8\U0001f1eb", "flag: Central African Republic", []string{"central_african_republic"}, "6.0", false},
+	{"\U0001f1ea\U0001f1e6", "flag: Ceuta & Melilla", []string{"ceuta_melilla"}, "11.0", false},
+	{"\U0001f1f9\U0001f1e9", "flag: Chad", []string{"chad"}, "6.0", false},
+	{"\u26d3\ufe0f", "chains", []string{"chains"}, "5.2", false},
+	{"\U0001fa91", "chair", []string{"chair"}, "12.0", false},
+	{"\U0001f37e", "bottle with popping cork", []string{"champagne"}, "8.0", false},
+	{"\U0001f4b9", "chart increasing with yen", []string{"chart"}, "6.0", false},
+	{"\U0001f4c9", "chart decreasing", []string{"chart_with_downwards_trend"}, "6.0", false},
+	{"\U0001f4c8", "chart increasing", []string{"chart_with_upwards_trend"}, "6.0", false},
+	{"\U0001f3c1", "chequered flag", []string{"checkered_flag"}, "6.0", false},
+	{"\U0001f9c0", "cheese wedge", []string{"cheese"}, "8.0", false},
+	{"\U0001f352", "cherries", []string{"cherries"}, "6.0", false},
+	{"\U0001f338", "cherry blossom", []string{"cherry_blossom"}, "6.0", false},
+	{"\u265f\ufe0f", "chess pawn", []string{"chess_pawn"}, "11.0", false},
+	{"\U0001f330", "chestnut", []string{"chestnut"}, "6.0", false},
+	{"\U0001f414", "chicken", []string{"chicken"}, "6.0", false},
+	{"\U0001f9d2", "child", []string{"child"}, "11.0", true},
+	{"\U0001f6b8", "children crossing", []string{"children_crossing"}, "6.0", false},
+	{"\U0001f1e8\U0001f1f1", "flag: Chile", []string{"chile"}, "6.0", false},
+	{"\U0001f43f\ufe0f", "chipmunk", []string{"chipmunk"}, "7.0", false},
+	{"\U0001f36b", "chocolate bar", []string{"chocolate_bar"}, "6.0", false},
+	{"\U0001f962", "chopsticks", []string{"chopsticks"}, "11.0", false},
+	{"\U0001f1e8\U0001f1fd", "flag: Christmas Island", []string{"christmas_island"}, "6.0", false},
+	{"\U0001f384", "Christmas tree", []string{"christmas_tree"}, "6.0", false},
+	{"\u26ea", "church", []string{"church"}, "5.2", false},
+	{"\U0001f3a6", "cinema", []string{"cinema"}, "6.0", false},
+	{"\U0001f3aa", "circus tent", []string{"circus_tent"}, "6.0", false},
+	{"\U0001f307", "sunset", []string{"city_sunrise"}, "6.0", false},
+	{"\U0001f306", "cityscape at dusk", []string{"city_sunset"}, "6.0", false},
+	{"\U0001f3d9\ufe0f", "cityscape", []string{"cityscape"}, "7.0", false},
+	{"\U0001f191", "CL button", []string{"cl"}, "6.0", false},
+	{"\U0001f5dc\ufe0f", "clamp", []string{"clamp"}, "7.0", false},
+	{"\U0001f44f", "clapping hands", []string{"clap"}, "6.0", true},
+	{"\U0001f3ac", "clapper board", []string{"clapper"}, "6.0", false},
+	{"\U0001f3db\ufe0f", "classical building", []string{"classical_building"}, "7.0", false},
+	{"\U0001f9d7", "person climbing", []string{"climbing"}, "11.0", true},
+	{"\U0001f9d7\u200d\u2642\ufe0f", "man climbing", []string{"climbing_man"}, "11.0", true},
+	{"\U0001f9d7\u200d\u2640\ufe0f", "woman climbing", []string{"climbing_woman"}, "11.0", true},
+	{"\U0001f942", "clinking glasses", []string{"clinking_glasses"}, "9.0", false},
+	{"\U0001f4cb", "clipboard", []string{"clipboard"}, "6.0", false},
+	{"\U0001f1e8\U0001f1f5", "flag: Clipperton Island", []string{"clipperton_island"}, "11.0", false},
+	{"\U0001f550", "one oโ€™clock", []string{"clock1"}, "6.0", false},
+	{"\U0001f559", "ten oโ€™clock", []string{"clock10"}, "6.0", false},
+	{"\U0001f565", "ten-thirty", []string{"clock1030"}, "6.0", false},
+	{"\U0001f55a", "eleven oโ€™clock", []string{"clock11"}, "6.0", false},
+	{"\U0001f566", "eleven-thirty", []string{"clock1130"}, "6.0", false},
+	{"\U0001f55b", "twelve oโ€™clock", []string{"clock12"}, "6.0", false},
+	{"\U0001f567", "twelve-thirty", []string{"clock1230"}, "6.0", false},
+	{"\U0001f55c", "one-thirty", []string{"clock130"}, "6.0", false},
+	{"\U0001f551", "two oโ€™clock", []string{"clock2"}, "6.0", false},
+	{"\U0001f55d", "two-thirty", []string{"clock230"}, "6.0", false},
+	{"\U0001f552", "three oโ€™clock", []string{"clock3"}, "6.0", false},
+	{"\U0001f55e", "three-thirty", []string{"clock330"}, "6.0", false},
+	{"\U0001f553", "four oโ€™clock", []string{"clock4"}, "6.0", false},
+	{"\U0001f55f", "four-thirty", []string{"clock430"}, "6.0", false},
+	{"\U0001f554", "five oโ€™clock", []string{"clock5"}, "6.0", false},
+	{"\U0001f560", "five-thirty", []string{"clock530"}, "6.0", false},
+	{"\U0001f555", "six oโ€™clock", []string{"clock6"}, "6.0", false},
+	{"\U0001f561", "six-thirty", []string{"clock630"}, "6.0", false},
+	{"\U0001f556", "seven oโ€™clock", []string{"clock7"}, "6.0", false},
+	{"\U0001f562", "seven-thirty", []string{"clock730"}, "6.0", false},
+	{"\U0001f557", "eight oโ€™clock", []string{"clock8"}, "6.0", false},
+	{"\U0001f563", "eight-thirty", []string{"clock830"}, "6.0", false},
+	{"\U0001f558", "nine oโ€™clock", []string{"clock9"}, "6.0", false},
+	{"\U0001f564", "nine-thirty", []string{"clock930"}, "6.0", false},
+	{"\U0001f4d5", "closed book", []string{"closed_book"}, "6.0", false},
+	{"\U0001f510", "locked with key", []string{"closed_lock_with_key"}, "6.0", false},
+	{"\U0001f302", "closed umbrella", []string{"closed_umbrella"}, "6.0", false},
+	{"\u2601\ufe0f", "cloud", []string{"cloud"}, "", false},
+	{"\U0001f329\ufe0f", "cloud with lightning", []string{"cloud_with_lightning"}, "7.0", false},
+	{"\u26c8\ufe0f", "cloud with lightning and rain", []string{"cloud_with_lightning_and_rain"}, "5.2", false},
+	{"\U0001f327\ufe0f", "cloud with rain", []string{"cloud_with_rain"}, "7.0", false},
+	{"\U0001f328\ufe0f", "cloud with snow", []string{"cloud_with_snow"}, "7.0", false},
+	{"\U0001f921", "clown face", []string{"clown_face"}, "9.0", false},
+	{"\u2663\ufe0f", "club suit", []string{"clubs"}, "", false},
+	{"\U0001f1e8\U0001f1f3", "flag: China", []string{"cn"}, "6.0", false},
+	{"\U0001f9e5", "coat", []string{"coat"}, "11.0", false},
+	{"\U0001f378", "cocktail glass", []string{"cocktail"}, "6.0", false},
+	{"\U0001f965", "coconut", []string{"coconut"}, "11.0", false},
+	{"\U0001f1e8\U0001f1e8", "flag: Cocos (Keeling) Islands", []string{"cocos_islands"}, "6.0", false},
+	{"\u2615", "hot beverage", []string{"coffee"}, "4.0", false},
+	{"\u26b0\ufe0f", "coffin", []string{"coffin"}, "4.1", false},
+	{"\U0001f976", "cold face", []string{"cold_face"}, "11.0", false},
+	{"\U0001f630", "anxious face with sweat", []string{"cold_sweat"}, "6.0", false},
+	{"\U0001f1e8\U0001f1f4", "flag: Colombia", []string{"colombia"}, "6.0", false},
+	{"\u2604\ufe0f", "comet", []string{"comet"}, "", false},
+	{"\U0001f1f0\U0001f1f2", "flag: Comoros", []string{"comoros"}, "6.0", false},
+	{"\U0001f9ed", "compass", []string{"compass"}, "11.0", false},
+	{"\U0001f4bb", "laptop", []string{"computer"}, "6.0", false},
+	{"\U0001f5b1\ufe0f", "computer mouse", []string{"computer_mouse"}, "7.0", false},
+	{"\U0001f38a", "confetti ball", []string{"confetti_ball"}, "6.0", false},
+	{"\U0001f616", "confounded face", []string{"confounded"}, "6.0", false},
+	{"\U0001f615", "confused face", []string{"confused"}, "6.1", false},
+	{"\U0001f1e8\U0001f1ec", "flag: Congo - Brazzaville", []string{"congo_brazzaville"}, "6.0", false},
+	{"\U0001f1e8\U0001f1e9", "flag: Congo - Kinshasa", []string{"congo_kinshasa"}, "6.0", false},
+	{"\u3297\ufe0f", "Japanese โ€œcongratulationsโ€ button", []string{"congratulations"}, "", false},
+	{"\U0001f6a7", "construction", []string{"construction"}, "6.0", false},
+	{"\U0001f477", "construction worker", []string{"construction_worker"}, "6.0", true},
+	{"\U0001f477\u200d\u2642\ufe0f", "man construction worker", []string{"construction_worker_man"}, "11.0", true},
+	{"\U0001f477\u200d\u2640\ufe0f", "woman construction worker", []string{"construction_worker_woman"}, "6.0", true},
+	{"\U0001f39b\ufe0f", "control knobs", []string{"control_knobs"}, "7.0", false},
+	{"\U0001f3ea", "convenience store", []string{"convenience_store"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f373", "cook", []string{"cook"}, "12.1", true},
+	{"\U0001f1e8\U0001f1f0", "flag: Cook Islands", []string{"cook_islands"}, "6.0", false},
+	{"\U0001f36a", "cookie", []string{"cookie"}, "6.0", false},
+	{"\U0001f192", "COOL button", []string{"cool"}, "6.0", false},
+	{"\u00a9\ufe0f", "copyright", []string{"copyright"}, "", false},
+	{"\U0001f33d", "ear of corn", []string{"corn"}, "6.0", false},
+	{"\U0001f1e8\U0001f1f7", "flag: Costa Rica", []string{"costa_rica"}, "6.0", false},
+	{"\U0001f1e8\U0001f1ee", "flag: Cรดte dโ€™Ivoire", []string{"cote_divoire"}, "6.0", false},
+	{"\U0001f6cb\ufe0f", "couch and lamp", []string{"couch_and_lamp"}, "7.0", false},
+	{"\U0001f46b", "woman and man holding hands", []string{"couple"}, "6.0", true},
+	{"\U0001f491", "couple with heart", []string{"couple_with_heart"}, "6.0", false},
+	{"\U0001f468\u200d\u2764\ufe0f\u200d\U0001f468", "couple with heart: man, man", []string{"couple_with_heart_man_man"}, "6.0", false},
+	{"\U0001f469\u200d\u2764\ufe0f\u200d\U0001f468", "couple with heart: woman, man", []string{"couple_with_heart_woman_man"}, "11.0", false},
+	{"\U0001f469\u200d\u2764\ufe0f\u200d\U0001f469", "couple with heart: woman, woman", []string{"couple_with_heart_woman_woman"}, "6.0", false},
+	{"\U0001f48f", "kiss", []string{"couplekiss"}, "6.0", false},
+	{"\U0001f468\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468", "kiss: man, man", []string{"couplekiss_man_man"}, "6.0", false},
+	{"\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f468", "kiss: woman, man", []string{"couplekiss_man_woman"}, "11.0", false},
+	{"\U0001f469\u200d\u2764\ufe0f\u200d\U0001f48b\u200d\U0001f469", "kiss: woman, woman", []string{"couplekiss_woman_woman"}, "6.0", false},
+	{"\U0001f42e", "cow face", []string{"cow"}, "6.0", false},
+	{"\U0001f404", "cow", []string{"cow2"}, "6.0", false},
+	{"\U0001f920", "cowboy hat face", []string{"cowboy_hat_face"}, "9.0", false},
+	{"\U0001f980", "crab", []string{"crab"}, "8.0", false},
+	{"\U0001f58d\ufe0f", "crayon", []string{"crayon"}, "7.0", false},
+	{"\U0001f4b3", "credit card", []string{"credit_card"}, "6.0", false},
+	{"\U0001f319", "crescent moon", []string{"crescent_moon"}, "6.0", false},
+	{"\U0001f997", "cricket", []string{"cricket"}, "11.0", false},
+	{"\U0001f3cf", "cricket game", []string{"cricket_game"}, "8.0", false},
+	{"\U0001f1ed\U0001f1f7", "flag: Croatia", []string{"croatia"}, "6.0", false},
+	{"\U0001f40a", "crocodile", []string{"crocodile"}, "6.0", false},
+	{"\U0001f950", "croissant", []string{"croissant"}, "9.0", false},
+	{"\U0001f91e", "crossed fingers", []string{"crossed_fingers"}, "9.0", true},
+	{"\U0001f38c", "crossed flags", []string{"crossed_flags"}, "6.0", false},
+	{"\u2694\ufe0f", "crossed swords", []string{"crossed_swords"}, "4.1", false},
+	{"\U0001f451", "crown", []string{"crown"}, "6.0", false},
+	{"\U0001f622", "crying face", []string{"cry"}, "6.0", false},
+	{"\U0001f63f", "crying cat", []string{"crying_cat_face"}, "6.0", false},
+	{"\U0001f52e", "crystal ball", []string{"crystal_ball"}, "6.0", false},
+	{"\U0001f1e8\U0001f1fa", "flag: Cuba", []string{"cuba"}, "6.0", false},
+	{"\U0001f952", "cucumber", []string{"cucumber"}, "9.0", false},
+	{"\U0001f964", "cup with straw", []string{"cup_with_straw"}, "11.0", false},
+	{"\U0001f9c1", "cupcake", []string{"cupcake"}, "11.0", false},
+	{"\U0001f498", "heart with arrow", []string{"cupid"}, "6.0", false},
+	{"\U0001f1e8\U0001f1fc", "flag: Curaรงao", []string{"curacao"}, "6.0", false},
+	{"\U0001f94c", "curling stone", []string{"curling_stone"}, "11.0", false},
+	{"\U0001f468\u200d\U0001f9b1", "man: curly hair", []string{"curly_haired_man"}, "11.0", true},
+	{"\U0001f469\u200d\U0001f9b1", "woman: curly hair", []string{"curly_haired_woman"}, "11.0", true},
+	{"\u27b0", "curly loop", []string{"curly_loop"}, "6.0", false},
+	{"\U0001f4b1", "currency exchange", []string{"currency_exchange"}, "6.0", false},
+	{"\U0001f35b", "curry rice", []string{"curry"}, "6.0", false},
+	{"\U0001f92c", "face with symbols on mouth", []string{"cursing_face"}, "11.0", false},
+	{"\U0001f36e", "custard", []string{"custard"}, "6.0", false},
+	{"\U0001f6c3", "customs", []string{"customs"}, "6.0", false},
+	{"\U0001f969", "cut of meat", []string{"cut_of_meat"}, "11.0", false},
+	{"\U0001f300", "cyclone", []string{"cyclone"}, "6.0", false},
+	{"\U0001f1e8\U0001f1fe", "flag: Cyprus", []string{"cyprus"}, "6.0", false},
+	{"\U0001f1e8\U0001f1ff", "flag: Czechia", []string{"czech_republic"}, "6.0", false},
+	{"\U0001f5e1\ufe0f", "dagger", []string{"dagger"}, "7.0", false},
+	{"\U0001f46f", "people with bunny ears", []string{"dancers"}, "6.0", false},
+	{"\U0001f46f\u200d\u2642\ufe0f", "men with bunny ears", []string{"dancing_men"}, "6.0", false},
+	{"\U0001f46f\u200d\u2640\ufe0f", "women with bunny ears", []string{"dancing_women"}, "11.0", false},
+	{"\U0001f361", "dango", []string{"dango"}, "6.0", false},
+	{"\U0001f576\ufe0f", "sunglasses", []string{"dark_sunglasses"}, "7.0", false},
+	{"\U0001f3af", "direct hit", []string{"dart"}, "6.0", false},
+	{"\U0001f4a8", "dashing away", []string{"dash"}, "6.0", false},
+	{"\U0001f4c5", "calendar", []string{"date"}, "6.0", false},
+	{"\U0001f1e9\U0001f1ea", "flag: Germany", []string{"de"}, "6.0", false},
+	{"\U0001f9cf\u200d\u2642\ufe0f", "deaf man", []string{"deaf_man"}, "12.0", true},
+	{"\U0001f9cf", "deaf person", []string{"deaf_person"}, "12.0", true},
+	{"\U0001f9cf\u200d\u2640\ufe0f", "deaf woman", []string{"deaf_woman"}, "12.0", true},
+	{"\U0001f333", "deciduous tree", []string{"deciduous_tree"}, "6.0", false},
+	{"\U0001f98c", "deer", []string{"deer"}, "9.0", false},
+	{"\U0001f1e9\U0001f1f0", "flag: Denmark", []string{"denmark"}, "6.0", false},
+	{"\U0001f3ec", "department store", []string{"department_store"}, "6.0", false},
+	{"\U0001f3da\ufe0f", "derelict house", []string{"derelict_house"}, "7.0", false},
+	{"\U0001f3dc\ufe0f", "desert", []string{"desert"}, "7.0", false},
+	{"\U0001f3dd\ufe0f", "desert island", []string{"desert_island"}, "7.0", false},
+	{"\U0001f5a5\ufe0f", "desktop computer", []string{"desktop_computer"}, "7.0", false},
+	{"\U0001f575\ufe0f", "detective", []string{"detective"}, "7.0", true},
+	{"\U0001f4a0", "diamond with a dot", []string{"diamond_shape_with_a_dot_inside"}, "6.0", false},
+	{"\u2666\ufe0f", "diamond suit", []string{"diamonds"}, "", false},
+	{"\U0001f1e9\U0001f1ec", "flag: Diego Garcia", []string{"diego_garcia"}, "11.0", false},
+	{"\U0001f61e", "disappointed face", []string{"disappointed"}, "6.0", false},
+	{"\U0001f625", "sad but relieved face", []string{"disappointed_relieved"}, "6.0", false},
+	{"\U0001f93f", "diving mask", []string{"diving_mask"}, "12.0", false},
+	{"\U0001fa94", "diya lamp", []string{"diya_lamp"}, "12.0", false},
+	{"\U0001f4ab", "dizzy", []string{"dizzy"}, "6.0", false},
+	{"\U0001f635", "dizzy face", []string{"dizzy_face"}, "6.0", false},
+	{"\U0001f1e9\U0001f1ef", "flag: Djibouti", []string{"djibouti"}, "6.0", false},
+	{"\U0001f9ec", "dna", []string{"dna"}, "11.0", false},
+	{"\U0001f6af", "no littering", []string{"do_not_litter"}, "6.0", false},
+	{"\U0001f436", "dog face", []string{"dog"}, "6.0", false},
+	{"\U0001f415", "dog", []string{"dog2"}, "6.0", false},
+	{"\U0001f4b5", "dollar banknote", []string{"dollar"}, "6.0", false},
+	{"\U0001f38e", "Japanese dolls", []string{"dolls"}, "6.0", false},
+	{"\U0001f42c", "dolphin", []string{"dolphin", "flipper"}, "6.0", false},
+	{"\U0001f1e9\U0001f1f2", "flag: Dominica", []string{"dominica"}, "6.0", false},
+	{"\U0001f1e9\U0001f1f4", "flag: Dominican Republic", []string{"dominican_republic"}, "6.0", false},
+	{"\U0001f6aa", "door", []string{"door"}, "6.0", false},
+	{"\U0001f369", "doughnut", []string{"doughnut"}, "6.0", false},
+	{"\U0001f54a\ufe0f", "dove", []string{"dove"}, "7.0", false},
+	{"\U0001f409", "dragon", []string{"dragon"}, "6.0", false},
+	{"\U0001f432", "dragon face", []string{"dragon_face"}, "6.0", false},
+	{"\U0001f457", "dress", []string{"dress"}, "6.0", false},
+	{"\U0001f42a", "camel", []string{"dromedary_camel"}, "6.0", false},
+	{"\U0001f924", "drooling face", []string{"drooling_face"}, "9.0", false},
+	{"\U0001fa78", "drop of blood", []string{"drop_of_blood"}, "12.0", false},
+	{"\U0001f4a7", "droplet", []string{"droplet"}, "6.0", false},
+	{"\U0001f941", "drum", []string{"drum"}, "", false},
+	{"\U0001f986", "duck", []string{"duck"}, "9.0", false},
+	{"\U0001f95f", "dumpling", []string{"dumpling"}, "11.0", false},
+	{"\U0001f4c0", "dvd", []string{"dvd"}, "6.0", false},
+	{"\U0001f4e7", "e-mail", []string{"e-mail"}, "6.0", false},
+	{"\U0001f985", "eagle", []string{"eagle"}, "9.0", false},
+	{"\U0001f442", "ear", []string{"ear"}, "6.0", true},
+	{"\U0001f33e", "sheaf of rice", []string{"ear_of_rice"}, "6.0", false},
+	{"\U0001f9bb", "ear with hearing aid", []string{"ear_with_hearing_aid"}, "12.0", true},
+	{"\U0001f30d", "globe showing Europe-Africa", []string{"earth_africa"}, "6.0", false},
+	{"\U0001f30e", "globe showing Americas", []string{"earth_americas"}, "6.0", false},
+	{"\U0001f30f", "globe showing Asia-Australia", []string{"earth_asia"}, "6.0", false},
+	{"\U0001f1ea\U0001f1e8", "flag: Ecuador", []string{"ecuador"}, "6.0", false},
+	{"\U0001f95a", "egg", []string{"egg"}, "9.0", false},
+	{"\U0001f346", "eggplant", []string{"eggplant"}, "6.0", false},
+	{"\U0001f1ea\U0001f1ec", "flag: Egypt", []string{"egypt"}, "6.0", false},
+	{"8\ufe0f\u20e3", "keycap: 8", []string{"eight"}, "", false},
+	{"\u2734\ufe0f", "eight-pointed star", []string{"eight_pointed_black_star"}, "", false},
+	{"\u2733\ufe0f", "eight-spoked asterisk", []string{"eight_spoked_asterisk"}, "", false},
+	{"\u23cf\ufe0f", "eject button", []string{"eject_button"}, "11.0", false},
+	{"\U0001f1f8\U0001f1fb", "flag: El Salvador", []string{"el_salvador"}, "6.0", false},
+	{"\U0001f50c", "electric plug", []string{"electric_plug"}, "6.0", false},
+	{"\U0001f418", "elephant", []string{"elephant"}, "6.0", false},
+	{"\U0001f9dd", "elf", []string{"elf"}, "11.0", true},
+	{"\U0001f9dd\u200d\u2642\ufe0f", "man elf", []string{"elf_man"}, "11.0", true},
+	{"\U0001f9dd\u200d\u2640\ufe0f", "woman elf", []string{"elf_woman"}, "11.0", true},
+	{"\u2709\ufe0f", "envelope", []string{"email", "envelope"}, "", false},
+	{"\U0001f51a", "END arrow", []string{"end"}, "6.0", false},
+	{"\U0001f3f4\U000e0067\U000e0062\U000e0065\U000e006e\U000e0067\U000e007f", "flag: England", []string{"england"}, "11.0", false},
+	{"\U0001f4e9", "envelope with arrow", []string{"envelope_with_arrow"}, "6.0", false},
+	{"\U0001f1ec\U0001f1f6", "flag: Equatorial Guinea", []string{"equatorial_guinea"}, "6.0", false},
+	{"\U0001f1ea\U0001f1f7", "flag: Eritrea", []string{"eritrea"}, "6.0", false},
+	{"\U0001f1ea\U0001f1f8", "flag: Spain", []string{"es"}, "6.0", false},
+	{"\U0001f1ea\U0001f1ea", "flag: Estonia", []string{"estonia"}, "6.0", false},
+	{"\U0001f1ea\U0001f1f9", "flag: Ethiopia", []string{"ethiopia"}, "6.0", false},
+	{"\U0001f1ea\U0001f1fa", "flag: European Union", []string{"eu", "european_union"}, "6.0", false},
+	{"\U0001f4b6", "euro banknote", []string{"euro"}, "6.0", false},
+	{"\U0001f3f0", "castle", []string{"european_castle"}, "6.0", false},
+	{"\U0001f3e4", "post office", []string{"european_post_office"}, "6.0", false},
+	{"\U0001f332", "evergreen tree", []string{"evergreen_tree"}, "6.0", false},
+	{"\u2757", "exclamation mark", []string{"exclamation", "heavy_exclamation_mark"}, "5.2", false},
+	{"\U0001f92f", "exploding head", []string{"exploding_head"}, "11.0", false},
+	{"\U0001f611", "expressionless face", []string{"expressionless"}, "6.1", false},
+	{"\U0001f441\ufe0f", "eye", []string{"eye"}, "7.0", false},
+	{"\U0001f441\ufe0f\u200d\U0001f5e8\ufe0f", "eye in speech bubble", []string{"eye_speech_bubble"}, "11.0", false},
+	{"\U0001f453", "glasses", []string{"eyeglasses"}, "6.0", false},
+	{"\U0001f440", "eyes", []string{"eyes"}, "6.0", false},
+	{"\U0001f915", "face with head-bandage", []string{"face_with_head_bandage"}, "8.0", false},
+	{"\U0001f912", "face with thermometer", []string{"face_with_thermometer"}, "8.0", false},
+	{"\U0001f926", "person facepalming", []string{"facepalm"}, "11.0", true},
+	{"\U0001f3ed", "factory", []string{"factory"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f3ed", "factory worker", []string{"factory_worker"}, "12.1", true},
+	{"\U0001f9da", "fairy", []string{"fairy"}, "11.0", true},
+	{"\U0001f9da\u200d\u2642\ufe0f", "man fairy", []string{"fairy_man"}, "11.0", true},
+	{"\U0001f9da\u200d\u2640\ufe0f", "woman fairy", []string{"fairy_woman"}, "11.0", true},
+	{"\U0001f9c6", "falafel", []string{"falafel"}, "12.0", false},
+	{"\U0001f1eb\U0001f1f0", "flag: Falkland Islands", []string{"falkland_islands"}, "6.0", false},
+	{"\U0001f342", "fallen leaf", []string{"fallen_leaf"}, "6.0", false},
+	{"\U0001f46a", "family", []string{"family"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f466", "family: man, boy", []string{"family_man_boy"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f466\u200d\U0001f466", "family: man, boy, boy", []string{"family_man_boy_boy"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f467", "family: man, girl", []string{"family_man_girl"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f467\u200d\U0001f466", "family: man, girl, boy", []string{"family_man_girl_boy"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f467\u200d\U0001f467", "family: man, girl, girl", []string{"family_man_girl_girl"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f468\u200d\U0001f466", "family: man, man, boy", []string{"family_man_man_boy"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f468\u200d\U0001f466\u200d\U0001f466", "family: man, man, boy, boy", []string{"family_man_man_boy_boy"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f468\u200d\U0001f467", "family: man, man, girl", []string{"family_man_man_girl"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f468\u200d\U0001f467\u200d\U0001f466", "family: man, man, girl, boy", []string{"family_man_man_girl_boy"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f468\u200d\U0001f467\u200d\U0001f467", "family: man, man, girl, girl", []string{"family_man_man_girl_girl"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f469\u200d\U0001f466", "family: man, woman, boy", []string{"family_man_woman_boy"}, "11.0", false},
+	{"\U0001f468\u200d\U0001f469\u200d\U0001f466\u200d\U0001f466", "family: man, woman, boy, boy", []string{"family_man_woman_boy_boy"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f469\u200d\U0001f467", "family: man, woman, girl", []string{"family_man_woman_girl"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f469\u200d\U0001f467\u200d\U0001f466", "family: man, woman, girl, boy", []string{"family_man_woman_girl_boy"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f469\u200d\U0001f467\u200d\U0001f467", "family: man, woman, girl, girl", []string{"family_man_woman_girl_girl"}, "6.0", false},
+	{"\U0001f469\u200d\U0001f466", "family: woman, boy", []string{"family_woman_boy"}, "6.0", false},
+	{"\U0001f469\u200d\U0001f466\u200d\U0001f466", "family: woman, boy, boy", []string{"family_woman_boy_boy"}, "6.0", false},
+	{"\U0001f469\u200d\U0001f467", "family: woman, girl", []string{"family_woman_girl"}, "6.0", false},
+	{"\U0001f469\u200d\U0001f467\u200d\U0001f466", "family: woman, girl, boy", []string{"family_woman_girl_boy"}, "6.0", false},
+	{"\U0001f469\u200d\U0001f467\u200d\U0001f467", "family: woman, girl, girl", []string{"family_woman_girl_girl"}, "6.0", false},
+	{"\U0001f469\u200d\U0001f469\u200d\U0001f466", "family: woman, woman, boy", []string{"family_woman_woman_boy"}, "6.0", false},
+	{"\U0001f469\u200d\U0001f469\u200d\U0001f466\u200d\U0001f466", "family: woman, woman, boy, boy", []string{"family_woman_woman_boy_boy"}, "6.0", false},
+	{"\U0001f469\u200d\U0001f469\u200d\U0001f467", "family: woman, woman, girl", []string{"family_woman_woman_girl"}, "6.0", false},
+	{"\U0001f469\u200d\U0001f469\u200d\U0001f467\u200d\U0001f466", "family: woman, woman, girl, boy", []string{"family_woman_woman_girl_boy"}, "6.0", false},
+	{"\U0001f469\u200d\U0001f469\u200d\U0001f467\u200d\U0001f467", "family: woman, woman, girl, girl", []string{"family_woman_woman_girl_girl"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f33e", "farmer", []string{"farmer"}, "12.1", true},
+	{"\U0001f1eb\U0001f1f4", "flag: Faroe Islands", []string{"faroe_islands"}, "6.0", false},
+	{"\u23e9", "fast-forward button", []string{"fast_forward"}, "6.0", false},
+	{"\U0001f4e0", "fax machine", []string{"fax"}, "6.0", false},
+	{"\U0001f628", "fearful face", []string{"fearful"}, "6.0", false},
+	{"\U0001f43e", "paw prints", []string{"feet", "paw_prints"}, "6.0", false},
+	{"\U0001f575\ufe0f\u200d\u2640\ufe0f", "woman detective", []string{"female_detective"}, "6.0", true},
+	{"\u2640\ufe0f", "female sign", []string{"female_sign"}, "11.0", false},
+	{"\U0001f3a1", "ferris wheel", []string{"ferris_wheel"}, "6.0", false},
+	{"\u26f4\ufe0f", "ferry", []string{"ferry"}, "5.2", false},
+	{"\U0001f3d1", "field hockey", []string{"field_hockey"}, "8.0", false},
+	{"\U0001f1eb\U0001f1ef", "flag: Fiji", []string{"fiji"}, "6.0", false},
+	{"\U0001f5c4\ufe0f", "file cabinet", []string{"file_cabinet"}, "7.0", false},
+	{"\U0001f4c1", "file folder", []string{"file_folder"}, "6.0", false},
+	{"\U0001f4fd\ufe0f", "film projector", []string{"film_projector"}, "7.0", false},
+	{"\U0001f39e\ufe0f", "film frames", []string{"film_strip"}, "7.0", false},
+	{"\U0001f1eb\U0001f1ee", "flag: Finland", []string{"finland"}, "6.0", false},
+	{"\U0001f525", "fire", []string{"fire"}, "6.0", false},
+	{"\U0001f692", "fire engine", []string{"fire_engine"}, "6.0", false},
+	{"\U0001f9ef", "fire extinguisher", []string{"fire_extinguisher"}, "11.0", false},
+	{"\U0001f9e8", "firecracker", []string{"firecracker"}, "11.0", false},
+	{"\U0001f9d1\u200d\U0001f692", "firefighter", []string{"firefighter"}, "12.1", true},
+	{"\U0001f386", "fireworks", []string{"fireworks"}, "6.0", false},
+	{"\U0001f313", "first quarter moon", []string{"first_quarter_moon"}, "6.0", false},
+	{"\U0001f31b", "first quarter moon face", []string{"first_quarter_moon_with_face"}, "6.0", false},
+	{"\U0001f41f", "fish", []string{"fish"}, "6.0", false},
+	{"\U0001f365", "fish cake with swirl", []string{"fish_cake"}, "6.0", false},
+	{"\U0001f3a3", "fishing pole", []string{"fishing_pole_and_fish"}, "6.0", false},
+	{"\U0001f91b", "left-facing fist", []string{"fist_left"}, "9.0", true},
+	{"\U0001f44a", "oncoming fist", []string{"fist_oncoming", "facepunch", "punch"}, "6.0", true},
+	{"\u270a", "raised fist", []string{"fist_raised", "fist"}, "6.0", true},
+	{"\U0001f91c", "right-facing fist", []string{"fist_right"}, "9.0", true},
+	{"5\ufe0f\u20e3", "keycap: 5", []string{"five"}, "", false},
+	{"\U0001f38f", "carp streamer", []string{"flags"}, "6.0", false},
+	{"\U0001f9a9", "flamingo", []string{"flamingo"}, "12.0", false},
+	{"\U0001f526", "flashlight", []string{"flashlight"}, "6.0", false},
+	{"\U0001f97f", "flat shoe", []string{"flat_shoe"}, "11.0", false},
+	{"\u269c\ufe0f", "fleur-de-lis", []string{"fleur_de_lis"}, "4.1", false},
+	{"\U0001f6ec", "airplane arrival", []string{"flight_arrival"}, "7.0", false},
+	{"\U0001f6eb", "airplane departure", []string{"flight_departure"}, "7.0", false},
+	{"\U0001f4be", "floppy disk", []string{"floppy_disk"}, "6.0", false},
+	{"\U0001f3b4", "flower playing cards", []string{"flower_playing_cards"}, "6.0", false},
+	{"\U0001f633", "flushed face", []string{"flushed"}, "6.0", false},
+	{"\U0001f94f", "flying disc", []string{"flying_disc"}, "11.0", false},
+	{"\U0001f6f8", "flying saucer", []string{"flying_saucer"}, "11.0", false},
+	{"\U0001f32b\ufe0f", "fog", []string{"fog"}, "7.0", false},
+	{"\U0001f301", "foggy", []string{"foggy"}, "6.0", false},
+	{"\U0001f9b6", "foot", []string{"foot"}, "11.0", true},
+	{"\U0001f3c8", "american football", []string{"football"}, "6.0", false},
+	{"\U0001f463", "footprints", []string{"footprints"}, "6.0", false},
+	{"\U0001f374", "fork and knife", []string{"fork_and_knife"}, "6.0", false},
+	{"\U0001f960", "fortune cookie", []string{"fortune_cookie"}, "11.0", false},
+	{"\u26f2", "fountain", []string{"fountain"}, "5.2", false},
+	{"\U0001f58b\ufe0f", "fountain pen", []string{"fountain_pen"}, "7.0", false},
+	{"4\ufe0f\u20e3", "keycap: 4", []string{"four"}, "", false},
+	{"\U0001f340", "four leaf clover", []string{"four_leaf_clover"}, "6.0", false},
+	{"\U0001f98a", "fox", []string{"fox_face"}, "9.0", false},
+	{"\U0001f1eb\U0001f1f7", "flag: France", []string{"fr"}, "6.0", false},
+	{"\U0001f5bc\ufe0f", "framed picture", []string{"framed_picture"}, "7.0", false},
+	{"\U0001f193", "FREE button", []string{"free"}, "6.0", false},
+	{"\U0001f1ec\U0001f1eb", "flag: French Guiana", []string{"french_guiana"}, "6.0", false},
+	{"\U0001f1f5\U0001f1eb", "flag: French Polynesia", []string{"french_polynesia"}, "6.0", false},
+	{"\U0001f1f9\U0001f1eb", "flag: French Southern Territories", []string{"french_southern_territories"}, "6.0", false},
+	{"\U0001f373", "cooking", []string{"fried_egg"}, "6.0", false},
+	{"\U0001f364", "fried shrimp", []string{"fried_shrimp"}, "6.0", false},
+	{"\U0001f35f", "french fries", []string{"fries"}, "6.0", false},
+	{"\U0001f438", "frog", []string{"frog"}, "6.0", false},
+	{"\U0001f626", "frowning face with open mouth", []string{"frowning"}, "6.1", false},
+	{"\u2639\ufe0f", "frowning face", []string{"frowning_face"}, "", false},
+	{"\U0001f64d\u200d\u2642\ufe0f", "man frowning", []string{"frowning_man"}, "6.0", true},
+	{"\U0001f64d", "person frowning", []string{"frowning_person"}, "6.0", true},
+	{"\U0001f64d\u200d\u2640\ufe0f", "woman frowning", []string{"frowning_woman"}, "11.0", true},
+	{"\u26fd", "fuel pump", []string{"fuelpump"}, "5.2", false},
+	{"\U0001f315", "full moon", []string{"full_moon"}, "6.0", false},
+	{"\U0001f31d", "full moon face", []string{"full_moon_with_face"}, "6.0", false},
+	{"\u26b1\ufe0f", "funeral urn", []string{"funeral_urn"}, "4.1", false},
+	{"\U0001f1ec\U0001f1e6", "flag: Gabon", []string{"gabon"}, "6.0", false},
+	{"\U0001f1ec\U0001f1f2", "flag: Gambia", []string{"gambia"}, "6.0", false},
+	{"\U0001f3b2", "game die", []string{"game_die"}, "6.0", false},
+	{"\U0001f9c4", "garlic", []string{"garlic"}, "12.0", false},
+	{"\U0001f1ec\U0001f1e7", "flag: United Kingdom", []string{"gb", "uk"}, "6.0", false},
+	{"\u2699\ufe0f", "gear", []string{"gear"}, "4.1", false},
+	{"\U0001f48e", "gem stone", []string{"gem"}, "6.0", false},
+	{"\u264a", "Gemini", []string{"gemini"}, "", false},
+	{"\U0001f9de", "genie", []string{"genie"}, "11.0", false},
+	{"\U0001f9de\u200d\u2642\ufe0f", "man genie", []string{"genie_man"}, "11.0", false},
+	{"\U0001f9de\u200d\u2640\ufe0f", "woman genie", []string{"genie_woman"}, "11.0", false},
+	{"\U0001f1ec\U0001f1ea", "flag: Georgia", []string{"georgia"}, "6.0", false},
+	{"\U0001f1ec\U0001f1ed", "flag: Ghana", []string{"ghana"}, "6.0", false},
+	{"\U0001f47b", "ghost", []string{"ghost"}, "6.0", false},
+	{"\U0001f1ec\U0001f1ee", "flag: Gibraltar", []string{"gibraltar"}, "6.0", false},
+	{"\U0001f381", "wrapped gift", []string{"gift"}, "6.0", false},
+	{"\U0001f49d", "heart with ribbon", []string{"gift_heart"}, "6.0", false},
+	{"\U0001f992", "giraffe", []string{"giraffe"}, "11.0", false},
+	{"\U0001f467", "girl", []string{"girl"}, "6.0", true},
+	{"\U0001f310", "globe with meridians", []string{"globe_with_meridians"}, "6.0", false},
+	{"\U0001f9e4", "gloves", []string{"gloves"}, "11.0", false},
+	{"\U0001f945", "goal net", []string{"goal_net"}, "9.0", false},
+	{"\U0001f410", "goat", []string{"goat"}, "6.0", false},
+	{"\U0001f97d", "goggles", []string{"goggles"}, "11.0", false},
+	{"\u26f3", "flag in hole", []string{"golf"}, "5.2", false},
+	{"\U0001f3cc\ufe0f", "person golfing", []string{"golfing"}, "7.0", true},
+	{"\U0001f3cc\ufe0f\u200d\u2642\ufe0f", "man golfing", []string{"golfing_man"}, "11.0", true},
+	{"\U0001f3cc\ufe0f\u200d\u2640\ufe0f", "woman golfing", []string{"golfing_woman"}, "", true},
+	{"\U0001f98d", "gorilla", []string{"gorilla"}, "9.0", false},
+	{"\U0001f347", "grapes", []string{"grapes"}, "6.0", false},
+	{"\U0001f1ec\U0001f1f7", "flag: Greece", []string{"greece"}, "6.0", false},
+	{"\U0001f34f", "green apple", []string{"green_apple"}, "6.0", false},
+	{"\U0001f4d7", "green book", []string{"green_book"}, "6.0", false},
+	{"\U0001f7e2", "green circle", []string{"green_circle"}, "12.0", false},
+	{"\U0001f49a", "green heart", []string{"green_heart"}, "6.0", false},
+	{"\U0001f957", "green salad", []string{"green_salad"}, "9.0", false},
+	{"\U0001f7e9", "green square", []string{"green_square"}, "12.0", false},
+	{"\U0001f1ec\U0001f1f1", "flag: Greenland", []string{"greenland"}, "6.0", false},
+	{"\U0001f1ec\U0001f1e9", "flag: Grenada", []string{"grenada"}, "6.0", false},
+	{"\u2755", "white exclamation mark", []string{"grey_exclamation"}, "6.0", false},
+	{"\u2754", "white question mark", []string{"grey_question"}, "6.0", false},
+	{"\U0001f62c", "grimacing face", []string{"grimacing"}, "6.1", false},
+	{"\U0001f601", "beaming face with smiling eyes", []string{"grin"}, "6.0", false},
+	{"\U0001f600", "grinning face", []string{"grinning"}, "6.1", false},
+	{"\U0001f1ec\U0001f1f5", "flag: Guadeloupe", []string{"guadeloupe"}, "6.0", false},
+	{"\U0001f1ec\U0001f1fa", "flag: Guam", []string{"guam"}, "6.0", false},
+	{"\U0001f482", "guard", []string{"guard"}, "6.0", true},
+	{"\U0001f482\u200d\u2642\ufe0f", "man guard", []string{"guardsman"}, "11.0", true},
+	{"\U0001f482\u200d\u2640\ufe0f", "woman guard", []string{"guardswoman"}, "6.0", true},
+	{"\U0001f1ec\U0001f1f9", "flag: Guatemala", []string{"guatemala"}, "6.0", false},
+	{"\U0001f1ec\U0001f1ec", "flag: Guernsey", []string{"guernsey"}, "6.0", false},
+	{"\U0001f9ae", "guide dog", []string{"guide_dog"}, "12.0", false},
+	{"\U0001f1ec\U0001f1f3", "flag: Guinea", []string{"guinea"}, "6.0", false},
+	{"\U0001f1ec\U0001f1fc", "flag: Guinea-Bissau", []string{"guinea_bissau"}, "6.0", false},
+	{"\U0001f3b8", "guitar", []string{"guitar"}, "6.0", false},
+	{"\U0001f52b", "pistol", []string{"gun"}, "6.0", false},
+	{"\U0001f1ec\U0001f1fe", "flag: Guyana", []string{"guyana"}, "6.0", false},
+	{"\U0001f487", "person getting haircut", []string{"haircut"}, "6.0", true},
+	{"\U0001f487\u200d\u2642\ufe0f", "man getting haircut", []string{"haircut_man"}, "6.0", true},
+	{"\U0001f487\u200d\u2640\ufe0f", "woman getting haircut", []string{"haircut_woman"}, "11.0", true},
+	{"\U0001f1ed\U0001f1f9", "flag: Haiti", []string{"haiti"}, "6.0", false},
+	{"\U0001f354", "hamburger", []string{"hamburger"}, "6.0", false},
+	{"\U0001f528", "hammer", []string{"hammer"}, "6.0", false},
+	{"\u2692\ufe0f", "hammer and pick", []string{"hammer_and_pick"}, "4.1", false},
+	{"\U0001f6e0\ufe0f", "hammer and wrench", []string{"hammer_and_wrench"}, "7.0", false},
+	{"\U0001f439", "hamster", []string{"hamster"}, "6.0", false},
+	{"\u270b", "raised hand", []string{"hand", "raised_hand"}, "6.0", true},
+	{"\U0001f92d", "face with hand over mouth", []string{"hand_over_mouth"}, "11.0", false},
+	{"\U0001f45c", "handbag", []string{"handbag"}, "6.0", false},
+	{"\U0001f93e", "person playing handball", []string{"handball_person"}, "11.0", true},
+	{"\U0001f91d", "handshake", []string{"handshake"}, "9.0", false},
+	{"\U0001f4a9", "pile of poo", []string{"hankey", "poop", "shit"}, "6.0", false},
+	{"#\ufe0f\u20e3", "keycap: #", []string{"hash"}, "", false},
+	{"\U0001f425", "front-facing baby chick", []string{"hatched_chick"}, "6.0", false},
+	{"\U0001f423", "hatching chick", []string{"hatching_chick"}, "6.0", false},
+	{"\U0001f3a7", "headphone", []string{"headphones"}, "6.0", false},
+	{"\U0001f9d1\u200d\u2695\ufe0f", "health worker", []string{"health_worker"}, "12.1", true},
+	{"\U0001f649", "hear-no-evil monkey", []string{"hear_no_evil"}, "6.0", false},
+	{"\U0001f1ed\U0001f1f2", "flag: Heard & McDonald Islands", []string{"heard_mcdonald_islands"}, "11.0", false},
+	{"\u2764\ufe0f", "red heart", []string{"heart"}, "", false},
+	{"\U0001f49f", "heart decoration", []string{"heart_decoration"}, "6.0", false},
+	{"\U0001f60d", "smiling face with heart-eyes", []string{"heart_eyes"}, "6.0", false},
+	{"\U0001f63b", "smiling cat with heart-eyes", []string{"heart_eyes_cat"}, "6.0", false},
+	{"\U0001f493", "beating heart", []string{"heartbeat"}, "6.0", false},
+	{"\U0001f497", "growing heart", []string{"heartpulse"}, "6.0", false},
+	{"\u2665\ufe0f", "heart suit", []string{"hearts"}, "", false},
+	{"\u2714\ufe0f", "check mark", []string{"heavy_check_mark"}, "", false},
+	{"\u2797", "divide", []string{"heavy_division_sign"}, "6.0", false},
+	{"\U0001f4b2", "heavy dollar sign", []string{"heavy_dollar_sign"}, "6.0", false},
+	{"\u2763\ufe0f", "heart exclamation", []string{"heavy_heart_exclamation"}, "", false},
+	{"\u2796", "minus", []string{"heavy_minus_sign"}, "6.0", false},
+	{"\u2716\ufe0f", "multiply", []string{"heavy_multiplication_x"}, "", false},
+	{"\u2795", "plus", []string{"heavy_plus_sign"}, "6.0", false},
+	{"\U0001f994", "hedgehog", []string{"hedgehog"}, "11.0", false},
+	{"\U0001f681", "helicopter", []string{"helicopter"}, "6.0", false},
+	{"\U0001f33f", "herb", []string{"herb"}, "6.0", false},
+	{"\U0001f33a", "hibiscus", []string{"hibiscus"}, "6.0", false},
+	{"\U0001f506", "bright button", []string{"high_brightness"}, "6.0", false},
+	{"\U0001f460", "high-heeled shoe", []string{"high_heel"}, "6.0", false},
+	{"\U0001f97e", "hiking boot", []string{"hiking_boot"}, "11.0", false},
+	{"\U0001f6d5", "hindu temple", []string{"hindu_temple"}, "12.0", false},
+	{"\U0001f99b", "hippopotamus", []string{"hippopotamus"}, "11.0", false},
+	{"\U0001f52a", "kitchen knife", []string{"hocho", "knife"}, "6.0", false},
+	{"\U0001f573\ufe0f", "hole", []string{"hole"}, "7.0", false},
+	{"\U0001f1ed\U0001f1f3", "flag: Honduras", []string{"honduras"}, "6.0", false},
+	{"\U0001f36f", "honey pot", []string{"honey_pot"}, "6.0", false},
+	{"\U0001f1ed\U0001f1f0", "flag: Hong Kong SAR China", []string{"hong_kong"}, "6.0", false},
+	{"\U0001f434", "horse face", []string{"horse"}, "6.0", false},
+	{"\U0001f3c7", "horse racing", []string{"horse_racing"}, "6.0", true},
+	{"\U0001f3e5", "hospital", []string{"hospital"}, "6.0", false},
+	{"\U0001f975", "hot face", []string{"hot_face"}, "11.0", false},
+	{"\U0001f336\ufe0f", "hot pepper", []string{"hot_pepper"}, "7.0", false},
+	{"\U0001f32d", "hot dog", []string{"hotdog"}, "8.0", false},
+	{"\U0001f3e8", "hotel", []string{"hotel"}, "6.0", false},
+	{"\u2668\ufe0f", "hot springs", []string{"hotsprings"}, "", false},
+	{"\u231b", "hourglass done", []string{"hourglass"}, "", false},
+	{"\u23f3", "hourglass not done", []string{"hourglass_flowing_sand"}, "6.0", false},
+	{"\U0001f3e0", "house", []string{"house"}, "6.0", false},
+	{"\U0001f3e1", "house with garden", []string{"house_with_garden"}, "6.0", false},
+	{"\U0001f3d8\ufe0f", "houses", []string{"houses"}, "7.0", false},
+	{"\U0001f917", "hugging face", []string{"hugs"}, "8.0", false},
+	{"\U0001f1ed\U0001f1fa", "flag: Hungary", []string{"hungary"}, "6.0", false},
+	{"\U0001f62f", "hushed face", []string{"hushed"}, "6.1", false},
+	{"\U0001f368", "ice cream", []string{"ice_cream"}, "6.0", false},
+	{"\U0001f9ca", "ice", []string{"ice_cube"}, "12.0", false},
+	{"\U0001f3d2", "ice hockey", []string{"ice_hockey"}, "8.0", false},
+	{"\u26f8\ufe0f", "ice skate", []string{"ice_skate"}, "5.2", false},
+	{"\U0001f366", "soft ice cream", []string{"icecream"}, "6.0", false},
+	{"\U0001f1ee\U0001f1f8", "flag: Iceland", []string{"iceland"}, "6.0", false},
+	{"\U0001f194", "ID button", []string{"id"}, "6.0", false},
+	{"\U0001f250", "Japanese โ€œbargainโ€ button", []string{"ideograph_advantage"}, "6.0", false},
+	{"\U0001f47f", "angry face with horns", []string{"imp"}, "6.0", false},
+	{"\U0001f4e5", "inbox tray", []string{"inbox_tray"}, "6.0", false},
+	{"\U0001f4e8", "incoming envelope", []string{"incoming_envelope"}, "6.0", false},
+	{"\U0001f1ee\U0001f1f3", "flag: India", []string{"india"}, "6.0", false},
+	{"\U0001f1ee\U0001f1e9", "flag: Indonesia", []string{"indonesia"}, "6.0", false},
+	{"\u267e\ufe0f", "infinity", []string{"infinity"}, "11.0", false},
+	{"\u2139\ufe0f", "information", []string{"information_source"}, "3.0", false},
+	{"\U0001f607", "smiling face with halo", []string{"innocent"}, "6.0", false},
+	{"\u2049\ufe0f", "exclamation question mark", []string{"interrobang"}, "3.0", false},
+	{"\U0001f4f1", "mobile phone", []string{"iphone"}, "6.0", false},
+	{"\U0001f1ee\U0001f1f7", "flag: Iran", []string{"iran"}, "6.0", false},
+	{"\U0001f1ee\U0001f1f6", "flag: Iraq", []string{"iraq"}, "6.0", false},
+	{"\U0001f1ee\U0001f1ea", "flag: Ireland", []string{"ireland"}, "6.0", false},
+	{"\U0001f1ee\U0001f1f2", "flag: Isle of Man", []string{"isle_of_man"}, "6.0", false},
+	{"\U0001f1ee\U0001f1f1", "flag: Israel", []string{"israel"}, "6.0", false},
+	{"\U0001f1ee\U0001f1f9", "flag: Italy", []string{"it"}, "6.0", false},
+	{"\U0001f3ee", "red paper lantern", []string{"izakaya_lantern", "lantern"}, "6.0", false},
+	{"\U0001f383", "jack-o-lantern", []string{"jack_o_lantern"}, "6.0", false},
+	{"\U0001f1ef\U0001f1f2", "flag: Jamaica", []string{"jamaica"}, "6.0", false},
+	{"\U0001f5fe", "map of Japan", []string{"japan"}, "6.0", false},
+	{"\U0001f3ef", "Japanese castle", []string{"japanese_castle"}, "6.0", false},
+	{"\U0001f47a", "goblin", []string{"japanese_goblin"}, "6.0", false},
+	{"\U0001f479", "ogre", []string{"japanese_ogre"}, "6.0", false},
+	{"\U0001f456", "jeans", []string{"jeans"}, "6.0", false},
+	{"\U0001f1ef\U0001f1ea", "flag: Jersey", []string{"jersey"}, "6.0", false},
+	{"\U0001f9e9", "puzzle piece", []string{"jigsaw"}, "11.0", false},
+	{"\U0001f1ef\U0001f1f4", "flag: Jordan", []string{"jordan"}, "6.0", false},
+	{"\U0001f602", "face with tears of joy", []string{"joy"}, "6.0", false},
+	{"\U0001f639", "cat with tears of joy", []string{"joy_cat"}, "6.0", false},
+	{"\U0001f579\ufe0f", "joystick", []string{"joystick"}, "7.0", false},
+	{"\U0001f1ef\U0001f1f5", "flag: Japan", []string{"jp"}, "6.0", false},
+	{"\U0001f9d1\u200d\u2696\ufe0f", "judge", []string{"judge"}, "12.1", true},
+	{"\U0001f939", "person juggling", []string{"juggling_person"}, "11.0", true},
+	{"\U0001f54b", "kaaba", []string{"kaaba"}, "8.0", false},
+	{"\U0001f998", "kangaroo", []string{"kangaroo"}, "11.0", false},
+	{"\U0001f1f0\U0001f1ff", "flag: Kazakhstan", []string{"kazakhstan"}, "6.0", false},
+	{"\U0001f1f0\U0001f1ea", "flag: Kenya", []string{"kenya"}, "6.0", false},
+	{"\U0001f511", "key", []string{"key"}, "6.0", false},
+	{"\u2328\ufe0f", "keyboard", []string{"keyboard"}, "", false},
+	{"\U0001f51f", "keycap: 10", []string{"keycap_ten"}, "6.0", false},
+	{"\U0001f6f4", "kick scooter", []string{"kick_scooter"}, "9.0", false},
+	{"\U0001f458", "kimono", []string{"kimono"}, "6.0", false},
+	{"\U0001f1f0\U0001f1ee", "flag: Kiribati", []string{"kiribati"}, "6.0", false},
+	{"\U0001f48b", "kiss mark", []string{"kiss"}, "6.0", false},
+	{"\U0001f617", "kissing face", []string{"kissing"}, "6.1", false},
+	{"\U0001f63d", "kissing cat", []string{"kissing_cat"}, "6.0", false},
+	{"\U0001f61a", "kissing face with closed eyes", []string{"kissing_closed_eyes"}, "6.0", false},
+	{"\U0001f618", "face blowing a kiss", []string{"kissing_heart"}, "6.0", false},
+	{"\U0001f619", "kissing face with smiling eyes", []string{"kissing_smiling_eyes"}, "6.1", false},
+	{"\U0001fa81", "kite", []string{"kite"}, "12.0", false},
+	{"\U0001f95d", "kiwi fruit", []string{"kiwi_fruit"}, "9.0", false},
+	{"\U0001f9ce\u200d\u2642\ufe0f", "man kneeling", []string{"kneeling_man"}, "12.0", true},
+	{"\U0001f9ce", "person kneeling", []string{"kneeling_person"}, "12.0", true},
+	{"\U0001f9ce\u200d\u2640\ufe0f", "woman kneeling", []string{"kneeling_woman"}, "12.0", true},
+	{"\U0001f428", "koala", []string{"koala"}, "6.0", false},
+	{"\U0001f201", "Japanese โ€œhereโ€ button", []string{"koko"}, "6.0", false},
+	{"\U0001f1fd\U0001f1f0", "flag: Kosovo", []string{"kosovo"}, "6.0", false},
+	{"\U0001f1f0\U0001f1f7", "flag: South Korea", []string{"kr"}, "6.0", false},
+	{"\U0001f1f0\U0001f1fc", "flag: Kuwait", []string{"kuwait"}, "6.0", false},
+	{"\U0001f1f0\U0001f1ec", "flag: Kyrgyzstan", []string{"kyrgyzstan"}, "6.0", false},
+	{"\U0001f97c", "lab coat", []string{"lab_coat"}, "11.0", false},
+	{"\U0001f3f7\ufe0f", "label", []string{"label"}, "7.0", false},
+	{"\U0001f94d", "lacrosse", []string{"lacrosse"}, "11.0", false},
+	{"\U0001f41e", "lady beetle", []string{"lady_beetle"}, "6.0", false},
+	{"\U0001f1f1\U0001f1e6", "flag: Laos", []string{"laos"}, "6.0", false},
+	{"\U0001f535", "blue circle", []string{"large_blue_circle"}, "6.0", false},
+	{"\U0001f537", "large blue diamond", []string{"large_blue_diamond"}, "6.0", false},
+	{"\U0001f536", "large orange diamond", []string{"large_orange_diamond"}, "6.0", false},
+	{"\U0001f317", "last quarter moon", []string{"last_quarter_moon"}, "6.0", false},
+	{"\U0001f31c", "last quarter moon face", []string{"last_quarter_moon_with_face"}, "6.0", false},
+	{"\u271d\ufe0f", "latin cross", []string{"latin_cross"}, "", false},
+	{"\U0001f1f1\U0001f1fb", "flag: Latvia", []string{"latvia"}, "6.0", false},
+	{"\U0001f606", "grinning squinting face", []string{"laughing", "satisfied", "laugh"}, "6.0", false},
+	{"\U0001f96c", "leafy green", []string{"leafy_green"}, "11.0", false},
+	{"\U0001f343", "leaf fluttering in wind", []string{"leaves"}, "6.0", false},
+	{"\U0001f1f1\U0001f1e7", "flag: Lebanon", []string{"lebanon"}, "6.0", false},
+	{"\U0001f4d2", "ledger", []string{"ledger"}, "6.0", false},
+	{"\U0001f6c5", "left luggage", []string{"left_luggage"}, "6.0", false},
+	{"\u2194\ufe0f", "left-right arrow", []string{"left_right_arrow"}, "", false},
+	{"\U0001f5e8\ufe0f", "left speech bubble", []string{"left_speech_bubble"}, "11.0", false},
+	{"\u21a9\ufe0f", "right arrow curving left", []string{"leftwards_arrow_with_hook"}, "", false},
+	{"\U0001f9b5", "leg", []string{"leg"}, "11.0", true},
+	{"\U0001f34b", "lemon", []string{"lemon"}, "6.0", false},
+	{"\u264c", "Leo", []string{"leo"}, "", false},
+	{"\U0001f406", "leopard", []string{"leopard"}, "6.0", false},
+	{"\U0001f1f1\U0001f1f8", "flag: Lesotho", []string{"lesotho"}, "6.0", false},
+	{"\U0001f39a\ufe0f", "level slider", []string{"level_slider"}, "7.0", false},
+	{"\U0001f1f1\U0001f1f7", "flag: Liberia", []string{"liberia"}, "6.0", false},
+	{"\u264e", "Libra", []string{"libra"}, "", false},
+	{"\U0001f1f1\U0001f1fe", "flag: Libya", []string{"libya"}, "6.0", false},
+	{"\U0001f1f1\U0001f1ee", "flag: Liechtenstein", []string{"liechtenstein"}, "6.0", false},
+	{"\U0001f688", "light rail", []string{"light_rail"}, "6.0", false},
+	{"\U0001f517", "link", []string{"link"}, "6.0", false},
+	{"\U0001f981", "lion", []string{"lion"}, "8.0", false},
+	{"\U0001f444", "mouth", []string{"lips"}, "6.0", false},
+	{"\U0001f484", "lipstick", []string{"lipstick"}, "6.0", false},
+	{"\U0001f1f1\U0001f1f9", "flag: Lithuania", []string{"lithuania"}, "6.0", false},
+	{"\U0001f98e", "lizard", []string{"lizard"}, "9.0", false},
+	{"\U0001f999", "llama", []string{"llama"}, "11.0", false},
+	{"\U0001f99e", "lobster", []string{"lobster"}, "11.0", false},
+	{"\U0001f512", "locked", []string{"lock"}, "6.0", false},
+	{"\U0001f50f", "locked with pen", []string{"lock_with_ink_pen"}, "6.0", false},
+	{"\U0001f36d", "lollipop", []string{"lollipop"}, "6.0", false},
+	{"\u27bf", "double curly loop", []string{"loop"}, "6.0", false},
+	{"\U0001f9f4", "lotion bottle", []string{"lotion_bottle"}, "11.0", false},
+	{"\U0001f9d8", "person in lotus position", []string{"lotus_position"}, "11.0", true},
+	{"\U0001f9d8\u200d\u2642\ufe0f", "man in lotus position", []string{"lotus_position_man"}, "11.0", true},
+	{"\U0001f9d8\u200d\u2640\ufe0f", "woman in lotus position", []string{"lotus_position_woman"}, "11.0", true},
+	{"\U0001f50a", "speaker high volume", []string{"loud_sound"}, "6.0", false},
+	{"\U0001f4e2", "loudspeaker", []string{"loudspeaker"}, "6.0", false},
+	{"\U0001f3e9", "love hotel", []string{"love_hotel"}, "6.0", false},
+	{"\U0001f48c", "love letter", []string{"love_letter"}, "6.0", false},
+	{"\U0001f91f", "love-you gesture", []string{"love_you_gesture"}, "11.0", true},
+	{"\U0001f505", "dim button", []string{"low_brightness"}, "6.0", false},
+	{"\U0001f9f3", "luggage", []string{"luggage"}, "11.0", false},
+	{"\U0001f1f1\U0001f1fa", "flag: Luxembourg", []string{"luxembourg"}, "6.0", false},
+	{"\U0001f925", "lying face", []string{"lying_face"}, "9.0", false},
+	{"\u24c2\ufe0f", "circled M", []string{"m"}, "", false},
+	{"\U0001f1f2\U0001f1f4", "flag: Macao SAR China", []string{"macau"}, "6.0", false},
+	{"\U0001f1f2\U0001f1f0", "flag: North Macedonia", []string{"macedonia"}, "6.0", false},
+	{"\U0001f1f2\U0001f1ec", "flag: Madagascar", []string{"madagascar"}, "6.0", false},
+	{"\U0001f50d", "magnifying glass tilted left", []string{"mag"}, "6.0", false},
+	{"\U0001f50e", "magnifying glass tilted right", []string{"mag_right"}, "6.0", false},
+	{"\U0001f9d9", "mage", []string{"mage"}, "11.0", true},
+	{"\U0001f9d9\u200d\u2642\ufe0f", "man mage", []string{"mage_man"}, "11.0", true},
+	{"\U0001f9d9\u200d\u2640\ufe0f", "woman mage", []string{"mage_woman"}, "11.0", true},
+	{"\U0001f9f2", "magnet", []string{"magnet"}, "11.0", false},
+	{"\U0001f004", "mahjong red dragon", []string{"mahjong"}, "", false},
+	{"\U0001f4eb", "closed mailbox with raised flag", []string{"mailbox"}, "6.0", false},
+	{"\U0001f4ea", "closed mailbox with lowered flag", []string{"mailbox_closed"}, "6.0", false},
+	{"\U0001f4ec", "open mailbox with raised flag", []string{"mailbox_with_mail"}, "6.0", false},
+	{"\U0001f4ed", "open mailbox with lowered flag", []string{"mailbox_with_no_mail"}, "6.0", false},
+	{"\U0001f1f2\U0001f1fc", "flag: Malawi", []string{"malawi"}, "6.0", false},
+	{"\U0001f1f2\U0001f1fe", "flag: Malaysia", []string{"malaysia"}, "6.0", false},
+	{"\U0001f1f2\U0001f1fb", "flag: Maldives", []string{"maldives"}, "6.0", false},
+	{"\U0001f575\ufe0f\u200d\u2642\ufe0f", "man detective", []string{"male_detective"}, "11.0", true},
+	{"\u2642\ufe0f", "male sign", []string{"male_sign"}, "11.0", false},
+	{"\U0001f1f2\U0001f1f1", "flag: Mali", []string{"mali"}, "6.0", false},
+	{"\U0001f1f2\U0001f1f9", "flag: Malta", []string{"malta"}, "6.0", false},
+	{"\U0001f468", "man", []string{"man"}, "6.0", true},
+	{"\U0001f468\u200d\U0001f3a8", "man artist", []string{"man_artist"}, "", true},
+	{"\U0001f468\u200d\U0001f680", "man astronaut", []string{"man_astronaut"}, "", true},
+	{"\U0001f938\u200d\u2642\ufe0f", "man cartwheeling", []string{"man_cartwheeling"}, "", true},
+	{"\U0001f468\u200d\U0001f373", "man cook", []string{"man_cook"}, "", true},
+	{"\U0001f57a", "man dancing", []string{"man_dancing"}, "9.0", true},
+	{"\U0001f926\u200d\u2642\ufe0f", "man facepalming", []string{"man_facepalming"}, "9.0", true},
+	{"\U0001f468\u200d\U0001f3ed", "man factory worker", []string{"man_factory_worker"}, "", true},
+	{"\U0001f468\u200d\U0001f33e", "man farmer", []string{"man_farmer"}, "", true},
+	{"\U0001f468\u200d\U0001f692", "man firefighter", []string{"man_firefighter"}, "", true},
+	{"\U0001f468\u200d\u2695\ufe0f", "man health worker", []string{"man_health_worker"}, "", true},
+	{"\U0001f468\u200d\U0001f9bd", "man in manual wheelchair", []string{"man_in_manual_wheelchair"}, "12.0", true},
+	{"\U0001f468\u200d\U0001f9bc", "man in motorized wheelchair", []string{"man_in_motorized_wheelchair"}, "12.0", true},
+	{"\U0001f468\u200d\u2696\ufe0f", "man judge", []string{"man_judge"}, "", true},
+	{"\U0001f939\u200d\u2642\ufe0f", "man juggling", []string{"man_juggling"}, "9.0", true},
+	{"\U0001f468\u200d\U0001f527", "man mechanic", []string{"man_mechanic"}, "", true},
+	{"\U0001f468\u200d\U0001f4bc", "man office worker", []string{"man_office_worker"}, "", true},
+	{"\U0001f468\u200d\u2708\ufe0f", "man pilot", []string{"man_pilot"}, "", true},
+	{"\U0001f93e\u200d\u2642\ufe0f", "man playing handball", []string{"man_playing_handball"}, "9.0", true},
+	{"\U0001f93d\u200d\u2642\ufe0f", "man playing water polo", []string{"man_playing_water_polo"}, "9.0", true},
+	{"\U0001f468\u200d\U0001f52c", "man scientist", []string{"man_scientist"}, "", true},
+	{"\U0001f937\u200d\u2642\ufe0f", "man shrugging", []string{"man_shrugging"}, "9.0", true},
+	{"\U0001f468\u200d\U0001f3a4", "man singer", []string{"man_singer"}, "", true},
+	{"\U0001f468\u200d\U0001f393", "man student", []string{"man_student"}, "", true},
+	{"\U0001f468\u200d\U0001f3eb", "man teacher", []string{"man_teacher"}, "", true},
+	{"\U0001f468\u200d\U0001f4bb", "man technologist", []string{"man_technologist"}, "", true},
+	{"\U0001f472", "person with skullcap", []string{"man_with_gua_pi_mao"}, "6.0", true},
+	{"\U0001f468\u200d\U0001f9af", "man with white cane", []string{"man_with_probing_cane"}, "12.0", true},
+	{"\U0001f473\u200d\u2642\ufe0f", "man wearing turban", []string{"man_with_turban"}, "11.0", true},
+	{"\U0001f96d", "mango", []string{"mango"}, "11.0", false},
+	{"\U0001f45e", "manโ€™s shoe", []string{"mans_shoe", "shoe"}, "6.0", false},
+	{"\U0001f570\ufe0f", "mantelpiece clock", []string{"mantelpiece_clock"}, "7.0", false},
+	{"\U0001f9bd", "manual wheelchair", []string{"manual_wheelchair"}, "12.0", false},
+	{"\U0001f341", "maple leaf", []string{"maple_leaf"}, "6.0", false},
+	{"\U0001f1f2\U0001f1ed", "flag: Marshall Islands", []string{"marshall_islands"}, "6.0", false},
+	{"\U0001f94b", "martial arts uniform", []string{"martial_arts_uniform"}, "9.0", false},
+	{"\U0001f1f2\U0001f1f6", "flag: Martinique", []string{"martinique"}, "6.0", false},
+	{"\U0001f637", "face with medical mask", []string{"mask"}, "6.0", false},
+	{"\U0001f486", "person getting massage", []string{"massage"}, "6.0", true},
+	{"\U0001f486\u200d\u2642\ufe0f", "man getting massage", []string{"massage_man"}, "6.0", true},
+	{"\U0001f486\u200d\u2640\ufe0f", "woman getting massage", []string{"massage_woman"}, "11.0", true},
+	{"\U0001f9c9", "mate", []string{"mate"}, "12.0", false},
+	{"\U0001f1f2\U0001f1f7", "flag: Mauritania", []string{"mauritania"}, "6.0", false},
+	{"\U0001f1f2\U0001f1fa", "flag: Mauritius", []string{"mauritius"}, "6.0", false},
+	{"\U0001f1fe\U0001f1f9", "flag: Mayotte", []string{"mayotte"}, "6.0", false},
+	{"\U0001f356", "meat on bone", []string{"meat_on_bone"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f527", "mechanic", []string{"mechanic"}, "12.1", true},
+	{"\U0001f9be", "mechanical arm", []string{"mechanical_arm"}, "12.0", false},
+	{"\U0001f9bf", "mechanical leg", []string{"mechanical_leg"}, "12.0", false},
+	{"\U0001f396\ufe0f", "military medal", []string{"medal_military"}, "7.0", false},
+	{"\U0001f3c5", "sports medal", []string{"medal_sports"}, "7.0", false},
+	{"\u2695\ufe0f", "medical symbol", []string{"medical_symbol"}, "11.0", false},
+	{"\U0001f4e3", "megaphone", []string{"mega"}, "6.0", false},
+	{"\U0001f348", "melon", []string{"melon"}, "6.0", false},
+	{"\U0001f4dd", "memo", []string{"memo", "pencil"}, "6.0", false},
+	{"\U0001f93c\u200d\u2642\ufe0f", "men wrestling", []string{"men_wrestling"}, "9.0", false},
+	{"\U0001f54e", "menorah", []string{"menorah"}, "8.0", false},
+	{"\U0001f6b9", "menโ€™s room", []string{"mens"}, "6.0", false},
+	{"\U0001f9dc\u200d\u2640\ufe0f", "mermaid", []string{"mermaid"}, "11.0", true},
+	{"\U0001f9dc\u200d\u2642\ufe0f", "merman", []string{"merman"}, "11.0", true},
+	{"\U0001f9dc", "merperson", []string{"merperson"}, "11.0", true},
+	{"\U0001f918", "sign of the horns", []string{"metal"}, "8.0", true},
+	{"\U0001f687", "metro", []string{"metro"}, "6.0", false},
+	{"\U0001f1f2\U0001f1fd", "flag: Mexico", []string{"mexico"}, "6.0", false},
+	{"\U0001f9a0", "microbe", []string{"microbe"}, "11.0", false},
+	{"\U0001f1eb\U0001f1f2", "flag: Micronesia", []string{"micronesia"}, "6.0", false},
+	{"\U0001f3a4", "microphone", []string{"microphone"}, "6.0", false},
+	{"\U0001f52c", "microscope", []string{"microscope"}, "6.0", false},
+	{"\U0001f595", "middle finger", []string{"middle_finger", "fu"}, "7.0", true},
+	{"\U0001f95b", "glass of milk", []string{"milk_glass"}, "9.0", false},
+	{"\U0001f30c", "milky way", []string{"milky_way"}, "6.0", false},
+	{"\U0001f690", "minibus", []string{"minibus"}, "6.0", false},
+	{"\U0001f4bd", "computer disk", []string{"minidisc"}, "6.0", false},
+	{"\U0001f4f4", "mobile phone off", []string{"mobile_phone_off"}, "6.0", false},
+	{"\U0001f1f2\U0001f1e9", "flag: Moldova", []string{"moldova"}, "6.0", false},
+	{"\U0001f1f2\U0001f1e8", "flag: Monaco", []string{"monaco"}, "6.0", false},
+	{"\U0001f911", "money-mouth face", []string{"money_mouth_face"}, "8.0", false},
+	{"\U0001f4b8", "money with wings", []string{"money_with_wings"}, "6.0", false},
+	{"\U0001f4b0", "money bag", []string{"moneybag"}, "6.0", false},
+	{"\U0001f1f2\U0001f1f3", "flag: Mongolia", []string{"mongolia"}, "6.0", false},
+	{"\U0001f412", "monkey", []string{"monkey"}, "6.0", false},
+	{"\U0001f435", "monkey face", []string{"monkey_face"}, "6.0", false},
+	{"\U0001f9d0", "face with monocle", []string{"monocle_face"}, "11.0", false},
+	{"\U0001f69d", "monorail", []string{"monorail"}, "6.0", false},
+	{"\U0001f1f2\U0001f1ea", "flag: Montenegro", []string{"montenegro"}, "6.0", false},
+	{"\U0001f1f2\U0001f1f8", "flag: Montserrat", []string{"montserrat"}, "6.0", false},
+	{"\U0001f314", "waxing gibbous moon", []string{"moon", "waxing_gibbous_moon"}, "6.0", false},
+	{"\U0001f96e", "moon cake", []string{"moon_cake"}, "11.0", false},
+	{"\U0001f1f2\U0001f1e6", "flag: Morocco", []string{"morocco"}, "6.0", false},
+	{"\U0001f393", "graduation cap", []string{"mortar_board"}, "6.0", false},
+	{"\U0001f54c", "mosque", []string{"mosque"}, "8.0", false},
+	{"\U0001f99f", "mosquito", []string{"mosquito"}, "11.0", false},
+	{"\U0001f6e5\ufe0f", "motor boat", []string{"motor_boat"}, "7.0", false},
+	{"\U0001f6f5", "motor scooter", []string{"motor_scooter"}, "9.0", false},
+	{"\U0001f3cd\ufe0f", "motorcycle", []string{"motorcycle"}, "7.0", false},
+	{"\U0001f9bc", "motorized wheelchair", []string{"motorized_wheelchair"}, "12.0", false},
+	{"\U0001f6e3\ufe0f", "motorway", []string{"motorway"}, "7.0", false},
+	{"\U0001f5fb", "mount fuji", []string{"mount_fuji"}, "6.0", false},
+	{"\u26f0\ufe0f", "mountain", []string{"mountain"}, "5.2", false},
+	{"\U0001f6b5", "person mountain biking", []string{"mountain_bicyclist"}, "6.0", true},
+	{"\U0001f6b5\u200d\u2642\ufe0f", "man mountain biking", []string{"mountain_biking_man"}, "11.0", true},
+	{"\U0001f6b5\u200d\u2640\ufe0f", "woman mountain biking", []string{"mountain_biking_woman"}, "6.0", true},
+	{"\U0001f6a0", "mountain cableway", []string{"mountain_cableway"}, "6.0", false},
+	{"\U0001f69e", "mountain railway", []string{"mountain_railway"}, "6.0", false},
+	{"\U0001f3d4\ufe0f", "snow-capped mountain", []string{"mountain_snow"}, "7.0", false},
+	{"\U0001f42d", "mouse face", []string{"mouse"}, "6.0", false},
+	{"\U0001f401", "mouse", []string{"mouse2"}, "6.0", false},
+	{"\U0001f3a5", "movie camera", []string{"movie_camera"}, "6.0", false},
+	{"\U0001f5ff", "moai", []string{"moyai"}, "6.0", false},
+	{"\U0001f1f2\U0001f1ff", "flag: Mozambique", []string{"mozambique"}, "6.0", false},
+	{"\U0001f936", "Mrs. Claus", []string{"mrs_claus"}, "9.0", true},
+	{"\U0001f4aa", "flexed biceps", []string{"muscle"}, "6.0", true},
+	{"\U0001f344", "mushroom", []string{"mushroom"}, "6.0", false},
+	{"\U0001f3b9", "musical keyboard", []string{"musical_keyboard"}, "6.0", false},
+	{"\U0001f3b5", "musical note", []string{"musical_note"}, "6.0", false},
+	{"\U0001f3bc", "musical score", []string{"musical_score"}, "6.0", false},
+	{"\U0001f507", "muted speaker", []string{"mute"}, "6.0", false},
+	{"\U0001f1f2\U0001f1f2", "flag: Myanmar (Burma)", []string{"myanmar"}, "6.0", false},
+	{"\U0001f485", "nail polish", []string{"nail_care"}, "6.0", true},
+	{"\U0001f4db", "name badge", []string{"name_badge"}, "6.0", false},
+	{"\U0001f1f3\U0001f1e6", "flag: Namibia", []string{"namibia"}, "6.0", false},
+	{"\U0001f3de\ufe0f", "national park", []string{"national_park"}, "7.0", false},
+	{"\U0001f1f3\U0001f1f7", "flag: Nauru", []string{"nauru"}, "6.0", false},
+	{"\U0001f922", "nauseated face", []string{"nauseated_face"}, "9.0", false},
+	{"\U0001f9ff", "nazar amulet", []string{"nazar_amulet"}, "11.0", false},
+	{"\U0001f454", "necktie", []string{"necktie"}, "6.0", false},
+	{"\u274e", "cross mark button", []string{"negative_squared_cross_mark"}, "6.0", false},
+	{"\U0001f1f3\U0001f1f5", "flag: Nepal", []string{"nepal"}, "6.0", false},
+	{"\U0001f913", "nerd face", []string{"nerd_face"}, "8.0", false},
+	{"\U0001f1f3\U0001f1f1", "flag: Netherlands", []string{"netherlands"}, "6.0", false},
+	{"\U0001f610", "neutral face", []string{"neutral_face"}, "6.0", false},
+	{"\U0001f195", "NEW button", []string{"new"}, "6.0", false},
+	{"\U0001f1f3\U0001f1e8", "flag: New Caledonia", []string{"new_caledonia"}, "6.0", false},
+	{"\U0001f311", "new moon", []string{"new_moon"}, "6.0", false},
+	{"\U0001f31a", "new moon face", []string{"new_moon_with_face"}, "6.0", false},
+	{"\U0001f1f3\U0001f1ff", "flag: New Zealand", []string{"new_zealand"}, "6.0", false},
+	{"\U0001f4f0", "newspaper", []string{"newspaper"}, "6.0", false},
+	{"\U0001f5de\ufe0f", "rolled-up newspaper", []string{"newspaper_roll"}, "7.0", false},
+	{"\u23ed\ufe0f", "next track button", []string{"next_track_button"}, "6.0", false},
+	{"\U0001f196", "NG button", []string{"ng"}, "6.0", false},
+	{"\U0001f1f3\U0001f1ee", "flag: Nicaragua", []string{"nicaragua"}, "6.0", false},
+	{"\U0001f1f3\U0001f1ea", "flag: Niger", []string{"niger"}, "6.0", false},
+	{"\U0001f1f3\U0001f1ec", "flag: Nigeria", []string{"nigeria"}, "6.0", false},
+	{"\U0001f303", "night with stars", []string{"night_with_stars"}, "6.0", false},
+	{"9\ufe0f\u20e3", "keycap: 9", []string{"nine"}, "", false},
+	{"\U0001f1f3\U0001f1fa", "flag: Niue", []string{"niue"}, "6.0", false},
+	{"\U0001f515", "bell with slash", []string{"no_bell"}, "6.0", false},
+	{"\U0001f6b3", "no bicycles", []string{"no_bicycles"}, "6.0", false},
+	{"\u26d4", "no entry", []string{"no_entry"}, "5.2", false},
+	{"\U0001f6ab", "prohibited", []string{"no_entry_sign"}, "6.0", false},
+	{"\U0001f645", "person gesturing NO", []string{"no_good"}, "6.0", true},
+	{"\U0001f645\u200d\u2642\ufe0f", "man gesturing NO", []string{"no_good_man", "ng_man"}, "6.0", true},
+	{"\U0001f645\u200d\u2640\ufe0f", "woman gesturing NO", []string{"no_good_woman", "ng_woman"}, "11.0", true},
+	{"\U0001f4f5", "no mobile phones", []string{"no_mobile_phones"}, "6.0", false},
+	{"\U0001f636", "face without mouth", []string{"no_mouth"}, "6.0", false},
+	{"\U0001f6b7", "no pedestrians", []string{"no_pedestrians"}, "6.0", false},
+	{"\U0001f6ad", "no smoking", []string{"no_smoking"}, "6.0", false},
+	{"\U0001f6b1", "non-potable water", []string{"non-potable_water"}, "6.0", false},
+	{"\U0001f1f3\U0001f1eb", "flag: Norfolk Island", []string{"norfolk_island"}, "6.0", false},
+	{"\U0001f1f0\U0001f1f5", "flag: North Korea", []string{"north_korea"}, "6.0", false},
+	{"\U0001f1f2\U0001f1f5", "flag: Northern Mariana Islands", []string{"northern_mariana_islands"}, "6.0", false},
+	{"\U0001f1f3\U0001f1f4", "flag: Norway", []string{"norway"}, "6.0", false},
+	{"\U0001f443", "nose", []string{"nose"}, "6.0", true},
+	{"\U0001f4d3", "notebook", []string{"notebook"}, "6.0", false},
+	{"\U0001f4d4", "notebook with decorative cover", []string{"notebook_with_decorative_cover"}, "6.0", false},
+	{"\U0001f3b6", "musical notes", []string{"notes"}, "6.0", false},
+	{"\U0001f529", "nut and bolt", []string{"nut_and_bolt"}, "6.0", false},
+	{"\u2b55", "hollow red circle", []string{"o"}, "5.2", false},
+	{"\U0001f17e\ufe0f", "O button (blood type)", []string{"o2"}, "6.0", false},
+	{"\U0001f30a", "water wave", []string{"ocean"}, "6.0", false},
+	{"\U0001f419", "octopus", []string{"octopus"}, "6.0", false},
+	{"\U0001f362", "oden", []string{"oden"}, "6.0", false},
+	{"\U0001f3e2", "office building", []string{"office"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f4bc", "office worker", []string{"office_worker"}, "12.1", true},
+	{"\U0001f6e2\ufe0f", "oil drum", []string{"oil_drum"}, "7.0", false},
+	{"\U0001f197", "OK button", []string{"ok"}, "6.0", false},
+	{"\U0001f44c", "OK hand", []string{"ok_hand"}, "6.0", true},
+	{"\U0001f646\u200d\u2642\ufe0f", "man gesturing OK", []string{"ok_man"}, "6.0", true},
+	{"\U0001f646", "person gesturing OK", []string{"ok_person"}, "6.0", true},
+	{"\U0001f646\u200d\u2640\ufe0f", "woman gesturing OK", []string{"ok_woman"}, "11.0", true},
+	{"\U0001f5dd\ufe0f", "old key", []string{"old_key"}, "7.0", false},
+	{"\U0001f9d3", "older person", []string{"older_adult"}, "11.0", true},
+	{"\U0001f474", "old man", []string{"older_man"}, "6.0", true},
+	{"\U0001f475", "old woman", []string{"older_woman"}, "6.0", true},
+	{"\U0001f549\ufe0f", "om", []string{"om"}, "7.0", false},
+	{"\U0001f1f4\U0001f1f2", "flag: Oman", []string{"oman"}, "6.0", false},
+	{"\U0001f51b", "ON! arrow", []string{"on"}, "6.0", false},
+	{"\U0001f698", "oncoming automobile", []string{"oncoming_automobile"}, "6.0", false},
+	{"\U0001f68d", "oncoming bus", []string{"oncoming_bus"}, "6.0", false},
+	{"\U0001f694", "oncoming police car", []string{"oncoming_police_car"}, "6.0", false},
+	{"\U0001f696", "oncoming taxi", []string{"oncoming_taxi"}, "6.0", false},
+	{"1\ufe0f\u20e3", "keycap: 1", []string{"one"}, "", false},
+	{"\U0001fa71", "one-piece swimsuit", []string{"one_piece_swimsuit"}, "12.0", false},
+	{"\U0001f9c5", "onion", []string{"onion"}, "12.0", false},
+	{"\U0001f4c2", "open file folder", []string{"open_file_folder"}, "6.0", false},
+	{"\U0001f450", "open hands", []string{"open_hands"}, "6.0", true},
+	{"\U0001f62e", "face with open mouth", []string{"open_mouth"}, "6.1", false},
+	{"\u2602\ufe0f", "umbrella", []string{"open_umbrella"}, "", false},
+	{"\u26ce", "Ophiuchus", []string{"ophiuchus"}, "6.0", false},
+	{"\U0001f4d9", "orange book", []string{"orange_book"}, "6.0", false},
+	{"\U0001f7e0", "orange circle", []string{"orange_circle"}, "12.0", false},
+	{"\U0001f9e1", "orange heart", []string{"orange_heart"}, "11.0", false},
+	{"\U0001f7e7", "orange square", []string{"orange_square"}, "12.0", false},
+	{"\U0001f9a7", "orangutan", []string{"orangutan"}, "12.0", false},
+	{"\u2626\ufe0f", "orthodox cross", []string{"orthodox_cross"}, "", false},
+	{"\U0001f9a6", "otter", []string{"otter"}, "12.0", false},
+	{"\U0001f4e4", "outbox tray", []string{"outbox_tray"}, "6.0", false},
+	{"\U0001f989", "owl", []string{"owl"}, "9.0", false},
+	{"\U0001f402", "ox", []string{"ox"}, "6.0", false},
+	{"\U0001f9aa", "oyster", []string{"oyster"}, "12.0", false},
+	{"\U0001f4e6", "package", []string{"package"}, "6.0", false},
+	{"\U0001f4c4", "page facing up", []string{"page_facing_up"}, "6.0", false},
+	{"\U0001f4c3", "page with curl", []string{"page_with_curl"}, "6.0", false},
+	{"\U0001f4df", "pager", []string{"pager"}, "6.0", false},
+	{"\U0001f58c\ufe0f", "paintbrush", []string{"paintbrush"}, "7.0", false},
+	{"\U0001f1f5\U0001f1f0", "flag: Pakistan", []string{"pakistan"}, "6.0", false},
+	{"\U0001f1f5\U0001f1fc", "flag: Palau", []string{"palau"}, "6.0", false},
+	{"\U0001f1f5\U0001f1f8", "flag: Palestinian Territories", []string{"palestinian_territories"}, "6.0", false},
+	{"\U0001f334", "palm tree", []string{"palm_tree"}, "6.0", false},
+	{"\U0001f932", "palms up together", []string{"palms_up_together"}, "11.0", true},
+	{"\U0001f1f5\U0001f1e6", "flag: Panama", []string{"panama"}, "6.0", false},
+	{"\U0001f95e", "pancakes", []string{"pancakes"}, "9.0", false},
+	{"\U0001f43c", "panda", []string{"panda_face"}, "6.0", false},
+	{"\U0001f4ce", "paperclip", []string{"paperclip"}, "6.0", false},
+	{"\U0001f587\ufe0f", "linked paperclips", []string{"paperclips"}, "7.0", false},
+	{"\U0001f1f5\U0001f1ec", "flag: Papua New Guinea", []string{"papua_new_guinea"}, "6.0", false},
+	{"\U0001fa82", "parachute", []string{"parachute"}, "12.0", false},
+	{"\U0001f1f5\U0001f1fe", "flag: Paraguay", []string{"paraguay"}, "6.0", false},
+	{"\u26f1\ufe0f", "umbrella on ground", []string{"parasol_on_ground"}, "5.2", false},
+	{"\U0001f17f\ufe0f", "P button", []string{"parking"}, "5.2", false},
+	{"\U0001f99c", "parrot", []string{"parrot"}, "11.0", false},
+	{"\u303d\ufe0f", "part alternation mark", []string{"part_alternation_mark"}, "3.2", false},
+	{"\u26c5", "sun behind cloud", []string{"partly_sunny"}, "5.2", false},
+	{"\U0001f973", "partying face", []string{"partying_face"}, "11.0", false},
+	{"\U0001f6f3\ufe0f", "passenger ship", []string{"passenger_ship"}, "7.0", false},
+	{"\U0001f6c2", "passport control", []string{"passport_control"}, "6.0", false},
+	{"\u23f8\ufe0f", "pause button", []string{"pause_button"}, "7.0", false},
+	{"\u262e\ufe0f", "peace symbol", []string{"peace_symbol"}, "", false},
+	{"\U0001f351", "peach", []string{"peach"}, "6.0", false},
+	{"\U0001f99a", "peacock", []string{"peacock"}, "11.0", false},
+	{"\U0001f95c", "peanuts", []string{"peanuts"}, "9.0", false},
+	{"\U0001f350", "pear", []string{"pear"}, "6.0", false},
+	{"\U0001f58a\ufe0f", "pen", []string{"pen"}, "7.0", false},
+	{"\u270f\ufe0f", "pencil", []string{"pencil2"}, "", false},
+	{"\U0001f427", "penguin", []string{"penguin"}, "6.0", false},
+	{"\U0001f614", "pensive face", []string{"pensive"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands", []string{"people_holding_hands"}, "12.0", true},
+	{"\U0001f3ad", "performing arts", []string{"performing_arts"}, "6.0", false},
+	{"\U0001f623", "persevering face", []string{"persevere"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f9b2", "person: bald", []string{"person_bald"}, "12.1", true},
+	{"\U0001f9d1\u200d\U0001f9b1", "person: curly hair", []string{"person_curly_hair"}, "12.1", true},
+	{"\U0001f93a", "person fencing", []string{"person_fencing"}, "9.0", false},
+	{"\U0001f9d1\u200d\U0001f9bd", "person in manual wheelchair", []string{"person_in_manual_wheelchair"}, "12.1", true},
+	{"\U0001f9d1\u200d\U0001f9bc", "person in motorized wheelchair", []string{"person_in_motorized_wheelchair"}, "12.1", true},
+	{"\U0001f935", "person in tuxedo", []string{"person_in_tuxedo"}, "9.0", true},
+	{"\U0001f9d1\u200d\U0001f9b0", "person: red hair", []string{"person_red_hair"}, "12.1", true},
+	{"\U0001f9d1\u200d\U0001f9b3", "person: white hair", []string{"person_white_hair"}, "12.1", true},
+	{"\U0001f9d1\u200d\U0001f9af", "person with white cane", []string{"person_with_probing_cane"}, "12.1", true},
+	{"\U0001f473", "person wearing turban", []string{"person_with_turban"}, "6.0", true},
+	{"\U0001f470", "person with veil", []string{"person_with_veil"}, "6.0", true},
+	{"\U0001f1f5\U0001f1ea", "flag: Peru", []string{"peru"}, "6.0", false},
+	{"\U0001f9eb", "petri dish", []string{"petri_dish"}, "11.0", false},
+	{"\U0001f1f5\U0001f1ed", "flag: Philippines", []string{"philippines"}, "6.0", false},
+	{"\u260e\ufe0f", "telephone", []string{"phone", "telephone"}, "", false},
+	{"\u26cf\ufe0f", "pick", []string{"pick"}, "5.2", false},
+	{"\U0001f967", "pie", []string{"pie"}, "11.0", false},
+	{"\U0001f437", "pig face", []string{"pig"}, "6.0", false},
+	{"\U0001f416", "pig", []string{"pig2"}, "6.0", false},
+	{"\U0001f43d", "pig nose", []string{"pig_nose"}, "6.0", false},
+	{"\U0001f48a", "pill", []string{"pill"}, "6.0", false},
+	{"\U0001f9d1\u200d\u2708\ufe0f", "pilot", []string{"pilot"}, "12.1", true},
+	{"\U0001f90f", "pinching hand", []string{"pinching_hand"}, "12.0", true},
+	{"\U0001f34d", "pineapple", []string{"pineapple"}, "6.0", false},
+	{"\U0001f3d3", "ping pong", []string{"ping_pong"}, "8.0", false},
+	{"\U0001f3f4\u200d\u2620\ufe0f", "pirate flag", []string{"pirate_flag"}, "11.0", false},
+	{"\u2653", "Pisces", []string{"pisces"}, "", false},
+	{"\U0001f1f5\U0001f1f3", "flag: Pitcairn Islands", []string{"pitcairn_islands"}, "6.0", false},
+	{"\U0001f355", "pizza", []string{"pizza"}, "6.0", false},
+	{"\U0001f6d0", "place of worship", []string{"place_of_worship"}, "8.0", false},
+	{"\U0001f37d\ufe0f", "fork and knife with plate", []string{"plate_with_cutlery"}, "7.0", false},
+	{"\u23ef\ufe0f", "play or pause button", []string{"play_or_pause_button"}, "6.0", false},
+	{"\U0001f97a", "pleading face", []string{"pleading_face"}, "11.0", false},
+	{"\U0001f447", "backhand index pointing down", []string{"point_down"}, "6.0", true},
+	{"\U0001f448", "backhand index pointing left", []string{"point_left"}, "6.0", true},
+	{"\U0001f449", "backhand index pointing right", []string{"point_right"}, "6.0", true},
+	{"\u261d\ufe0f", "index pointing up", []string{"point_up"}, "", true},
+	{"\U0001f446", "backhand index pointing up", []string{"point_up_2"}, "6.0", true},
+	{"\U0001f1f5\U0001f1f1", "flag: Poland", []string{"poland"}, "6.0", false},
+	{"\U0001f693", "police car", []string{"police_car"}, "6.0", false},
+	{"\U0001f46e", "police officer", []string{"police_officer", "cop"}, "6.0", true},
+	{"\U0001f46e\u200d\u2642\ufe0f", "man police officer", []string{"policeman"}, "11.0", true},
+	{"\U0001f46e\u200d\u2640\ufe0f", "woman police officer", []string{"policewoman"}, "6.0", true},
+	{"\U0001f429", "poodle", []string{"poodle"}, "6.0", false},
+	{"\U0001f37f", "popcorn", []string{"popcorn"}, "8.0", false},
+	{"\U0001f1f5\U0001f1f9", "flag: Portugal", []string{"portugal"}, "6.0", false},
+	{"\U0001f3e3", "Japanese post office", []string{"post_office"}, "6.0", false},
+	{"\U0001f4ef", "postal horn", []string{"postal_horn"}, "6.0", false},
+	{"\U0001f4ee", "postbox", []string{"postbox"}, "6.0", false},
+	{"\U0001f6b0", "potable water", []string{"potable_water"}, "6.0", false},
+	{"\U0001f954", "potato", []string{"potato"}, "9.0", false},
+	{"\U0001f45d", "clutch bag", []string{"pouch"}, "6.0", false},
+	{"\U0001f357", "poultry leg", []string{"poultry_leg"}, "6.0", false},
+	{"\U0001f4b7", "pound banknote", []string{"pound"}, "6.0", false},
+	{"\U0001f63e", "pouting cat", []string{"pouting_cat"}, "6.0", false},
+	{"\U0001f64e", "person pouting", []string{"pouting_face"}, "6.0", true},
+	{"\U0001f64e\u200d\u2642\ufe0f", "man pouting", []string{"pouting_man"}, "6.0", true},
+	{"\U0001f64e\u200d\u2640\ufe0f", "woman pouting", []string{"pouting_woman"}, "11.0", true},
+	{"\U0001f64f", "folded hands", []string{"pray"}, "6.0", true},
+	{"\U0001f4ff", "prayer beads", []string{"prayer_beads"}, "8.0", false},
+	{"\U0001f930", "pregnant woman", []string{"pregnant_woman"}, "9.0", true},
+	{"\U0001f968", "pretzel", []string{"pretzel"}, "11.0", false},
+	{"\u23ee\ufe0f", "last track button", []string{"previous_track_button"}, "6.0", false},
+	{"\U0001f934", "prince", []string{"prince"}, "9.0", true},
+	{"\U0001f478", "princess", []string{"princess"}, "6.0", true},
+	{"\U0001f5a8\ufe0f", "printer", []string{"printer"}, "7.0", false},
+	{"\U0001f9af", "white cane", []string{"probing_cane"}, "12.0", false},
+	{"\U0001f1f5\U0001f1f7", "flag: Puerto Rico", []string{"puerto_rico"}, "6.0", false},
+	{"\U0001f7e3", "purple circle", []string{"purple_circle"}, "12.0", false},
+	{"\U0001f49c", "purple heart", []string{"purple_heart"}, "6.0", false},
+	{"\U0001f7ea", "purple square", []string{"purple_square"}, "12.0", false},
+	{"\U0001f45b", "purse", []string{"purse"}, "6.0", false},
+	{"\U0001f4cc", "pushpin", []string{"pushpin"}, "6.0", false},
+	{"\U0001f6ae", "litter in bin sign", []string{"put_litter_in_its_place"}, "6.0", false},
+	{"\U0001f1f6\U0001f1e6", "flag: Qatar", []string{"qatar"}, "6.0", false},
+	{"\u2753", "question mark", []string{"question"}, "6.0", false},
+	{"\U0001f430", "rabbit face", []string{"rabbit"}, "6.0", false},
+	{"\U0001f407", "rabbit", []string{"rabbit2"}, "6.0", false},
+	{"\U0001f99d", "raccoon", []string{"raccoon"}, "11.0", false},
+	{"\U0001f40e", "horse", []string{"racehorse"}, "6.0", false},
+	{"\U0001f3ce\ufe0f", "racing car", []string{"racing_car"}, "7.0", false},
+	{"\U0001f4fb", "radio", []string{"radio"}, "6.0", false},
+	{"\U0001f518", "radio button", []string{"radio_button"}, "6.0", false},
+	{"\u2622\ufe0f", "radioactive", []string{"radioactive"}, "", false},
+	{"\U0001f621", "pouting face", []string{"rage", "pout"}, "6.0", false},
+	{"\U0001f683", "railway car", []string{"railway_car"}, "6.0", false},
+	{"\U0001f6e4\ufe0f", "railway track", []string{"railway_track"}, "7.0", false},
+	{"\U0001f308", "rainbow", []string{"rainbow"}, "6.0", false},
+	{"\U0001f3f3\ufe0f\u200d\U0001f308", "rainbow flag", []string{"rainbow_flag"}, "6.0", false},
+	{"\U0001f91a", "raised back of hand", []string{"raised_back_of_hand"}, "9.0", true},
+	{"\U0001f928", "face with raised eyebrow", []string{"raised_eyebrow"}, "11.0", false},
+	{"\U0001f590\ufe0f", "hand with fingers splayed", []string{"raised_hand_with_fingers_splayed"}, "7.0", true},
+	{"\U0001f64c", "raising hands", []string{"raised_hands"}, "6.0", true},
+	{"\U0001f64b", "person raising hand", []string{"raising_hand"}, "6.0", true},
+	{"\U0001f64b\u200d\u2642\ufe0f", "man raising hand", []string{"raising_hand_man"}, "6.0", true},
+	{"\U0001f64b\u200d\u2640\ufe0f", "woman raising hand", []string{"raising_hand_woman"}, "11.0", true},
+	{"\U0001f40f", "ram", []string{"ram"}, "6.0", false},
+	{"\U0001f35c", "steaming bowl", []string{"ramen"}, "6.0", false},
+	{"\U0001f400", "rat", []string{"rat"}, "6.0", false},
+	{"\U0001fa92", "razor", []string{"razor"}, "12.0", false},
+	{"\U0001f9fe", "receipt", []string{"receipt"}, "11.0", false},
+	{"\u23fa\ufe0f", "record button", []string{"record_button"}, "7.0", false},
+	{"\u267b\ufe0f", "recycling symbol", []string{"recycle"}, "3.2", false},
+	{"\U0001f534", "red circle", []string{"red_circle"}, "6.0", false},
+	{"\U0001f9e7", "red envelope", []string{"red_envelope"}, "11.0", false},
+	{"\U0001f468\u200d\U0001f9b0", "man: red hair", []string{"red_haired_man"}, "11.0", true},
+	{"\U0001f469\u200d\U0001f9b0", "woman: red hair", []string{"red_haired_woman"}, "11.0", true},
+	{"\U0001f7e5", "red square", []string{"red_square"}, "12.0", false},
+	{"\u00ae\ufe0f", "registered", []string{"registered"}, "", false},
+	{"\u263a\ufe0f", "smiling face", []string{"relaxed"}, "", false},
+	{"\U0001f60c", "relieved face", []string{"relieved"}, "6.0", false},
+	{"\U0001f397\ufe0f", "reminder ribbon", []string{"reminder_ribbon"}, "7.0", false},
+	{"\U0001f501", "repeat button", []string{"repeat"}, "6.0", false},
+	{"\U0001f502", "repeat single button", []string{"repeat_one"}, "6.0", false},
+	{"\u26d1\ufe0f", "rescue workerโ€™s helmet", []string{"rescue_worker_helmet"}, "5.2", false},
+	{"\U0001f6bb", "restroom", []string{"restroom"}, "6.0", false},
+	{"\U0001f1f7\U0001f1ea", "flag: Rรฉunion", []string{"reunion"}, "6.0", false},
+	{"\U0001f49e", "revolving hearts", []string{"revolving_hearts"}, "6.0", false},
+	{"\u23ea", "fast reverse button", []string{"rewind"}, "6.0", false},
+	{"\U0001f98f", "rhinoceros", []string{"rhinoceros"}, "9.0", false},
+	{"\U0001f380", "ribbon", []string{"ribbon"}, "6.0", false},
+	{"\U0001f35a", "cooked rice", []string{"rice"}, "6.0", false},
+	{"\U0001f359", "rice ball", []string{"rice_ball"}, "6.0", false},
+	{"\U0001f358", "rice cracker", []string{"rice_cracker"}, "6.0", false},
+	{"\U0001f391", "moon viewing ceremony", []string{"rice_scene"}, "6.0", false},
+	{"\U0001f5ef\ufe0f", "right anger bubble", []string{"right_anger_bubble"}, "7.0", false},
+	{"\U0001f48d", "ring", []string{"ring"}, "6.0", false},
+	{"\U0001fa90", "ringed planet", []string{"ringed_planet"}, "12.0", false},
+	{"\U0001f916", "robot", []string{"robot"}, "8.0", false},
+	{"\U0001f680", "rocket", []string{"rocket"}, "6.0", false},
+	{"\U0001f923", "rolling on the floor laughing", []string{"rofl"}, "9.0", false},
+	{"\U0001f644", "face with rolling eyes", []string{"roll_eyes"}, "8.0", false},
+	{"\U0001f9fb", "roll of paper", []string{"roll_of_paper"}, "11.0", false},
+	{"\U0001f3a2", "roller coaster", []string{"roller_coaster"}, "6.0", false},
+	{"\U0001f1f7\U0001f1f4", "flag: Romania", []string{"romania"}, "6.0", false},
+	{"\U0001f413", "rooster", []string{"rooster"}, "6.0", false},
+	{"\U0001f339", "rose", []string{"rose"}, "6.0", false},
+	{"\U0001f3f5\ufe0f", "rosette", []string{"rosette"}, "7.0", false},
+	{"\U0001f6a8", "police car light", []string{"rotating_light"}, "6.0", false},
+	{"\U0001f4cd", "round pushpin", []string{"round_pushpin"}, "6.0", false},
+	{"\U0001f6a3", "person rowing boat", []string{"rowboat"}, "6.0", true},
+	{"\U0001f6a3\u200d\u2642\ufe0f", "man rowing boat", []string{"rowing_man"}, "11.0", true},
+	{"\U0001f6a3\u200d\u2640\ufe0f", "woman rowing boat", []string{"rowing_woman"}, "6.0", true},
+	{"\U0001f1f7\U0001f1fa", "flag: Russia", []string{"ru"}, "6.0", false},
+	{"\U0001f3c9", "rugby football", []string{"rugby_football"}, "6.0", false},
+	{"\U0001f3c3", "person running", []string{"runner", "running"}, "6.0", true},
+	{"\U0001f3c3\u200d\u2642\ufe0f", "man running", []string{"running_man"}, "11.0", true},
+	{"\U0001f3bd", "running shirt", []string{"running_shirt_with_sash"}, "6.0", false},
+	{"\U0001f3c3\u200d\u2640\ufe0f", "woman running", []string{"running_woman"}, "6.0", true},
+	{"\U0001f1f7\U0001f1fc", "flag: Rwanda", []string{"rwanda"}, "6.0", false},
+	{"\U0001f202\ufe0f", "Japanese โ€œservice chargeโ€ button", []string{"sa"}, "6.0", false},
+	{"\U0001f9f7", "safety pin", []string{"safety_pin"}, "11.0", false},
+	{"\U0001f9ba", "safety vest", []string{"safety_vest"}, "12.0", false},
+	{"\u2650", "Sagittarius", []string{"sagittarius"}, "", false},
+	{"\U0001f376", "sake", []string{"sake"}, "6.0", false},
+	{"\U0001f9c2", "salt", []string{"salt"}, "11.0", false},
+	{"\U0001f1fc\U0001f1f8", "flag: Samoa", []string{"samoa"}, "6.0", false},
+	{"\U0001f1f8\U0001f1f2", "flag: San Marino", []string{"san_marino"}, "6.0", false},
+	{"\U0001f461", "womanโ€™s sandal", []string{"sandal"}, "6.0", false},
+	{"\U0001f96a", "sandwich", []string{"sandwich"}, "11.0", false},
+	{"\U0001f385", "Santa Claus", []string{"santa"}, "6.0", true},
+	{"\U0001f1f8\U0001f1f9", "flag: Sรฃo Tomรฉ & Prรญncipe", []string{"sao_tome_principe"}, "6.0", false},
+	{"\U0001f97b", "sari", []string{"sari"}, "12.0", false},
+	{"\U0001f4e1", "satellite antenna", []string{"satellite"}, "6.0", false},
+	{"\U0001f1f8\U0001f1e6", "flag: Saudi Arabia", []string{"saudi_arabia"}, "6.0", false},
+	{"\U0001f9d6\u200d\u2642\ufe0f", "man in steamy room", []string{"sauna_man"}, "11.0", true},
+	{"\U0001f9d6", "person in steamy room", []string{"sauna_person"}, "11.0", true},
+	{"\U0001f9d6\u200d\u2640\ufe0f", "woman in steamy room", []string{"sauna_woman"}, "11.0", true},
+	{"\U0001f995", "sauropod", []string{"sauropod"}, "11.0", false},
+	{"\U0001f3b7", "saxophone", []string{"saxophone"}, "6.0", false},
+	{"\U0001f9e3", "scarf", []string{"scarf"}, "11.0", false},
+	{"\U0001f3eb", "school", []string{"school"}, "6.0", false},
+	{"\U0001f392", "backpack", []string{"school_satchel"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f52c", "scientist", []string{"scientist"}, "12.1", true},
+	{"\u2702\ufe0f", "scissors", []string{"scissors"}, "", false},
+	{"\U0001f982", "scorpion", []string{"scorpion"}, "8.0", false},
+	{"\u264f", "Scorpio", []string{"scorpius"}, "", false},
+	{"\U0001f3f4\U000e0067\U000e0062\U000e0073\U000e0063\U000e0074\U000e007f", "flag: Scotland", []string{"scotland"}, "11.0", false},
+	{"\U0001f631", "face screaming in fear", []string{"scream"}, "6.0", false},
+	{"\U0001f640", "weary cat", []string{"scream_cat"}, "6.0", false},
+	{"\U0001f4dc", "scroll", []string{"scroll"}, "6.0", false},
+	{"\U0001f4ba", "seat", []string{"seat"}, "6.0", false},
+	{"\u3299\ufe0f", "Japanese โ€œsecretโ€ button", []string{"secret"}, "", false},
+	{"\U0001f648", "see-no-evil monkey", []string{"see_no_evil"}, "6.0", false},
+	{"\U0001f331", "seedling", []string{"seedling"}, "6.0", false},
+	{"\U0001f933", "selfie", []string{"selfie"}, "9.0", true},
+	{"\U0001f1f8\U0001f1f3", "flag: Senegal", []string{"senegal"}, "6.0", false},
+	{"\U0001f1f7\U0001f1f8", "flag: Serbia", []string{"serbia"}, "6.0", false},
+	{"\U0001f415\u200d\U0001f9ba", "service dog", []string{"service_dog"}, "12.0", false},
+	{"7\ufe0f\u20e3", "keycap: 7", []string{"seven"}, "", false},
+	{"\U0001f1f8\U0001f1e8", "flag: Seychelles", []string{"seychelles"}, "6.0", false},
+	{"\U0001f958", "shallow pan of food", []string{"shallow_pan_of_food"}, "", false},
+	{"\u2618\ufe0f", "shamrock", []string{"shamrock"}, "4.1", false},
+	{"\U0001f988", "shark", []string{"shark"}, "9.0", false},
+	{"\U0001f367", "shaved ice", []string{"shaved_ice"}, "6.0", false},
+	{"\U0001f411", "ewe", []string{"sheep"}, "6.0", false},
+	{"\U0001f41a", "spiral shell", []string{"shell"}, "6.0", false},
+	{"\U0001f6e1\ufe0f", "shield", []string{"shield"}, "7.0", false},
+	{"\u26e9\ufe0f", "shinto shrine", []string{"shinto_shrine"}, "5.2", false},
+	{"\U0001f6a2", "ship", []string{"ship"}, "6.0", false},
+	{"\U0001f455", "t-shirt", []string{"shirt", "tshirt"}, "6.0", false},
+	{"\U0001f6cd\ufe0f", "shopping bags", []string{"shopping"}, "7.0", false},
+	{"\U0001f6d2", "shopping cart", []string{"shopping_cart"}, "9.0", false},
+	{"\U0001fa73", "shorts", []string{"shorts"}, "12.0", false},
+	{"\U0001f6bf", "shower", []string{"shower"}, "6.0", false},
+	{"\U0001f990", "shrimp", []string{"shrimp"}, "9.0", false},
+	{"\U0001f937", "person shrugging", []string{"shrug"}, "11.0", true},
+	{"\U0001f92b", "shushing face", []string{"shushing_face"}, "11.0", false},
+	{"\U0001f1f8\U0001f1f1", "flag: Sierra Leone", []string{"sierra_leone"}, "6.0", false},
+	{"\U0001f4f6", "antenna bars", []string{"signal_strength"}, "6.0", false},
+	{"\U0001f1f8\U0001f1ec", "flag: Singapore", []string{"singapore"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f3a4", "singer", []string{"singer"}, "12.1", true},
+	{"\U0001f1f8\U0001f1fd", "flag: Sint Maarten", []string{"sint_maarten"}, "6.0", false},
+	{"6\ufe0f\u20e3", "keycap: 6", []string{"six"}, "", false},
+	{"\U0001f52f", "dotted six-pointed star", []string{"six_pointed_star"}, "6.0", false},
+	{"\U0001f6f9", "skateboard", []string{"skateboard"}, "11.0", false},
+	{"\U0001f3bf", "skis", []string{"ski"}, "6.0", false},
+	{"\u26f7\ufe0f", "skier", []string{"skier"}, "5.2", false},
+	{"\U0001f480", "skull", []string{"skull"}, "6.0", false},
+	{"\u2620\ufe0f", "skull and crossbones", []string{"skull_and_crossbones"}, "", false},
+	{"\U0001f9a8", "skunk", []string{"skunk"}, "12.0", false},
+	{"\U0001f6f7", "sled", []string{"sled"}, "11.0", false},
+	{"\U0001f634", "sleeping face", []string{"sleeping"}, "6.1", false},
+	{"\U0001f6cc", "person in bed", []string{"sleeping_bed"}, "7.0", true},
+	{"\U0001f62a", "sleepy face", []string{"sleepy"}, "6.0", false},
+	{"\U0001f641", "slightly frowning face", []string{"slightly_frowning_face"}, "7.0", false},
+	{"\U0001f642", "slightly smiling face", []string{"slightly_smiling_face"}, "7.0", false},
+	{"\U0001f3b0", "slot machine", []string{"slot_machine"}, "6.0", false},
+	{"\U0001f9a5", "sloth", []string{"sloth"}, "12.0", false},
+	{"\U0001f1f8\U0001f1f0", "flag: Slovakia", []string{"slovakia"}, "6.0", false},
+	{"\U0001f1f8\U0001f1ee", "flag: Slovenia", []string{"slovenia"}, "6.0", false},
+	{"\U0001f6e9\ufe0f", "small airplane", []string{"small_airplane"}, "7.0", false},
+	{"\U0001f539", "small blue diamond", []string{"small_blue_diamond"}, "6.0", false},
+	{"\U0001f538", "small orange diamond", []string{"small_orange_diamond"}, "6.0", false},
+	{"\U0001f53a", "red triangle pointed up", []string{"small_red_triangle"}, "6.0", false},
+	{"\U0001f53b", "red triangle pointed down", []string{"small_red_triangle_down"}, "6.0", false},
+	{"\U0001f604", "grinning face with smiling eyes", []string{"smile"}, "6.0", false},
+	{"\U0001f638", "grinning cat with smiling eyes", []string{"smile_cat"}, "6.0", false},
+	{"\U0001f603", "grinning face with big eyes", []string{"smiley"}, "6.0", false},
+	{"\U0001f63a", "grinning cat", []string{"smiley_cat"}, "6.0", false},
+	{"\U0001f970", "smiling face with hearts", []string{"smiling_face_with_three_hearts"}, "11.0", false},
+	{"\U0001f608", "smiling face with horns", []string{"smiling_imp"}, "6.0", false},
+	{"\U0001f60f", "smirking face", []string{"smirk"}, "6.0", false},
+	{"\U0001f63c", "cat with wry smile", []string{"smirk_cat"}, "6.0", false},
+	{"\U0001f6ac", "cigarette", []string{"smoking"}, "6.0", false},
+	{"\U0001f40c", "snail", []string{"snail"}, "6.0", false},
+	{"\U0001f40d", "snake", []string{"snake"}, "6.0", false},
+	{"\U0001f927", "sneezing face", []string{"sneezing_face"}, "9.0", false},
+	{"\U0001f3c2", "snowboarder", []string{"snowboarder"}, "6.0", true},
+	{"\u2744\ufe0f", "snowflake", []string{"snowflake"}, "", false},
+	{"\u26c4", "snowman without snow", []string{"snowman"}, "5.2", false},
+	{"\u2603\ufe0f", "snowman", []string{"snowman_with_snow"}, "", false},
+	{"\U0001f9fc", "soap", []string{"soap"}, "11.0", false},
+	{"\U0001f62d", "loudly crying face", []string{"sob"}, "6.0", false},
+	{"\u26bd", "soccer ball", []string{"soccer"}, "5.2", false},
+	{"\U0001f9e6", "socks", []string{"socks"}, "11.0", false},
+	{"\U0001f94e", "softball", []string{"softball"}, "11.0", false},
+	{"\U0001f1f8\U0001f1e7", "flag: Solomon Islands", []string{"solomon_islands"}, "6.0", false},
+	{"\U0001f1f8\U0001f1f4", "flag: Somalia", []string{"somalia"}, "6.0", false},
+	{"\U0001f51c", "SOON arrow", []string{"soon"}, "6.0", false},
+	{"\U0001f198", "SOS button", []string{"sos"}, "6.0", false},
+	{"\U0001f509", "speaker medium volume", []string{"sound"}, "6.0", false},
+	{"\U0001f1ff\U0001f1e6", "flag: South Africa", []string{"south_africa"}, "6.0", false},
+	{"\U0001f1ec\U0001f1f8", "flag: South Georgia & South Sandwich Islands", []string{"south_georgia_south_sandwich_islands"}, "6.0", false},
+	{"\U0001f1f8\U0001f1f8", "flag: South Sudan", []string{"south_sudan"}, "6.0", false},
+	{"\U0001f47e", "alien monster", []string{"space_invader"}, "6.0", false},
+	{"\u2660\ufe0f", "spade suit", []string{"spades"}, "", false},
+	{"\U0001f35d", "spaghetti", []string{"spaghetti"}, "6.0", false},
+	{"\u2747\ufe0f", "sparkle", []string{"sparkle"}, "", false},
+	{"\U0001f387", "sparkler", []string{"sparkler"}, "6.0", false},
+	{"\u2728", "sparkles", []string{"sparkles"}, "6.0", false},
+	{"\U0001f496", "sparkling heart", []string{"sparkling_heart"}, "6.0", false},
+	{"\U0001f64a", "speak-no-evil monkey", []string{"speak_no_evil"}, "6.0", false},
+	{"\U0001f508", "speaker low volume", []string{"speaker"}, "6.0", false},
+	{"\U0001f5e3\ufe0f", "speaking head", []string{"speaking_head"}, "7.0", false},
+	{"\U0001f4ac", "speech balloon", []string{"speech_balloon"}, "6.0", false},
+	{"\U0001f6a4", "speedboat", []string{"speedboat"}, "6.0", false},
+	{"\U0001f577\ufe0f", "spider", []string{"spider"}, "7.0", false},
+	{"\U0001f578\ufe0f", "spider web", []string{"spider_web"}, "7.0", false},
+	{"\U0001f5d3\ufe0f", "spiral calendar", []string{"spiral_calendar"}, "7.0", false},
+	{"\U0001f5d2\ufe0f", "spiral notepad", []string{"spiral_notepad"}, "7.0", false},
+	{"\U0001f9fd", "sponge", []string{"sponge"}, "11.0", false},
+	{"\U0001f944", "spoon", []string{"spoon"}, "9.0", false},
+	{"\U0001f991", "squid", []string{"squid"}, "9.0", false},
+	{"\U0001f1f1\U0001f1f0", "flag: Sri Lanka", []string{"sri_lanka"}, "6.0", false},
+	{"\U0001f1e7\U0001f1f1", "flag: St. Barthรฉlemy", []string{"st_barthelemy"}, "6.0", false},
+	{"\U0001f1f8\U0001f1ed", "flag: St. Helena", []string{"st_helena"}, "6.0", false},
+	{"\U0001f1f0\U0001f1f3", "flag: St. Kitts & Nevis", []string{"st_kitts_nevis"}, "6.0", false},
+	{"\U0001f1f1\U0001f1e8", "flag: St. Lucia", []string{"st_lucia"}, "6.0", false},
+	{"\U0001f1f2\U0001f1eb", "flag: St. Martin", []string{"st_martin"}, "11.0", false},
+	{"\U0001f1f5\U0001f1f2", "flag: St. Pierre & Miquelon", []string{"st_pierre_miquelon"}, "6.0", false},
+	{"\U0001f1fb\U0001f1e8", "flag: St. Vincent & Grenadines", []string{"st_vincent_grenadines"}, "6.0", false},
+	{"\U0001f3df\ufe0f", "stadium", []string{"stadium"}, "7.0", false},
+	{"\U0001f9cd\u200d\u2642\ufe0f", "man standing", []string{"standing_man"}, "12.0", true},
+	{"\U0001f9cd", "person standing", []string{"standing_person"}, "12.0", true},
+	{"\U0001f9cd\u200d\u2640\ufe0f", "woman standing", []string{"standing_woman"}, "12.0", true},
+	{"\u2b50", "star", []string{"star"}, "5.1", false},
+	{"\U0001f31f", "glowing star", []string{"star2"}, "6.0", false},
+	{"\u262a\ufe0f", "star and crescent", []string{"star_and_crescent"}, "", false},
+	{"\u2721\ufe0f", "star of David", []string{"star_of_david"}, "", false},
+	{"\U0001f929", "star-struck", []string{"star_struck"}, "11.0", false},
+	{"\U0001f320", "shooting star", []string{"stars"}, "6.0", false},
+	{"\U0001f689", "station", []string{"station"}, "6.0", false},
+	{"\U0001f5fd", "Statue of Liberty", []string{"statue_of_liberty"}, "6.0", false},
+	{"\U0001f682", "locomotive", []string{"steam_locomotive"}, "6.0", false},
+	{"\U0001fa7a", "stethoscope", []string{"stethoscope"}, "12.0", false},
+	{"\U0001f372", "pot of food", []string{"stew"}, "6.0", false},
+	{"\u23f9\ufe0f", "stop button", []string{"stop_button"}, "7.0", false},
+	{"\U0001f6d1", "stop sign", []string{"stop_sign"}, "9.0", false},
+	{"\u23f1\ufe0f", "stopwatch", []string{"stopwatch"}, "6.0", false},
+	{"\U0001f4cf", "straight ruler", []string{"straight_ruler"}, "6.0", false},
+	{"\U0001f353", "strawberry", []string{"strawberry"}, "6.0", false},
+	{"\U0001f61b", "face with tongue", []string{"stuck_out_tongue"}, "6.1", false},
+	{"\U0001f61d", "squinting face with tongue", []string{"stuck_out_tongue_closed_eyes"}, "6.0", false},
+	{"\U0001f61c", "winking face with tongue", []string{"stuck_out_tongue_winking_eye"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f393", "student", []string{"student"}, "12.1", true},
+	{"\U0001f399\ufe0f", "studio microphone", []string{"studio_microphone"}, "7.0", false},
+	{"\U0001f959", "stuffed flatbread", []string{"stuffed_flatbread"}, "9.0", false},
+	{"\U0001f1f8\U0001f1e9", "flag: Sudan", []string{"sudan"}, "6.0", false},
+	{"\U0001f325\ufe0f", "sun behind large cloud", []string{"sun_behind_large_cloud"}, "7.0", false},
+	{"\U0001f326\ufe0f", "sun behind rain cloud", []string{"sun_behind_rain_cloud"}, "7.0", false},
+	{"\U0001f324\ufe0f", "sun behind small cloud", []string{"sun_behind_small_cloud"}, "7.0", false},
+	{"\U0001f31e", "sun with face", []string{"sun_with_face"}, "6.0", false},
+	{"\U0001f33b", "sunflower", []string{"sunflower"}, "6.0", false},
+	{"\U0001f60e", "smiling face with sunglasses", []string{"sunglasses"}, "6.0", false},
+	{"\u2600\ufe0f", "sun", []string{"sunny"}, "", false},
+	{"\U0001f305", "sunrise", []string{"sunrise"}, "6.0", false},
+	{"\U0001f304", "sunrise over mountains", []string{"sunrise_over_mountains"}, "6.0", false},
+	{"\U0001f9b8", "superhero", []string{"superhero"}, "11.0", true},
+	{"\U0001f9b8\u200d\u2642\ufe0f", "man superhero", []string{"superhero_man"}, "11.0", true},
+	{"\U0001f9b8\u200d\u2640\ufe0f", "woman superhero", []string{"superhero_woman"}, "11.0", true},
+	{"\U0001f9b9", "supervillain", []string{"supervillain"}, "11.0", true},
+	{"\U0001f9b9\u200d\u2642\ufe0f", "man supervillain", []string{"supervillain_man"}, "11.0", true},
+	{"\U0001f9b9\u200d\u2640\ufe0f", "woman supervillain", []string{"supervillain_woman"}, "11.0", true},
+	{"\U0001f3c4", "person surfing", []string{"surfer"}, "6.0", true},
+	{"\U0001f3c4\u200d\u2642\ufe0f", "man surfing", []string{"surfing_man"}, "11.0", true},
+	{"\U0001f3c4\u200d\u2640\ufe0f", "woman surfing", []string{"surfing_woman"}, "7.0", true},
+	{"\U0001f1f8\U0001f1f7", "flag: Suriname", []string{"suriname"}, "6.0", false},
+	{"\U0001f363", "sushi", []string{"sushi"}, "6.0", false},
+	{"\U0001f69f", "suspension railway", []string{"suspension_railway"}, "6.0", false},
+	{"\U0001f1f8\U0001f1ef", "flag: Svalbard & Jan Mayen", []string{"svalbard_jan_mayen"}, "11.0", false},
+	{"\U0001f9a2", "swan", []string{"swan"}, "11.0", false},
+	{"\U0001f1f8\U0001f1ff", "flag: Eswatini", []string{"swaziland"}, "6.0", false},
+	{"\U0001f613", "downcast face with sweat", []string{"sweat"}, "6.0", false},
+	{"\U0001f4a6", "sweat droplets", []string{"sweat_drops"}, "6.0", false},
+	{"\U0001f605", "grinning face with sweat", []string{"sweat_smile"}, "6.0", false},
+	{"\U0001f1f8\U0001f1ea", "flag: Sweden", []string{"sweden"}, "6.0", false},
+	{"\U0001f360", "roasted sweet potato", []string{"sweet_potato"}, "6.0", false},
+	{"\U0001fa72", "briefs", []string{"swim_brief"}, "12.0", false},
+	{"\U0001f3ca", "person swimming", []string{"swimmer"}, "6.0", true},
+	{"\U0001f3ca\u200d\u2642\ufe0f", "man swimming", []string{"swimming_man"}, "11.0", true},
+	{"\U0001f3ca\u200d\u2640\ufe0f", "woman swimming", []string{"swimming_woman"}, "6.0", true},
+	{"\U0001f1e8\U0001f1ed", "flag: Switzerland", []string{"switzerland"}, "6.0", false},
+	{"\U0001f523", "input symbols", []string{"symbols"}, "6.0", false},
+	{"\U0001f54d", "synagogue", []string{"synagogue"}, "8.0", false},
+	{"\U0001f1f8\U0001f1fe", "flag: Syria", []string{"syria"}, "6.0", false},
+	{"\U0001f489", "syringe", []string{"syringe"}, "6.0", false},
+	{"\U0001f996", "T-Rex", []string{"t-rex"}, "11.0", false},
+	{"\U0001f32e", "taco", []string{"taco"}, "8.0", false},
+	{"\U0001f389", "party popper", []string{"tada", "hooray"}, "6.0", false},
+	{"\U0001f1f9\U0001f1fc", "flag: Taiwan", []string{"taiwan"}, "6.0", false},
+	{"\U0001f1f9\U0001f1ef", "flag: Tajikistan", []string{"tajikistan"}, "6.0", false},
+	{"\U0001f961", "takeout box", []string{"takeout_box"}, "11.0", false},
+	{"\U0001f38b", "tanabata tree", []string{"tanabata_tree"}, "6.0", false},
+	{"\U0001f34a", "tangerine", []string{"tangerine", "orange", "mandarin"}, "6.0", false},
+	{"\U0001f1f9\U0001f1ff", "flag: Tanzania", []string{"tanzania"}, "6.0", false},
+	{"\u2649", "Taurus", []string{"taurus"}, "", false},
+	{"\U0001f695", "taxi", []string{"taxi"}, "6.0", false},
+	{"\U0001f375", "teacup without handle", []string{"tea"}, "6.0", false},
+	{"\U0001f9d1\u200d\U0001f3eb", "teacher", []string{"teacher"}, "12.1", true},
+	{"\U0001f9d1\u200d\U0001f4bb", "technologist", []string{"technologist"}, "12.1", true},
+	{"\U0001f9f8", "teddy bear", []string{"teddy_bear"}, "11.0", false},
+	{"\U0001f4de", "telephone receiver", []string{"telephone_receiver"}, "6.0", false},
+	{"\U0001f52d", "telescope", []string{"telescope"}, "6.0", false},
+	{"\U0001f3be", "tennis", []string{"tennis"}, "6.0", false},
+	{"\u26fa", "tent", []string{"tent"}, "5.2", false},
+	{"\U0001f9ea", "test tube", []string{"test_tube"}, "11.0", false},
+	{"\U0001f1f9\U0001f1ed", "flag: Thailand", []string{"thailand"}, "6.0", false},
+	{"\U0001f321\ufe0f", "thermometer", []string{"thermometer"}, "7.0", false},
+	{"\U0001f914", "thinking face", []string{"thinking"}, "8.0", false},
+	{"\U0001f4ad", "thought balloon", []string{"thought_balloon"}, "6.0", false},
+	{"\U0001f9f5", "thread", []string{"thread"}, "11.0", false},
+	{"3\ufe0f\u20e3", "keycap: 3", []string{"three"}, "", false},
+	{"\U0001f3ab", "ticket", []string{"ticket"}, "6.0", false},
+	{"\U0001f39f\ufe0f", "admission tickets", []string{"tickets"}, "7.0", false},
+	{"\U0001f42f", "tiger face", []string{"tiger"}, "6.0", false},
+	{"\U0001f405", "tiger", []string{"tiger2"}, "6.0", false},
+	{"\u23f2\ufe0f", "timer clock", []string{"timer_clock"}, "6.0", false},
+	{"\U0001f1f9\U0001f1f1", "flag: Timor-Leste", []string{"timor_leste"}, "6.0", false},
+	{"\U0001f481\u200d\u2642\ufe0f", "man tipping hand", []string{"tipping_hand_man", "sassy_man"}, "6.0", true},
+	{"\U0001f481", "person tipping hand", []string{"tipping_hand_person", "information_desk_person"}, "6.0", true},
+	{"\U0001f481\u200d\u2640\ufe0f", "woman tipping hand", []string{"tipping_hand_woman", "sassy_woman"}, "11.0", true},
+	{"\U0001f62b", "tired face", []string{"tired_face"}, "6.0", false},
+	{"\u2122\ufe0f", "trade mark", []string{"tm"}, "", false},
+	{"\U0001f1f9\U0001f1ec", "flag: Togo", []string{"togo"}, "6.0", false},
+	{"\U0001f6bd", "toilet", []string{"toilet"}, "6.0", false},
+	{"\U0001f1f9\U0001f1f0", "flag: Tokelau", []string{"tokelau"}, "6.0", false},
+	{"\U0001f5fc", "Tokyo tower", []string{"tokyo_tower"}, "6.0", false},
+	{"\U0001f345", "tomato", []string{"tomato"}, "6.0", false},
+	{"\U0001f1f9\U0001f1f4", "flag: Tonga", []string{"tonga"}, "6.0", false},
+	{"\U0001f445", "tongue", []string{"tongue"}, "6.0", false},
+	{"\U0001f9f0", "toolbox", []string{"toolbox"}, "11.0", false},
+	{"\U0001f9b7", "tooth", []string{"tooth"}, "11.0", false},
+	{"\U0001f51d", "TOP arrow", []string{"top"}, "6.0", false},
+	{"\U0001f3a9", "top hat", []string{"tophat"}, "6.0", false},
+	{"\U0001f32a\ufe0f", "tornado", []string{"tornado"}, "7.0", false},
+	{"\U0001f1f9\U0001f1f7", "flag: Turkey", []string{"tr"}, "8.0", false},
+	{"\U0001f5b2\ufe0f", "trackball", []string{"trackball"}, "7.0", false},
+	{"\U0001f69c", "tractor", []string{"tractor"}, "6.0", false},
+	{"\U0001f6a5", "horizontal traffic light", []string{"traffic_light"}, "6.0", false},
+	{"\U0001f68b", "tram car", []string{"train"}, "6.0", false},
+	{"\U0001f686", "train", []string{"train2"}, "6.0", false},
+	{"\U0001f68a", "tram", []string{"tram"}, "6.0", false},
+	{"\U0001f6a9", "triangular flag", []string{"triangular_flag_on_post"}, "6.0", false},
+	{"\U0001f4d0", "triangular ruler", []string{"triangular_ruler"}, "6.0", false},
+	{"\U0001f531", "trident emblem", []string{"trident"}, "6.0", false},
+	{"\U0001f1f9\U0001f1f9", "flag: Trinidad & Tobago", []string{"trinidad_tobago"}, "6.0", false},
+	{"\U0001f1f9\U0001f1e6", "flag: Tristan da Cunha", []string{"tristan_da_cunha"}, "11.0", false},
+	{"\U0001f624", "face with steam from nose", []string{"triumph"}, "6.0", false},
+	{"\U0001f68e", "trolleybus", []string{"trolleybus"}, "6.0", false},
+	{"\U0001f3c6", "trophy", []string{"trophy"}, "6.0", false},
+	{"\U0001f379", "tropical drink", []string{"tropical_drink"}, "6.0", false},
+	{"\U0001f420", "tropical fish", []string{"tropical_fish"}, "6.0", false},
+	{"\U0001f69a", "delivery truck", []string{"truck"}, "6.0", false},
+	{"\U0001f3ba", "trumpet", []string{"trumpet"}, "6.0", false},
+	{"\U0001f337", "tulip", []string{"tulip"}, "6.0", false},
+	{"\U0001f943", "tumbler glass", []string{"tumbler_glass"}, "9.0", false},
+	{"\U0001f1f9\U0001f1f3", "flag: Tunisia", []string{"tunisia"}, "6.0", false},
+	{"\U0001f983", "turkey", []string{"turkey"}, "8.0", false},
+	{"\U0001f1f9\U0001f1f2", "flag: Turkmenistan", []string{"turkmenistan"}, "6.0", false},
+	{"\U0001f1f9\U0001f1e8", "flag: Turks & Caicos Islands", []string{"turks_caicos_islands"}, "6.0", false},
+	{"\U0001f422", "turtle", []string{"turtle"}, "6.0", false},
+	{"\U0001f1f9\U0001f1fb", "flag: Tuvalu", []string{"tuvalu"}, "6.0", false},
+	{"\U0001f4fa", "television", []string{"tv"}, "6.0", false},
+	{"\U0001f500", "shuffle tracks button", []string{"twisted_rightwards_arrows"}, "6.0", false},
+	{"2\ufe0f\u20e3", "keycap: 2", []string{"two"}, "", false},
+	{"\U0001f495", "two hearts", []string{"two_hearts"}, "6.0", false},
+	{"\U0001f46c", "men holding hands", []string{"two_men_holding_hands"}, "6.0", true},
+	{"\U0001f46d", "women holding hands", []string{"two_women_holding_hands"}, "6.0", true},
+	{"\U0001f239", "Japanese โ€œdiscountโ€ button", []string{"u5272"}, "6.0", false},
+	{"\U0001f234", "Japanese โ€œpassing gradeโ€ button", []string{"u5408"}, "6.0", false},
+	{"\U0001f23a", "Japanese โ€œopen for businessโ€ button", []string{"u55b6"}, "6.0", false},
+	{"\U0001f22f", "Japanese โ€œreservedโ€ button", []string{"u6307"}, "", false},
+	{"\U0001f237\ufe0f", "Japanese โ€œmonthly amountโ€ button", []string{"u6708"}, "6.0", false},
+	{"\U0001f236", "Japanese โ€œnot free of chargeโ€ button", []string{"u6709"}, "6.0", false},
+	{"\U0001f235", "Japanese โ€œno vacancyโ€ button", []string{"u6e80"}, "6.0", false},
+	{"\U0001f21a", "Japanese โ€œfree of chargeโ€ button", []string{"u7121"}, "", false},
+	{"\U0001f238", "Japanese โ€œapplicationโ€ button", []string{"u7533"}, "6.0", false},
+	{"\U0001f232", "Japanese โ€œprohibitedโ€ button", []string{"u7981"}, "6.0", false},
+	{"\U0001f233", "Japanese โ€œvacancyโ€ button", []string{"u7a7a"}, "6.0", false},
+	{"\U0001f1fa\U0001f1ec", "flag: Uganda", []string{"uganda"}, "6.0", false},
+	{"\U0001f1fa\U0001f1e6", "flag: Ukraine", []string{"ukraine"}, "6.0", false},
+	{"\u2614", "umbrella with rain drops", []string{"umbrella"}, "4.0", false},
+	{"\U0001f612", "unamused face", []string{"unamused"}, "6.0", false},
+	{"\U0001f51e", "no one under eighteen", []string{"underage"}, "6.0", false},
+	{"\U0001f984", "unicorn", []string{"unicorn"}, "8.0", false},
+	{"\U0001f1e6\U0001f1ea", "flag: United Arab Emirates", []string{"united_arab_emirates"}, "6.0", false},
+	{"\U0001f1fa\U0001f1f3", "flag: United Nations", []string{"united_nations"}, "11.0", false},
+	{"\U0001f513", "unlocked", []string{"unlock"}, "6.0", false},
+	{"\U0001f199", "UP! button", []string{"up"}, "6.0", false},
+	{"\U0001f643", "upside-down face", []string{"upside_down_face"}, "8.0", false},
+	{"\U0001f1fa\U0001f1fe", "flag: Uruguay", []string{"uruguay"}, "6.0", false},
+	{"\U0001f1fa\U0001f1f8", "flag: United States", []string{"us"}, "6.0", false},
+	{"\U0001f1fa\U0001f1f2", "flag: U.S. Outlying Islands", []string{"us_outlying_islands"}, "11.0", false},
+	{"\U0001f1fb\U0001f1ee", "flag: U.S. Virgin Islands", []string{"us_virgin_islands"}, "6.0", false},
+	{"\U0001f1fa\U0001f1ff", "flag: Uzbekistan", []string{"uzbekistan"}, "6.0", false},
+	{"\u270c\ufe0f", "victory hand", []string{"v"}, "", true},
+	{"\U0001f9db", "vampire", []string{"vampire"}, "11.0", true},
+	{"\U0001f9db\u200d\u2642\ufe0f", "man vampire", []string{"vampire_man"}, "11.0", true},
+	{"\U0001f9db\u200d\u2640\ufe0f", "woman vampire", []string{"vampire_woman"}, "11.0", true},
+	{"\U0001f1fb\U0001f1fa", "flag: Vanuatu", []string{"vanuatu"}, "6.0", false},
+	{"\U0001f1fb\U0001f1e6", "flag: Vatican City", []string{"vatican_city"}, "6.0", false},
+	{"\U0001f1fb\U0001f1ea", "flag: Venezuela", []string{"venezuela"}, "6.0", false},
+	{"\U0001f6a6", "vertical traffic light", []string{"vertical_traffic_light"}, "6.0", false},
+	{"\U0001f4fc", "videocassette", []string{"vhs"}, "6.0", false},
+	{"\U0001f4f3", "vibration mode", []string{"vibration_mode"}, "6.0", false},
+	{"\U0001f4f9", "video camera", []string{"video_camera"}, "6.0", false},
+	{"\U0001f3ae", "video game", []string{"video_game"}, "6.0", false},
+	{"\U0001f1fb\U0001f1f3", "flag: Vietnam", []string{"vietnam"}, "6.0", false},
+	{"\U0001f3bb", "violin", []string{"violin"}, "6.0", false},
+	{"\u264d", "Virgo", []string{"virgo"}, "", false},
+	{"\U0001f30b", "volcano", []string{"volcano"}, "6.0", false},
+	{"\U0001f3d0", "volleyball", []string{"volleyball"}, "8.0", false},
+	{"\U0001f92e", "face vomiting", []string{"vomiting_face"}, "11.0", false},
+	{"\U0001f19a", "VS button", []string{"vs"}, "6.0", false},
+	{"\U0001f596", "vulcan salute", []string{"vulcan_salute"}, "7.0", true},
+	{"\U0001f9c7", "waffle", []string{"waffle"}, "12.0", false},
+	{"\U0001f3f4\U000e0067\U000e0062\U000e0077\U000e006c\U000e0073\U000e007f", "flag: Wales", []string{"wales"}, "11.0", false},
+	{"\U0001f6b6", "person walking", []string{"walking"}, "6.0", true},
+	{"\U0001f6b6\u200d\u2642\ufe0f", "man walking", []string{"walking_man"}, "11.0", true},
+	{"\U0001f6b6\u200d\u2640\ufe0f", "woman walking", []string{"walking_woman"}, "6.0", true},
+	{"\U0001f1fc\U0001f1eb", "flag: Wallis & Futuna", []string{"wallis_futuna"}, "6.0", false},
+	{"\U0001f318", "waning crescent moon", []string{"waning_crescent_moon"}, "6.0", false},
+	{"\U0001f316", "waning gibbous moon", []string{"waning_gibbous_moon"}, "6.0", false},
+	{"\u26a0\ufe0f", "warning", []string{"warning"}, "4.0", false},
+	{"\U0001f5d1\ufe0f", "wastebasket", []string{"wastebasket"}, "7.0", false},
+	{"\u231a", "watch", []string{"watch"}, "", false},
+	{"\U0001f403", "water buffalo", []string{"water_buffalo"}, "6.0", false},
+	{"\U0001f93d", "person playing water polo", []string{"water_polo"}, "11.0", true},
+	{"\U0001f349", "watermelon", []string{"watermelon"}, "6.0", false},
+	{"\U0001f44b", "waving hand", []string{"wave"}, "6.0", true},
+	{"\u3030\ufe0f", "wavy dash", []string{"wavy_dash"}, "", false},
+	{"\U0001f312", "waxing crescent moon", []string{"waxing_crescent_moon"}, "6.0", false},
+	{"\U0001f6be", "water closet", []string{"wc"}, "6.0", false},
+	{"\U0001f629", "weary face", []string{"weary"}, "6.0", false},
+	{"\U0001f492", "wedding", []string{"wedding"}, "6.0", false},
+	{"\U0001f3cb\ufe0f", "person lifting weights", []string{"weight_lifting"}, "7.0", true},
+	{"\U0001f3cb\ufe0f\u200d\u2642\ufe0f", "man lifting weights", []string{"weight_lifting_man"}, "11.0", true},
+	{"\U0001f3cb\ufe0f\u200d\u2640\ufe0f", "woman lifting weights", []string{"weight_lifting_woman"}, "6.0", true},
+	{"\U0001f1ea\U0001f1ed", "flag: Western Sahara", []string{"western_sahara"}, "6.0", false},
+	{"\U0001f433", "spouting whale", []string{"whale"}, "6.0", false},
+	{"\U0001f40b", "whale", []string{"whale2"}, "6.0", false},
+	{"\u2638\ufe0f", "wheel of dharma", []string{"wheel_of_dharma"}, "", false},
+	{"\u267f", "wheelchair symbol", []string{"wheelchair"}, "4.1", false},
+	{"\u2705", "check mark button", []string{"white_check_mark"}, "6.0", false},
+	{"\u26aa", "white circle", []string{"white_circle"}, "4.1", false},
+	{"\U0001f3f3\ufe0f", "white flag", []string{"white_flag"}, "7.0", false},
+	{"\U0001f4ae", "white flower", []string{"white_flower"}, "6.0", false},
+	{"\U0001f468\u200d\U0001f9b3", "man: white hair", []string{"white_haired_man"}, "11.0", true},
+	{"\U0001f469\u200d\U0001f9b3", "woman: white hair", []string{"white_haired_woman"}, "11.0", true},
+	{"\U0001f90d", "white heart", []string{"white_heart"}, "12.0", false},
+	{"\u2b1c", "white large square", []string{"white_large_square"}, "5.1", false},
+	{"\u25fd", "white medium-small square", []string{"white_medium_small_square"}, "3.2", false},
+	{"\u25fb\ufe0f", "white medium square", []string{"white_medium_square"}, "3.2", false},
+	{"\u25ab\ufe0f", "white small square", []string{"white_small_square"}, "", false},
+	{"\U0001f533", "white square button", []string{"white_square_button"}, "6.0", false},
+	{"\U0001f940", "wilted flower", []string{"wilted_flower"}, "9.0", false},
+	{"\U0001f390", "wind chime", []string{"wind_chime"}, "6.0", false},
+	{"\U0001f32c\ufe0f", "wind face", []string{"wind_face"}, "7.0", false},
+	{"\U0001f377", "wine glass", []string{"wine_glass"}, "6.0", false},
+	{"\U0001f609", "winking face", []string{"wink"}, "6.0", false},
+	{"\U0001f43a", "wolf", []string{"wolf"}, "6.0", false},
+	{"\U0001f469", "woman", []string{"woman"}, "6.0", true},
+	{"\U0001f469\u200d\U0001f3a8", "woman artist", []string{"woman_artist"}, "", true},
+	{"\U0001f469\u200d\U0001f680", "woman astronaut", []string{"woman_astronaut"}, "", true},
+	{"\U0001f938\u200d\u2640\ufe0f", "woman cartwheeling", []string{"woman_cartwheeling"}, "", true},
+	{"\U0001f469\u200d\U0001f373", "woman cook", []string{"woman_cook"}, "", true},
+	{"\U0001f483", "woman dancing", []string{"woman_dancing", "dancer"}, "6.0", true},
+	{"\U0001f926\u200d\u2640\ufe0f", "woman facepalming", []string{"woman_facepalming"}, "9.0", true},
+	{"\U0001f469\u200d\U0001f3ed", "woman factory worker", []string{"woman_factory_worker"}, "", true},
+	{"\U0001f469\u200d\U0001f33e", "woman farmer", []string{"woman_farmer"}, "", true},
+	{"\U0001f469\u200d\U0001f692", "woman firefighter", []string{"woman_firefighter"}, "", true},
+	{"\U0001f469\u200d\u2695\ufe0f", "woman health worker", []string{"woman_health_worker"}, "", true},
+	{"\U0001f469\u200d\U0001f9bd", "woman in manual wheelchair", []string{"woman_in_manual_wheelchair"}, "12.0", true},
+	{"\U0001f469\u200d\U0001f9bc", "woman in motorized wheelchair", []string{"woman_in_motorized_wheelchair"}, "12.0", true},
+	{"\U0001f469\u200d\u2696\ufe0f", "woman judge", []string{"woman_judge"}, "", true},
+	{"\U0001f939\u200d\u2640\ufe0f", "woman juggling", []string{"woman_juggling"}, "9.0", true},
+	{"\U0001f469\u200d\U0001f527", "woman mechanic", []string{"woman_mechanic"}, "", true},
+	{"\U0001f469\u200d\U0001f4bc", "woman office worker", []string{"woman_office_worker"}, "", true},
+	{"\U0001f469\u200d\u2708\ufe0f", "woman pilot", []string{"woman_pilot"}, "", true},
+	{"\U0001f93e\u200d\u2640\ufe0f", "woman playing handball", []string{"woman_playing_handball"}, "9.0", true},
+	{"\U0001f93d\u200d\u2640\ufe0f", "woman playing water polo", []string{"woman_playing_water_polo"}, "9.0", true},
+	{"\U0001f469\u200d\U0001f52c", "woman scientist", []string{"woman_scientist"}, "", true},
+	{"\U0001f937\u200d\u2640\ufe0f", "woman shrugging", []string{"woman_shrugging"}, "9.0", true},
+	{"\U0001f469\u200d\U0001f3a4", "woman singer", []string{"woman_singer"}, "", true},
+	{"\U0001f469\u200d\U0001f393", "woman student", []string{"woman_student"}, "", true},
+	{"\U0001f469\u200d\U0001f3eb", "woman teacher", []string{"woman_teacher"}, "", true},
+	{"\U0001f469\u200d\U0001f4bb", "woman technologist", []string{"woman_technologist"}, "", true},
+	{"\U0001f9d5", "woman with headscarf", []string{"woman_with_headscarf"}, "11.0", true},
+	{"\U0001f469\u200d\U0001f9af", "woman with white cane", []string{"woman_with_probing_cane"}, "12.0", true},
+	{"\U0001f473\u200d\u2640\ufe0f", "woman wearing turban", []string{"woman_with_turban"}, "6.0", true},
+	{"\U0001f45a", "womanโ€™s clothes", []string{"womans_clothes"}, "6.0", false},
+	{"\U0001f452", "womanโ€™s hat", []string{"womans_hat"}, "6.0", false},
+	{"\U0001f93c\u200d\u2640\ufe0f", "women wrestling", []string{"women_wrestling"}, "9.0", false},
+	{"\U0001f6ba", "womenโ€™s room", []string{"womens"}, "6.0", false},
+	{"\U0001f974", "woozy face", []string{"woozy_face"}, "11.0", false},
+	{"\U0001f5fa\ufe0f", "world map", []string{"world_map"}, "7.0", false},
+	{"\U0001f61f", "worried face", []string{"worried"}, "6.1", false},
+	{"\U0001f527", "wrench", []string{"wrench"}, "6.0", false},
+	{"\U0001f93c", "people wrestling", []string{"wrestling"}, "11.0", false},
+	{"\u270d\ufe0f", "writing hand", []string{"writing_hand"}, "", true},
+	{"\u274c", "cross mark", []string{"x"}, "6.0", false},
+	{"\U0001f9f6", "yarn", []string{"yarn"}, "11.0", false},
+	{"\U0001f971", "yawning face", []string{"yawning_face"}, "12.0", false},
+	{"\U0001f7e1", "yellow circle", []string{"yellow_circle"}, "12.0", false},
+	{"\U0001f49b", "yellow heart", []string{"yellow_heart"}, "6.0", false},
+	{"\U0001f7e8", "yellow square", []string{"yellow_square"}, "12.0", false},
+	{"\U0001f1fe\U0001f1ea", "flag: Yemen", []string{"yemen"}, "6.0", false},
+	{"\U0001f4b4", "yen banknote", []string{"yen"}, "6.0", false},
+	{"\u262f\ufe0f", "yin yang", []string{"yin_yang"}, "", false},
+	{"\U0001fa80", "yo-yo", []string{"yo_yo"}, "12.0", false},
+	{"\U0001f60b", "face savoring food", []string{"yum"}, "6.0", false},
+	{"\U0001f1ff\U0001f1f2", "flag: Zambia", []string{"zambia"}, "6.0", false},
+	{"\U0001f92a", "zany face", []string{"zany_face"}, "11.0", false},
+	{"\u26a1", "high voltage", []string{"zap"}, "4.0", false},
+	{"\U0001f993", "zebra", []string{"zebra"}, "11.0", false},
+	{"0\ufe0f\u20e3", "keycap: 0", []string{"zero"}, "", false},
+	{"\U0001f1ff\U0001f1fc", "flag: Zimbabwe", []string{"zimbabwe"}, "6.0", false},
+	{"\U0001f910", "zipper-mouth face", []string{"zipper_mouth_face"}, "8.0", false},
+	{"\U0001f9df", "zombie", []string{"zombie"}, "11.0", false},
+	{"\U0001f9df\u200d\u2642\ufe0f", "man zombie", []string{"zombie_man"}, "11.0", false},
+	{"\U0001f9df\u200d\u2640\ufe0f", "woman zombie", []string{"zombie_woman"}, "11.0", false},
+	{"\U0001f4a4", "zzz", []string{"zzz"}, "6.0", false},
+	{"\U0001f44d\U0001f3ff", "thumbs up: Dark Skin Tone", []string{"+1_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f44d\U0001f3fb", "thumbs up: Light Skin Tone", []string{"+1_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44d\U0001f3fc", "thumbs up: Medium-Light Skin Tone", []string{"+1_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44d\U0001f3fd", "thumbs up: Medium Skin Tone", []string{"+1_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f44d\U0001f3fe", "thumbs up: Medium-Dark Skin Tone", []string{"+1_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f44e\U0001f3fb", "thumbs down: Light Skin Tone", []string{"-1_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44e\U0001f3fc", "thumbs down: Medium-Light Skin Tone", []string{"-1_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44e\U0001f3fd", "thumbs down: Medium Skin Tone", []string{"-1_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f44e\U0001f3fe", "thumbs down: Medium-Dark Skin Tone", []string{"-1_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f44e\U0001f3ff", "thumbs down: Dark Skin Tone", []string{"-1_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd", "person: Medium Skin Tone", []string{"adult_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe", "person: Medium-Dark Skin Tone", []string{"adult_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff", "person: Dark Skin Tone", []string{"adult_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb", "person: Light Skin Tone", []string{"adult_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc", "person: Medium-Light Skin Tone", []string{"adult_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f47c\U0001f3fb", "baby angel: Light Skin Tone", []string{"angel_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f47c\U0001f3fc", "baby angel: Medium-Light Skin Tone", []string{"angel_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f47c\U0001f3fd", "baby angel: Medium Skin Tone", []string{"angel_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f47c\U0001f3fe", "baby angel: Medium-Dark Skin Tone", []string{"angel_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f47c\U0001f3ff", "baby angel: Dark Skin Tone", []string{"angel_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f3a8", "artist: Medium-Dark Skin Tone", []string{"artist_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f3a8", "artist: Dark Skin Tone", []string{"artist_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f3a8", "artist: Light Skin Tone", []string{"artist_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f3a8", "artist: Medium-Light Skin Tone", []string{"artist_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f3a8", "artist: Medium Skin Tone", []string{"artist_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f680", "astronaut: Light Skin Tone", []string{"astronaut_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f680", "astronaut: Medium-Light Skin Tone", []string{"astronaut_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f680", "astronaut: Medium Skin Tone", []string{"astronaut_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f680", "astronaut: Medium-Dark Skin Tone", []string{"astronaut_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f680", "astronaut: Dark Skin Tone", []string{"astronaut_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f476\U0001f3fb", "baby: Light Skin Tone", []string{"baby_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f476\U0001f3fc", "baby: Medium-Light Skin Tone", []string{"baby_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f476\U0001f3fd", "baby: Medium Skin Tone", []string{"baby_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f476\U0001f3fe", "baby: Medium-Dark Skin Tone", []string{"baby_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f476\U0001f3ff", "baby: Dark Skin Tone", []string{"baby_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f9b2", "man: bald: Light Skin Tone", []string{"bald_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f9b2", "man: bald: Medium-Light Skin Tone", []string{"bald_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f9b2", "man: bald: Medium Skin Tone", []string{"bald_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f9b2", "man: bald: Medium-Dark Skin Tone", []string{"bald_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f9b2", "man: bald: Dark Skin Tone", []string{"bald_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f9b2", "woman: bald: Dark Skin Tone", []string{"bald_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f9b2", "woman: bald: Light Skin Tone", []string{"bald_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f9b2", "woman: bald: Medium-Light Skin Tone", []string{"bald_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f9b2", "woman: bald: Medium Skin Tone", []string{"bald_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f9b2", "woman: bald: Medium-Dark Skin Tone", []string{"bald_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6c0\U0001f3fb", "person taking bath: Light Skin Tone", []string{"bath_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6c0\U0001f3fc", "person taking bath: Medium-Light Skin Tone", []string{"bath_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6c0\U0001f3fd", "person taking bath: Medium Skin Tone", []string{"bath_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6c0\U0001f3fe", "person taking bath: Medium-Dark Skin Tone", []string{"bath_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6c0\U0001f3ff", "person taking bath: Dark Skin Tone", []string{"bath_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d4\U0001f3fb", "man: beard: Light Skin Tone", []string{"bearded_person_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d4\U0001f3fc", "man: beard: Medium-Light Skin Tone", []string{"bearded_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d4\U0001f3fd", "man: beard: Medium Skin Tone", []string{"bearded_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d4\U0001f3fe", "man: beard: Medium-Dark Skin Tone", []string{"bearded_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d4\U0001f3ff", "man: beard: Dark Skin Tone", []string{"bearded_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3ff", "person biking: Dark Skin Tone", []string{"bicyclist_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fb", "person biking: Light Skin Tone", []string{"bicyclist_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fc", "person biking: Medium-Light Skin Tone", []string{"bicyclist_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fd", "person biking: Medium Skin Tone", []string{"bicyclist_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fe", "person biking: Medium-Dark Skin Tone", []string{"bicyclist_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fe\u200d\u2642\ufe0f", "man biking: Medium-Dark Skin Tone", []string{"biking_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3ff\u200d\u2642\ufe0f", "man biking: Dark Skin Tone", []string{"biking_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fb\u200d\u2642\ufe0f", "man biking: Light Skin Tone", []string{"biking_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fc\u200d\u2642\ufe0f", "man biking: Medium-Light Skin Tone", []string{"biking_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fd\u200d\u2642\ufe0f", "man biking: Medium Skin Tone", []string{"biking_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fb\u200d\u2640\ufe0f", "woman biking: Light Skin Tone", []string{"biking_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fc\u200d\u2640\ufe0f", "woman biking: Medium-Light Skin Tone", []string{"biking_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fd\u200d\u2640\ufe0f", "woman biking: Medium Skin Tone", []string{"biking_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3fe\u200d\u2640\ufe0f", "woman biking: Medium-Dark Skin Tone", []string{"biking_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b4\U0001f3ff\u200d\u2640\ufe0f", "woman biking: Dark Skin Tone", []string{"biking_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fb\u200d\u2642\ufe0f", "man: blond hair: Light Skin Tone", []string{"blond_haired_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fc\u200d\u2642\ufe0f", "man: blond hair: Medium-Light Skin Tone", []string{"blond_haired_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fd\u200d\u2642\ufe0f", "man: blond hair: Medium Skin Tone", []string{"blond_haired_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fe\u200d\u2642\ufe0f", "man: blond hair: Medium-Dark Skin Tone", []string{"blond_haired_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3ff\u200d\u2642\ufe0f", "man: blond hair: Dark Skin Tone", []string{"blond_haired_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fb", "person: blond hair: Light Skin Tone", []string{"blond_haired_person_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fc", "person: blond hair: Medium-Light Skin Tone", []string{"blond_haired_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fd", "person: blond hair: Medium Skin Tone", []string{"blond_haired_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fe", "person: blond hair: Medium-Dark Skin Tone", []string{"blond_haired_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3ff", "person: blond hair: Dark Skin Tone", []string{"blond_haired_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fb\u200d\u2640\ufe0f", "woman: blond hair: Light Skin Tone", []string{"blond_haired_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fc\u200d\u2640\ufe0f", "woman: blond hair: Medium-Light Skin Tone", []string{"blond_haired_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fd\u200d\u2640\ufe0f", "woman: blond hair: Medium Skin Tone", []string{"blond_haired_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3fe\u200d\u2640\ufe0f", "woman: blond hair: Medium-Dark Skin Tone", []string{"blond_haired_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f471\U0001f3ff\u200d\u2640\ufe0f", "woman: blond hair: Dark Skin Tone", []string{"blond_haired_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fe\ufe0f\u200d\u2642\ufe0f", "man bouncing ball: Medium-Dark Skin Tone", []string{"bouncing_ball_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3ff\ufe0f\u200d\u2642\ufe0f", "man bouncing ball: Dark Skin Tone", []string{"bouncing_ball_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fb\ufe0f\u200d\u2642\ufe0f", "man bouncing ball: Light Skin Tone", []string{"bouncing_ball_man_Light_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fc\ufe0f\u200d\u2642\ufe0f", "man bouncing ball: Medium-Light Skin Tone", []string{"bouncing_ball_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fd\ufe0f\u200d\u2642\ufe0f", "man bouncing ball: Medium Skin Tone", []string{"bouncing_ball_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fb\ufe0f", "person bouncing ball: Light Skin Tone", []string{"bouncing_ball_person_Light_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fc\ufe0f", "person bouncing ball: Medium-Light Skin Tone", []string{"bouncing_ball_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fd\ufe0f", "person bouncing ball: Medium Skin Tone", []string{"bouncing_ball_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fe\ufe0f", "person bouncing ball: Medium-Dark Skin Tone", []string{"bouncing_ball_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3ff\ufe0f", "person bouncing ball: Dark Skin Tone", []string{"bouncing_ball_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fe\ufe0f\u200d\u2640\ufe0f", "woman bouncing ball: Medium-Dark Skin Tone", []string{"bouncing_ball_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3ff\ufe0f\u200d\u2640\ufe0f", "woman bouncing ball: Dark Skin Tone", []string{"bouncing_ball_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fb\ufe0f\u200d\u2640\ufe0f", "woman bouncing ball: Light Skin Tone", []string{"bouncing_ball_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fc\ufe0f\u200d\u2640\ufe0f", "woman bouncing ball: Medium-Light Skin Tone", []string{"bouncing_ball_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\u26f9\U0001f3fd\ufe0f\u200d\u2640\ufe0f", "woman bouncing ball: Medium Skin Tone", []string{"bouncing_ball_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fb", "person bowing: Light Skin Tone", []string{"bow_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fc", "person bowing: Medium-Light Skin Tone", []string{"bow_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fd", "person bowing: Medium Skin Tone", []string{"bow_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fe", "person bowing: Medium-Dark Skin Tone", []string{"bow_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3ff", "person bowing: Dark Skin Tone", []string{"bow_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3ff\u200d\u2642\ufe0f", "man bowing: Dark Skin Tone", []string{"bowing_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fb\u200d\u2642\ufe0f", "man bowing: Light Skin Tone", []string{"bowing_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fc\u200d\u2642\ufe0f", "man bowing: Medium-Light Skin Tone", []string{"bowing_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fd\u200d\u2642\ufe0f", "man bowing: Medium Skin Tone", []string{"bowing_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fe\u200d\u2642\ufe0f", "man bowing: Medium-Dark Skin Tone", []string{"bowing_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fe\u200d\u2640\ufe0f", "woman bowing: Medium-Dark Skin Tone", []string{"bowing_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3ff\u200d\u2640\ufe0f", "woman bowing: Dark Skin Tone", []string{"bowing_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fb\u200d\u2640\ufe0f", "woman bowing: Light Skin Tone", []string{"bowing_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fc\u200d\u2640\ufe0f", "woman bowing: Medium-Light Skin Tone", []string{"bowing_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f647\U0001f3fd\u200d\u2640\ufe0f", "woman bowing: Medium Skin Tone", []string{"bowing_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f466\U0001f3fb", "boy: Light Skin Tone", []string{"boy_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f466\U0001f3fc", "boy: Medium-Light Skin Tone", []string{"boy_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f466\U0001f3fd", "boy: Medium Skin Tone", []string{"boy_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f466\U0001f3fe", "boy: Medium-Dark Skin Tone", []string{"boy_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f466\U0001f3ff", "boy: Dark Skin Tone", []string{"boy_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f931\U0001f3fe", "breast-feeding: Medium-Dark Skin Tone", []string{"breast_feeding_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f931\U0001f3ff", "breast-feeding: Dark Skin Tone", []string{"breast_feeding_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f931\U0001f3fb", "breast-feeding: Light Skin Tone", []string{"breast_feeding_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f931\U0001f3fc", "breast-feeding: Medium-Light Skin Tone", []string{"breast_feeding_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f931\U0001f3fd", "breast-feeding: Medium Skin Tone", []string{"breast_feeding_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f574\U0001f3fb\ufe0f", "person in suit levitating: Light Skin Tone", []string{"business_suit_levitating_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f574\U0001f3fc\ufe0f", "person in suit levitating: Medium-Light Skin Tone", []string{"business_suit_levitating_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f574\U0001f3fd\ufe0f", "person in suit levitating: Medium Skin Tone", []string{"business_suit_levitating_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f574\U0001f3fe\ufe0f", "person in suit levitating: Medium-Dark Skin Tone", []string{"business_suit_levitating_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f574\U0001f3ff\ufe0f", "person in suit levitating: Dark Skin Tone", []string{"business_suit_levitating_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f919\U0001f3fb", "call me hand: Light Skin Tone", []string{"call_me_hand_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f919\U0001f3fc", "call me hand: Medium-Light Skin Tone", []string{"call_me_hand_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f919\U0001f3fd", "call me hand: Medium Skin Tone", []string{"call_me_hand_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f919\U0001f3fe", "call me hand: Medium-Dark Skin Tone", []string{"call_me_hand_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f919\U0001f3ff", "call me hand: Dark Skin Tone", []string{"call_me_hand_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fc", "person cartwheeling: Medium-Light Skin Tone", []string{"cartwheeling_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fd", "person cartwheeling: Medium Skin Tone", []string{"cartwheeling_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fe", "person cartwheeling: Medium-Dark Skin Tone", []string{"cartwheeling_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3ff", "person cartwheeling: Dark Skin Tone", []string{"cartwheeling_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fb", "person cartwheeling: Light Skin Tone", []string{"cartwheeling_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d2\U0001f3fd", "child: Medium Skin Tone", []string{"child_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d2\U0001f3fe", "child: Medium-Dark Skin Tone", []string{"child_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d2\U0001f3ff", "child: Dark Skin Tone", []string{"child_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d2\U0001f3fb", "child: Light Skin Tone", []string{"child_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d2\U0001f3fc", "child: Medium-Light Skin Tone", []string{"child_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44f\U0001f3fb", "clapping hands: Light Skin Tone", []string{"clap_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44f\U0001f3fc", "clapping hands: Medium-Light Skin Tone", []string{"clap_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44f\U0001f3fd", "clapping hands: Medium Skin Tone", []string{"clap_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f44f\U0001f3fe", "clapping hands: Medium-Dark Skin Tone", []string{"clap_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f44f\U0001f3ff", "clapping hands: Dark Skin Tone", []string{"clap_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fd", "person climbing: Medium Skin Tone", []string{"climbing_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fe", "person climbing: Medium-Dark Skin Tone", []string{"climbing_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3ff", "person climbing: Dark Skin Tone", []string{"climbing_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fb", "person climbing: Light Skin Tone", []string{"climbing_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fc", "person climbing: Medium-Light Skin Tone", []string{"climbing_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fb\u200d\u2642\ufe0f", "man climbing: Light Skin Tone", []string{"climbing_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fc\u200d\u2642\ufe0f", "man climbing: Medium-Light Skin Tone", []string{"climbing_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fd\u200d\u2642\ufe0f", "man climbing: Medium Skin Tone", []string{"climbing_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fe\u200d\u2642\ufe0f", "man climbing: Medium-Dark Skin Tone", []string{"climbing_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3ff\u200d\u2642\ufe0f", "man climbing: Dark Skin Tone", []string{"climbing_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fb\u200d\u2640\ufe0f", "woman climbing: Light Skin Tone", []string{"climbing_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fc\u200d\u2640\ufe0f", "woman climbing: Medium-Light Skin Tone", []string{"climbing_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fd\u200d\u2640\ufe0f", "woman climbing: Medium Skin Tone", []string{"climbing_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3fe\u200d\u2640\ufe0f", "woman climbing: Medium-Dark Skin Tone", []string{"climbing_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d7\U0001f3ff\u200d\u2640\ufe0f", "woman climbing: Dark Skin Tone", []string{"climbing_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fb", "construction worker: Light Skin Tone", []string{"construction_worker_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fc", "construction worker: Medium-Light Skin Tone", []string{"construction_worker_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fd", "construction worker: Medium Skin Tone", []string{"construction_worker_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fe", "construction worker: Medium-Dark Skin Tone", []string{"construction_worker_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3ff", "construction worker: Dark Skin Tone", []string{"construction_worker_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fb\u200d\u2642\ufe0f", "man construction worker: Light Skin Tone", []string{"construction_worker_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fc\u200d\u2642\ufe0f", "man construction worker: Medium-Light Skin Tone", []string{"construction_worker_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fd\u200d\u2642\ufe0f", "man construction worker: Medium Skin Tone", []string{"construction_worker_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fe\u200d\u2642\ufe0f", "man construction worker: Medium-Dark Skin Tone", []string{"construction_worker_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3ff\u200d\u2642\ufe0f", "man construction worker: Dark Skin Tone", []string{"construction_worker_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fb\u200d\u2640\ufe0f", "woman construction worker: Light Skin Tone", []string{"construction_worker_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fc\u200d\u2640\ufe0f", "woman construction worker: Medium-Light Skin Tone", []string{"construction_worker_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fd\u200d\u2640\ufe0f", "woman construction worker: Medium Skin Tone", []string{"construction_worker_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3fe\u200d\u2640\ufe0f", "woman construction worker: Medium-Dark Skin Tone", []string{"construction_worker_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f477\U0001f3ff\u200d\u2640\ufe0f", "woman construction worker: Dark Skin Tone", []string{"construction_worker_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f373", "cook: Medium Skin Tone", []string{"cook_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f373", "cook: Medium-Dark Skin Tone", []string{"cook_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f373", "cook: Dark Skin Tone", []string{"cook_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f373", "cook: Light Skin Tone", []string{"cook_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f373", "cook: Medium-Light Skin Tone", []string{"cook_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46b\U0001f3fb", "woman and man holding hands: Light Skin Tone", []string{"couple_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46b\U0001f3fc", "woman and man holding hands: Medium-Light Skin Tone", []string{"couple_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46b\U0001f3fd", "woman and man holding hands: Medium Skin Tone", []string{"couple_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f46b\U0001f3fe", "woman and man holding hands: Medium-Dark Skin Tone", []string{"couple_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f46b\U0001f3ff", "woman and man holding hands: Dark Skin Tone", []string{"couple_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f91e\U0001f3ff", "crossed fingers: Dark Skin Tone", []string{"crossed_fingers_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f91e\U0001f3fb", "crossed fingers: Light Skin Tone", []string{"crossed_fingers_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f91e\U0001f3fc", "crossed fingers: Medium-Light Skin Tone", []string{"crossed_fingers_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f91e\U0001f3fd", "crossed fingers: Medium Skin Tone", []string{"crossed_fingers_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f91e\U0001f3fe", "crossed fingers: Medium-Dark Skin Tone", []string{"crossed_fingers_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f9b1", "man: curly hair: Medium Skin Tone", []string{"curly_haired_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f9b1", "man: curly hair: Medium-Dark Skin Tone", []string{"curly_haired_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f9b1", "man: curly hair: Dark Skin Tone", []string{"curly_haired_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f9b1", "man: curly hair: Light Skin Tone", []string{"curly_haired_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f9b1", "man: curly hair: Medium-Light Skin Tone", []string{"curly_haired_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f9b1", "woman: curly hair: Light Skin Tone", []string{"curly_haired_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f9b1", "woman: curly hair: Medium-Light Skin Tone", []string{"curly_haired_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f9b1", "woman: curly hair: Medium Skin Tone", []string{"curly_haired_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f9b1", "woman: curly hair: Medium-Dark Skin Tone", []string{"curly_haired_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f9b1", "woman: curly hair: Dark Skin Tone", []string{"curly_haired_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fb\u200d\u2642\ufe0f", "deaf man: Light Skin Tone", []string{"deaf_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fc\u200d\u2642\ufe0f", "deaf man: Medium-Light Skin Tone", []string{"deaf_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fd\u200d\u2642\ufe0f", "deaf man: Medium Skin Tone", []string{"deaf_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fe\u200d\u2642\ufe0f", "deaf man: Medium-Dark Skin Tone", []string{"deaf_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3ff\u200d\u2642\ufe0f", "deaf man: Dark Skin Tone", []string{"deaf_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fd", "deaf person: Medium Skin Tone", []string{"deaf_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fe", "deaf person: Medium-Dark Skin Tone", []string{"deaf_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3ff", "deaf person: Dark Skin Tone", []string{"deaf_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fb", "deaf person: Light Skin Tone", []string{"deaf_person_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fc", "deaf person: Medium-Light Skin Tone", []string{"deaf_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fb\u200d\u2640\ufe0f", "deaf woman: Light Skin Tone", []string{"deaf_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fc\u200d\u2640\ufe0f", "deaf woman: Medium-Light Skin Tone", []string{"deaf_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fd\u200d\u2640\ufe0f", "deaf woman: Medium Skin Tone", []string{"deaf_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3fe\u200d\u2640\ufe0f", "deaf woman: Medium-Dark Skin Tone", []string{"deaf_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cf\U0001f3ff\u200d\u2640\ufe0f", "deaf woman: Dark Skin Tone", []string{"deaf_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fe\ufe0f", "detective: Medium-Dark Skin Tone", []string{"detective_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3ff\ufe0f", "detective: Dark Skin Tone", []string{"detective_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fb\ufe0f", "detective: Light Skin Tone", []string{"detective_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fc\ufe0f", "detective: Medium-Light Skin Tone", []string{"detective_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fd\ufe0f", "detective: Medium Skin Tone", []string{"detective_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f442\U0001f3fc", "ear: Medium-Light Skin Tone", []string{"ear_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f442\U0001f3fd", "ear: Medium Skin Tone", []string{"ear_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f442\U0001f3fe", "ear: Medium-Dark Skin Tone", []string{"ear_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f442\U0001f3ff", "ear: Dark Skin Tone", []string{"ear_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f442\U0001f3fb", "ear: Light Skin Tone", []string{"ear_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9bb\U0001f3fb", "ear with hearing aid: Light Skin Tone", []string{"ear_with_hearing_aid_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9bb\U0001f3fc", "ear with hearing aid: Medium-Light Skin Tone", []string{"ear_with_hearing_aid_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9bb\U0001f3fd", "ear with hearing aid: Medium Skin Tone", []string{"ear_with_hearing_aid_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9bb\U0001f3fe", "ear with hearing aid: Medium-Dark Skin Tone", []string{"ear_with_hearing_aid_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9bb\U0001f3ff", "ear with hearing aid: Dark Skin Tone", []string{"ear_with_hearing_aid_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fb", "elf: Light Skin Tone", []string{"elf_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fc", "elf: Medium-Light Skin Tone", []string{"elf_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fd", "elf: Medium Skin Tone", []string{"elf_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fe", "elf: Medium-Dark Skin Tone", []string{"elf_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3ff", "elf: Dark Skin Tone", []string{"elf_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3ff\u200d\u2642\ufe0f", "man elf: Dark Skin Tone", []string{"elf_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fb\u200d\u2642\ufe0f", "man elf: Light Skin Tone", []string{"elf_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fc\u200d\u2642\ufe0f", "man elf: Medium-Light Skin Tone", []string{"elf_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fd\u200d\u2642\ufe0f", "man elf: Medium Skin Tone", []string{"elf_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fe\u200d\u2642\ufe0f", "man elf: Medium-Dark Skin Tone", []string{"elf_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fb\u200d\u2640\ufe0f", "woman elf: Light Skin Tone", []string{"elf_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fc\u200d\u2640\ufe0f", "woman elf: Medium-Light Skin Tone", []string{"elf_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fd\u200d\u2640\ufe0f", "woman elf: Medium Skin Tone", []string{"elf_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3fe\u200d\u2640\ufe0f", "woman elf: Medium-Dark Skin Tone", []string{"elf_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dd\U0001f3ff\u200d\u2640\ufe0f", "woman elf: Dark Skin Tone", []string{"elf_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fb", "person facepalming: Light Skin Tone", []string{"facepalm_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fc", "person facepalming: Medium-Light Skin Tone", []string{"facepalm_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fd", "person facepalming: Medium Skin Tone", []string{"facepalm_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fe", "person facepalming: Medium-Dark Skin Tone", []string{"facepalm_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3ff", "person facepalming: Dark Skin Tone", []string{"facepalm_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f3ed", "factory worker: Dark Skin Tone", []string{"factory_worker_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f3ed", "factory worker: Light Skin Tone", []string{"factory_worker_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f3ed", "factory worker: Medium-Light Skin Tone", []string{"factory_worker_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f3ed", "factory worker: Medium Skin Tone", []string{"factory_worker_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f3ed", "factory worker: Medium-Dark Skin Tone", []string{"factory_worker_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fb", "fairy: Light Skin Tone", []string{"fairy_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fc", "fairy: Medium-Light Skin Tone", []string{"fairy_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fd", "fairy: Medium Skin Tone", []string{"fairy_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fe", "fairy: Medium-Dark Skin Tone", []string{"fairy_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3ff", "fairy: Dark Skin Tone", []string{"fairy_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fb\u200d\u2642\ufe0f", "man fairy: Light Skin Tone", []string{"fairy_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fc\u200d\u2642\ufe0f", "man fairy: Medium-Light Skin Tone", []string{"fairy_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fd\u200d\u2642\ufe0f", "man fairy: Medium Skin Tone", []string{"fairy_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fe\u200d\u2642\ufe0f", "man fairy: Medium-Dark Skin Tone", []string{"fairy_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3ff\u200d\u2642\ufe0f", "man fairy: Dark Skin Tone", []string{"fairy_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fe\u200d\u2640\ufe0f", "woman fairy: Medium-Dark Skin Tone", []string{"fairy_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3ff\u200d\u2640\ufe0f", "woman fairy: Dark Skin Tone", []string{"fairy_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fb\u200d\u2640\ufe0f", "woman fairy: Light Skin Tone", []string{"fairy_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fc\u200d\u2640\ufe0f", "woman fairy: Medium-Light Skin Tone", []string{"fairy_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9da\U0001f3fd\u200d\u2640\ufe0f", "woman fairy: Medium Skin Tone", []string{"fairy_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f33e", "farmer: Light Skin Tone", []string{"farmer_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f33e", "farmer: Medium-Light Skin Tone", []string{"farmer_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f33e", "farmer: Medium Skin Tone", []string{"farmer_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f33e", "farmer: Medium-Dark Skin Tone", []string{"farmer_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f33e", "farmer: Dark Skin Tone", []string{"farmer_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fc\ufe0f\u200d\u2640\ufe0f", "woman detective: Medium-Light Skin Tone", []string{"female_detective_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fd\ufe0f\u200d\u2640\ufe0f", "woman detective: Medium Skin Tone", []string{"female_detective_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fe\ufe0f\u200d\u2640\ufe0f", "woman detective: Medium-Dark Skin Tone", []string{"female_detective_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3ff\ufe0f\u200d\u2640\ufe0f", "woman detective: Dark Skin Tone", []string{"female_detective_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fb\ufe0f\u200d\u2640\ufe0f", "woman detective: Light Skin Tone", []string{"female_detective_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f692", "firefighter: Medium-Light Skin Tone", []string{"firefighter_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f692", "firefighter: Medium Skin Tone", []string{"firefighter_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f692", "firefighter: Medium-Dark Skin Tone", []string{"firefighter_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f692", "firefighter: Dark Skin Tone", []string{"firefighter_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f692", "firefighter: Light Skin Tone", []string{"firefighter_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f91b\U0001f3fc", "left-facing fist: Medium-Light Skin Tone", []string{"fist_left_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f91b\U0001f3fd", "left-facing fist: Medium Skin Tone", []string{"fist_left_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f91b\U0001f3fe", "left-facing fist: Medium-Dark Skin Tone", []string{"fist_left_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f91b\U0001f3ff", "left-facing fist: Dark Skin Tone", []string{"fist_left_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f91b\U0001f3fb", "left-facing fist: Light Skin Tone", []string{"fist_left_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44a\U0001f3fc", "oncoming fist: Medium-Light Skin Tone", []string{"fist_oncoming_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44a\U0001f3fd", "oncoming fist: Medium Skin Tone", []string{"fist_oncoming_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f44a\U0001f3fe", "oncoming fist: Medium-Dark Skin Tone", []string{"fist_oncoming_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f44a\U0001f3ff", "oncoming fist: Dark Skin Tone", []string{"fist_oncoming_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f44a\U0001f3fb", "oncoming fist: Light Skin Tone", []string{"fist_oncoming_Light_Skin_Tone"}, "12.0", false},
+	{"\u270a\U0001f3fc", "raised fist: Medium-Light Skin Tone", []string{"fist_raised_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\u270a\U0001f3fd", "raised fist: Medium Skin Tone", []string{"fist_raised_Medium_Skin_Tone"}, "12.0", false},
+	{"\u270a\U0001f3fe", "raised fist: Medium-Dark Skin Tone", []string{"fist_raised_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\u270a\U0001f3ff", "raised fist: Dark Skin Tone", []string{"fist_raised_Dark_Skin_Tone"}, "12.0", false},
+	{"\u270a\U0001f3fb", "raised fist: Light Skin Tone", []string{"fist_raised_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f91c\U0001f3fb", "right-facing fist: Light Skin Tone", []string{"fist_right_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f91c\U0001f3fc", "right-facing fist: Medium-Light Skin Tone", []string{"fist_right_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f91c\U0001f3fd", "right-facing fist: Medium Skin Tone", []string{"fist_right_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f91c\U0001f3fe", "right-facing fist: Medium-Dark Skin Tone", []string{"fist_right_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f91c\U0001f3ff", "right-facing fist: Dark Skin Tone", []string{"fist_right_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b6\U0001f3fd", "foot: Medium Skin Tone", []string{"foot_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b6\U0001f3fe", "foot: Medium-Dark Skin Tone", []string{"foot_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b6\U0001f3ff", "foot: Dark Skin Tone", []string{"foot_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b6\U0001f3fb", "foot: Light Skin Tone", []string{"foot_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b6\U0001f3fc", "foot: Medium-Light Skin Tone", []string{"foot_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fe\u200d\u2642\ufe0f", "man frowning: Medium-Dark Skin Tone", []string{"frowning_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3ff\u200d\u2642\ufe0f", "man frowning: Dark Skin Tone", []string{"frowning_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fb\u200d\u2642\ufe0f", "man frowning: Light Skin Tone", []string{"frowning_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fc\u200d\u2642\ufe0f", "man frowning: Medium-Light Skin Tone", []string{"frowning_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fd\u200d\u2642\ufe0f", "man frowning: Medium Skin Tone", []string{"frowning_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fd", "person frowning: Medium Skin Tone", []string{"frowning_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fe", "person frowning: Medium-Dark Skin Tone", []string{"frowning_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3ff", "person frowning: Dark Skin Tone", []string{"frowning_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fb", "person frowning: Light Skin Tone", []string{"frowning_person_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fc", "person frowning: Medium-Light Skin Tone", []string{"frowning_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fb\u200d\u2640\ufe0f", "woman frowning: Light Skin Tone", []string{"frowning_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fc\u200d\u2640\ufe0f", "woman frowning: Medium-Light Skin Tone", []string{"frowning_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fd\u200d\u2640\ufe0f", "woman frowning: Medium Skin Tone", []string{"frowning_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3fe\u200d\u2640\ufe0f", "woman frowning: Medium-Dark Skin Tone", []string{"frowning_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64d\U0001f3ff\u200d\u2640\ufe0f", "woman frowning: Dark Skin Tone", []string{"frowning_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f467\U0001f3fc", "girl: Medium-Light Skin Tone", []string{"girl_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f467\U0001f3fd", "girl: Medium Skin Tone", []string{"girl_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f467\U0001f3fe", "girl: Medium-Dark Skin Tone", []string{"girl_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f467\U0001f3ff", "girl: Dark Skin Tone", []string{"girl_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f467\U0001f3fb", "girl: Light Skin Tone", []string{"girl_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fb\ufe0f", "person golfing: Light Skin Tone", []string{"golfing_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fc\ufe0f", "person golfing: Medium-Light Skin Tone", []string{"golfing_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fd\ufe0f", "person golfing: Medium Skin Tone", []string{"golfing_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fe\ufe0f", "person golfing: Medium-Dark Skin Tone", []string{"golfing_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3ff\ufe0f", "person golfing: Dark Skin Tone", []string{"golfing_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fb\ufe0f\u200d\u2642\ufe0f", "man golfing: Light Skin Tone", []string{"golfing_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fc\ufe0f\u200d\u2642\ufe0f", "man golfing: Medium-Light Skin Tone", []string{"golfing_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fd\ufe0f\u200d\u2642\ufe0f", "man golfing: Medium Skin Tone", []string{"golfing_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fe\ufe0f\u200d\u2642\ufe0f", "man golfing: Medium-Dark Skin Tone", []string{"golfing_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3ff\ufe0f\u200d\u2642\ufe0f", "man golfing: Dark Skin Tone", []string{"golfing_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fb\ufe0f\u200d\u2640\ufe0f", "woman golfing: Light Skin Tone", []string{"golfing_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fc\ufe0f\u200d\u2640\ufe0f", "woman golfing: Medium-Light Skin Tone", []string{"golfing_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fd\ufe0f\u200d\u2640\ufe0f", "woman golfing: Medium Skin Tone", []string{"golfing_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3fe\ufe0f\u200d\u2640\ufe0f", "woman golfing: Medium-Dark Skin Tone", []string{"golfing_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cc\U0001f3ff\ufe0f\u200d\u2640\ufe0f", "woman golfing: Dark Skin Tone", []string{"golfing_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fb", "guard: Light Skin Tone", []string{"guard_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fc", "guard: Medium-Light Skin Tone", []string{"guard_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fd", "guard: Medium Skin Tone", []string{"guard_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fe", "guard: Medium-Dark Skin Tone", []string{"guard_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3ff", "guard: Dark Skin Tone", []string{"guard_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3ff\u200d\u2642\ufe0f", "man guard: Dark Skin Tone", []string{"guardsman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fb\u200d\u2642\ufe0f", "man guard: Light Skin Tone", []string{"guardsman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fc\u200d\u2642\ufe0f", "man guard: Medium-Light Skin Tone", []string{"guardsman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fd\u200d\u2642\ufe0f", "man guard: Medium Skin Tone", []string{"guardsman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fe\u200d\u2642\ufe0f", "man guard: Medium-Dark Skin Tone", []string{"guardsman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fb\u200d\u2640\ufe0f", "woman guard: Light Skin Tone", []string{"guardswoman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fc\u200d\u2640\ufe0f", "woman guard: Medium-Light Skin Tone", []string{"guardswoman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fd\u200d\u2640\ufe0f", "woman guard: Medium Skin Tone", []string{"guardswoman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3fe\u200d\u2640\ufe0f", "woman guard: Medium-Dark Skin Tone", []string{"guardswoman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f482\U0001f3ff\u200d\u2640\ufe0f", "woman guard: Dark Skin Tone", []string{"guardswoman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fe", "person getting haircut: Medium-Dark Skin Tone", []string{"haircut_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3ff", "person getting haircut: Dark Skin Tone", []string{"haircut_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fb", "person getting haircut: Light Skin Tone", []string{"haircut_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fc", "person getting haircut: Medium-Light Skin Tone", []string{"haircut_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fd", "person getting haircut: Medium Skin Tone", []string{"haircut_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fb\u200d\u2642\ufe0f", "man getting haircut: Light Skin Tone", []string{"haircut_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fc\u200d\u2642\ufe0f", "man getting haircut: Medium-Light Skin Tone", []string{"haircut_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fd\u200d\u2642\ufe0f", "man getting haircut: Medium Skin Tone", []string{"haircut_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fe\u200d\u2642\ufe0f", "man getting haircut: Medium-Dark Skin Tone", []string{"haircut_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3ff\u200d\u2642\ufe0f", "man getting haircut: Dark Skin Tone", []string{"haircut_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fc\u200d\u2640\ufe0f", "woman getting haircut: Medium-Light Skin Tone", []string{"haircut_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fd\u200d\u2640\ufe0f", "woman getting haircut: Medium Skin Tone", []string{"haircut_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fe\u200d\u2640\ufe0f", "woman getting haircut: Medium-Dark Skin Tone", []string{"haircut_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3ff\u200d\u2640\ufe0f", "woman getting haircut: Dark Skin Tone", []string{"haircut_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f487\U0001f3fb\u200d\u2640\ufe0f", "woman getting haircut: Light Skin Tone", []string{"haircut_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\u270b\U0001f3fc", "raised hand: Medium-Light Skin Tone", []string{"hand_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\u270b\U0001f3fd", "raised hand: Medium Skin Tone", []string{"hand_Medium_Skin_Tone"}, "12.0", false},
+	{"\u270b\U0001f3fe", "raised hand: Medium-Dark Skin Tone", []string{"hand_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\u270b\U0001f3ff", "raised hand: Dark Skin Tone", []string{"hand_Dark_Skin_Tone"}, "12.0", false},
+	{"\u270b\U0001f3fb", "raised hand: Light Skin Tone", []string{"hand_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fe", "person playing handball: Medium-Dark Skin Tone", []string{"handball_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3ff", "person playing handball: Dark Skin Tone", []string{"handball_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fb", "person playing handball: Light Skin Tone", []string{"handball_person_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fc", "person playing handball: Medium-Light Skin Tone", []string{"handball_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fd", "person playing handball: Medium Skin Tone", []string{"handball_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\u2695\ufe0f", "health worker: Dark Skin Tone", []string{"health_worker_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\u2695\ufe0f", "health worker: Light Skin Tone", []string{"health_worker_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\u2695\ufe0f", "health worker: Medium-Light Skin Tone", []string{"health_worker_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\u2695\ufe0f", "health worker: Medium Skin Tone", []string{"health_worker_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\u2695\ufe0f", "health worker: Medium-Dark Skin Tone", []string{"health_worker_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c7\U0001f3fd", "horse racing: Medium Skin Tone", []string{"horse_racing_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c7\U0001f3fe", "horse racing: Medium-Dark Skin Tone", []string{"horse_racing_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c7\U0001f3ff", "horse racing: Dark Skin Tone", []string{"horse_racing_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c7\U0001f3fb", "horse racing: Light Skin Tone", []string{"horse_racing_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c7\U0001f3fc", "horse racing: Medium-Light Skin Tone", []string{"horse_racing_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\u2696\ufe0f", "judge: Medium-Light Skin Tone", []string{"judge_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\u2696\ufe0f", "judge: Medium Skin Tone", []string{"judge_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\u2696\ufe0f", "judge: Medium-Dark Skin Tone", []string{"judge_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\u2696\ufe0f", "judge: Dark Skin Tone", []string{"judge_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\u2696\ufe0f", "judge: Light Skin Tone", []string{"judge_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fd", "person juggling: Medium Skin Tone", []string{"juggling_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fe", "person juggling: Medium-Dark Skin Tone", []string{"juggling_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3ff", "person juggling: Dark Skin Tone", []string{"juggling_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fb", "person juggling: Light Skin Tone", []string{"juggling_person_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fc", "person juggling: Medium-Light Skin Tone", []string{"juggling_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fb\u200d\u2642\ufe0f", "man kneeling: Light Skin Tone", []string{"kneeling_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fc\u200d\u2642\ufe0f", "man kneeling: Medium-Light Skin Tone", []string{"kneeling_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fd\u200d\u2642\ufe0f", "man kneeling: Medium Skin Tone", []string{"kneeling_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fe\u200d\u2642\ufe0f", "man kneeling: Medium-Dark Skin Tone", []string{"kneeling_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3ff\u200d\u2642\ufe0f", "man kneeling: Dark Skin Tone", []string{"kneeling_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fb", "person kneeling: Light Skin Tone", []string{"kneeling_person_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fc", "person kneeling: Medium-Light Skin Tone", []string{"kneeling_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fd", "person kneeling: Medium Skin Tone", []string{"kneeling_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fe", "person kneeling: Medium-Dark Skin Tone", []string{"kneeling_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3ff", "person kneeling: Dark Skin Tone", []string{"kneeling_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3ff\u200d\u2640\ufe0f", "woman kneeling: Dark Skin Tone", []string{"kneeling_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fb\u200d\u2640\ufe0f", "woman kneeling: Light Skin Tone", []string{"kneeling_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fc\u200d\u2640\ufe0f", "woman kneeling: Medium-Light Skin Tone", []string{"kneeling_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fd\u200d\u2640\ufe0f", "woman kneeling: Medium Skin Tone", []string{"kneeling_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9ce\U0001f3fe\u200d\u2640\ufe0f", "woman kneeling: Medium-Dark Skin Tone", []string{"kneeling_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b5\U0001f3fb", "leg: Light Skin Tone", []string{"leg_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b5\U0001f3fc", "leg: Medium-Light Skin Tone", []string{"leg_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b5\U0001f3fd", "leg: Medium Skin Tone", []string{"leg_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b5\U0001f3fe", "leg: Medium-Dark Skin Tone", []string{"leg_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b5\U0001f3ff", "leg: Dark Skin Tone", []string{"leg_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fd", "person in lotus position: Medium Skin Tone", []string{"lotus_position_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fe", "person in lotus position: Medium-Dark Skin Tone", []string{"lotus_position_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3ff", "person in lotus position: Dark Skin Tone", []string{"lotus_position_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fb", "person in lotus position: Light Skin Tone", []string{"lotus_position_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fc", "person in lotus position: Medium-Light Skin Tone", []string{"lotus_position_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fd\u200d\u2642\ufe0f", "man in lotus position: Medium Skin Tone", []string{"lotus_position_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fe\u200d\u2642\ufe0f", "man in lotus position: Medium-Dark Skin Tone", []string{"lotus_position_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3ff\u200d\u2642\ufe0f", "man in lotus position: Dark Skin Tone", []string{"lotus_position_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fb\u200d\u2642\ufe0f", "man in lotus position: Light Skin Tone", []string{"lotus_position_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fc\u200d\u2642\ufe0f", "man in lotus position: Medium-Light Skin Tone", []string{"lotus_position_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fd\u200d\u2640\ufe0f", "woman in lotus position: Medium Skin Tone", []string{"lotus_position_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fe\u200d\u2640\ufe0f", "woman in lotus position: Medium-Dark Skin Tone", []string{"lotus_position_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3ff\u200d\u2640\ufe0f", "woman in lotus position: Dark Skin Tone", []string{"lotus_position_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fb\u200d\u2640\ufe0f", "woman in lotus position: Light Skin Tone", []string{"lotus_position_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d8\U0001f3fc\u200d\u2640\ufe0f", "woman in lotus position: Medium-Light Skin Tone", []string{"lotus_position_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f91f\U0001f3fc", "love-you gesture: Medium-Light Skin Tone", []string{"love_you_gesture_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f91f\U0001f3fd", "love-you gesture: Medium Skin Tone", []string{"love_you_gesture_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f91f\U0001f3fe", "love-you gesture: Medium-Dark Skin Tone", []string{"love_you_gesture_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f91f\U0001f3ff", "love-you gesture: Dark Skin Tone", []string{"love_you_gesture_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f91f\U0001f3fb", "love-you gesture: Light Skin Tone", []string{"love_you_gesture_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fb", "mage: Light Skin Tone", []string{"mage_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fc", "mage: Medium-Light Skin Tone", []string{"mage_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fd", "mage: Medium Skin Tone", []string{"mage_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fe", "mage: Medium-Dark Skin Tone", []string{"mage_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3ff", "mage: Dark Skin Tone", []string{"mage_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fe\u200d\u2642\ufe0f", "man mage: Medium-Dark Skin Tone", []string{"mage_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3ff\u200d\u2642\ufe0f", "man mage: Dark Skin Tone", []string{"mage_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fb\u200d\u2642\ufe0f", "man mage: Light Skin Tone", []string{"mage_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fc\u200d\u2642\ufe0f", "man mage: Medium-Light Skin Tone", []string{"mage_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fd\u200d\u2642\ufe0f", "man mage: Medium Skin Tone", []string{"mage_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fb\u200d\u2640\ufe0f", "woman mage: Light Skin Tone", []string{"mage_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fc\u200d\u2640\ufe0f", "woman mage: Medium-Light Skin Tone", []string{"mage_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fd\u200d\u2640\ufe0f", "woman mage: Medium Skin Tone", []string{"mage_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3fe\u200d\u2640\ufe0f", "woman mage: Medium-Dark Skin Tone", []string{"mage_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d9\U0001f3ff\u200d\u2640\ufe0f", "woman mage: Dark Skin Tone", []string{"mage_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fc\ufe0f\u200d\u2642\ufe0f", "man detective: Medium-Light Skin Tone", []string{"male_detective_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fd\ufe0f\u200d\u2642\ufe0f", "man detective: Medium Skin Tone", []string{"male_detective_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fe\ufe0f\u200d\u2642\ufe0f", "man detective: Medium-Dark Skin Tone", []string{"male_detective_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3ff\ufe0f\u200d\u2642\ufe0f", "man detective: Dark Skin Tone", []string{"male_detective_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f575\U0001f3fb\ufe0f\u200d\u2642\ufe0f", "man detective: Light Skin Tone", []string{"male_detective_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe", "man: Medium-Dark Skin Tone", []string{"man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff", "man: Dark Skin Tone", []string{"man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb", "man: Light Skin Tone", []string{"man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc", "man: Medium-Light Skin Tone", []string{"man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd", "man: Medium Skin Tone", []string{"man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f3a8", "man artist: Dark Skin Tone", []string{"man_artist_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f3a8", "man artist: Light Skin Tone", []string{"man_artist_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f3a8", "man artist: Medium-Light Skin Tone", []string{"man_artist_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f3a8", "man artist: Medium Skin Tone", []string{"man_artist_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f3a8", "man artist: Medium-Dark Skin Tone", []string{"man_artist_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f680", "man astronaut: Medium Skin Tone", []string{"man_astronaut_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f680", "man astronaut: Medium-Dark Skin Tone", []string{"man_astronaut_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f680", "man astronaut: Dark Skin Tone", []string{"man_astronaut_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f680", "man astronaut: Light Skin Tone", []string{"man_astronaut_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f680", "man astronaut: Medium-Light Skin Tone", []string{"man_astronaut_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fc\u200d\u2642\ufe0f", "man cartwheeling: Medium-Light Skin Tone", []string{"man_cartwheeling_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fd\u200d\u2642\ufe0f", "man cartwheeling: Medium Skin Tone", []string{"man_cartwheeling_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fe\u200d\u2642\ufe0f", "man cartwheeling: Medium-Dark Skin Tone", []string{"man_cartwheeling_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3ff\u200d\u2642\ufe0f", "man cartwheeling: Dark Skin Tone", []string{"man_cartwheeling_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fb\u200d\u2642\ufe0f", "man cartwheeling: Light Skin Tone", []string{"man_cartwheeling_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f373", "man cook: Medium-Dark Skin Tone", []string{"man_cook_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f373", "man cook: Dark Skin Tone", []string{"man_cook_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f373", "man cook: Light Skin Tone", []string{"man_cook_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f373", "man cook: Medium-Light Skin Tone", []string{"man_cook_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f373", "man cook: Medium Skin Tone", []string{"man_cook_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f57a\U0001f3fb", "man dancing: Light Skin Tone", []string{"man_dancing_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f57a\U0001f3fc", "man dancing: Medium-Light Skin Tone", []string{"man_dancing_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f57a\U0001f3fd", "man dancing: Medium Skin Tone", []string{"man_dancing_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f57a\U0001f3fe", "man dancing: Medium-Dark Skin Tone", []string{"man_dancing_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f57a\U0001f3ff", "man dancing: Dark Skin Tone", []string{"man_dancing_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fe\u200d\u2642\ufe0f", "man facepalming: Medium-Dark Skin Tone", []string{"man_facepalming_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3ff\u200d\u2642\ufe0f", "man facepalming: Dark Skin Tone", []string{"man_facepalming_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fb\u200d\u2642\ufe0f", "man facepalming: Light Skin Tone", []string{"man_facepalming_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fc\u200d\u2642\ufe0f", "man facepalming: Medium-Light Skin Tone", []string{"man_facepalming_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fd\u200d\u2642\ufe0f", "man facepalming: Medium Skin Tone", []string{"man_facepalming_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f3ed", "man factory worker: Dark Skin Tone", []string{"man_factory_worker_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f3ed", "man factory worker: Light Skin Tone", []string{"man_factory_worker_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f3ed", "man factory worker: Medium-Light Skin Tone", []string{"man_factory_worker_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f3ed", "man factory worker: Medium Skin Tone", []string{"man_factory_worker_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f3ed", "man factory worker: Medium-Dark Skin Tone", []string{"man_factory_worker_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f33e", "man farmer: Light Skin Tone", []string{"man_farmer_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f33e", "man farmer: Medium-Light Skin Tone", []string{"man_farmer_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f33e", "man farmer: Medium Skin Tone", []string{"man_farmer_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f33e", "man farmer: Medium-Dark Skin Tone", []string{"man_farmer_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f33e", "man farmer: Dark Skin Tone", []string{"man_farmer_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f692", "man firefighter: Dark Skin Tone", []string{"man_firefighter_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f692", "man firefighter: Light Skin Tone", []string{"man_firefighter_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f692", "man firefighter: Medium-Light Skin Tone", []string{"man_firefighter_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f692", "man firefighter: Medium Skin Tone", []string{"man_firefighter_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f692", "man firefighter: Medium-Dark Skin Tone", []string{"man_firefighter_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\u2695\ufe0f", "man health worker: Light Skin Tone", []string{"man_health_worker_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\u2695\ufe0f", "man health worker: Medium-Light Skin Tone", []string{"man_health_worker_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\u2695\ufe0f", "man health worker: Medium Skin Tone", []string{"man_health_worker_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\u2695\ufe0f", "man health worker: Medium-Dark Skin Tone", []string{"man_health_worker_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\u2695\ufe0f", "man health worker: Dark Skin Tone", []string{"man_health_worker_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f9bd", "man in manual wheelchair: Light Skin Tone", []string{"man_in_manual_wheelchair_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f9bd", "man in manual wheelchair: Medium-Light Skin Tone", []string{"man_in_manual_wheelchair_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f9bd", "man in manual wheelchair: Medium Skin Tone", []string{"man_in_manual_wheelchair_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f9bd", "man in manual wheelchair: Medium-Dark Skin Tone", []string{"man_in_manual_wheelchair_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f9bd", "man in manual wheelchair: Dark Skin Tone", []string{"man_in_manual_wheelchair_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f9bc", "man in motorized wheelchair: Light Skin Tone", []string{"man_in_motorized_wheelchair_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f9bc", "man in motorized wheelchair: Medium-Light Skin Tone", []string{"man_in_motorized_wheelchair_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f9bc", "man in motorized wheelchair: Medium Skin Tone", []string{"man_in_motorized_wheelchair_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f9bc", "man in motorized wheelchair: Medium-Dark Skin Tone", []string{"man_in_motorized_wheelchair_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f9bc", "man in motorized wheelchair: Dark Skin Tone", []string{"man_in_motorized_wheelchair_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\u2696\ufe0f", "man judge: Medium Skin Tone", []string{"man_judge_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\u2696\ufe0f", "man judge: Medium-Dark Skin Tone", []string{"man_judge_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\u2696\ufe0f", "man judge: Dark Skin Tone", []string{"man_judge_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\u2696\ufe0f", "man judge: Light Skin Tone", []string{"man_judge_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\u2696\ufe0f", "man judge: Medium-Light Skin Tone", []string{"man_judge_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fe\u200d\u2642\ufe0f", "man juggling: Medium-Dark Skin Tone", []string{"man_juggling_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3ff\u200d\u2642\ufe0f", "man juggling: Dark Skin Tone", []string{"man_juggling_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fb\u200d\u2642\ufe0f", "man juggling: Light Skin Tone", []string{"man_juggling_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fc\u200d\u2642\ufe0f", "man juggling: Medium-Light Skin Tone", []string{"man_juggling_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fd\u200d\u2642\ufe0f", "man juggling: Medium Skin Tone", []string{"man_juggling_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f527", "man mechanic: Light Skin Tone", []string{"man_mechanic_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f527", "man mechanic: Medium-Light Skin Tone", []string{"man_mechanic_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f527", "man mechanic: Medium Skin Tone", []string{"man_mechanic_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f527", "man mechanic: Medium-Dark Skin Tone", []string{"man_mechanic_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f527", "man mechanic: Dark Skin Tone", []string{"man_mechanic_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f4bc", "man office worker: Light Skin Tone", []string{"man_office_worker_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f4bc", "man office worker: Medium-Light Skin Tone", []string{"man_office_worker_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f4bc", "man office worker: Medium Skin Tone", []string{"man_office_worker_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f4bc", "man office worker: Medium-Dark Skin Tone", []string{"man_office_worker_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f4bc", "man office worker: Dark Skin Tone", []string{"man_office_worker_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\u2708\ufe0f", "man pilot: Light Skin Tone", []string{"man_pilot_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\u2708\ufe0f", "man pilot: Medium-Light Skin Tone", []string{"man_pilot_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\u2708\ufe0f", "man pilot: Medium Skin Tone", []string{"man_pilot_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\u2708\ufe0f", "man pilot: Medium-Dark Skin Tone", []string{"man_pilot_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\u2708\ufe0f", "man pilot: Dark Skin Tone", []string{"man_pilot_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fb\u200d\u2642\ufe0f", "man playing handball: Light Skin Tone", []string{"man_playing_handball_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fc\u200d\u2642\ufe0f", "man playing handball: Medium-Light Skin Tone", []string{"man_playing_handball_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fd\u200d\u2642\ufe0f", "man playing handball: Medium Skin Tone", []string{"man_playing_handball_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fe\u200d\u2642\ufe0f", "man playing handball: Medium-Dark Skin Tone", []string{"man_playing_handball_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3ff\u200d\u2642\ufe0f", "man playing handball: Dark Skin Tone", []string{"man_playing_handball_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fb\u200d\u2642\ufe0f", "man playing water polo: Light Skin Tone", []string{"man_playing_water_polo_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fc\u200d\u2642\ufe0f", "man playing water polo: Medium-Light Skin Tone", []string{"man_playing_water_polo_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fd\u200d\u2642\ufe0f", "man playing water polo: Medium Skin Tone", []string{"man_playing_water_polo_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fe\u200d\u2642\ufe0f", "man playing water polo: Medium-Dark Skin Tone", []string{"man_playing_water_polo_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3ff\u200d\u2642\ufe0f", "man playing water polo: Dark Skin Tone", []string{"man_playing_water_polo_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f52c", "man scientist: Light Skin Tone", []string{"man_scientist_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f52c", "man scientist: Medium-Light Skin Tone", []string{"man_scientist_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f52c", "man scientist: Medium Skin Tone", []string{"man_scientist_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f52c", "man scientist: Medium-Dark Skin Tone", []string{"man_scientist_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f52c", "man scientist: Dark Skin Tone", []string{"man_scientist_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fb\u200d\u2642\ufe0f", "man shrugging: Light Skin Tone", []string{"man_shrugging_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fc\u200d\u2642\ufe0f", "man shrugging: Medium-Light Skin Tone", []string{"man_shrugging_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fd\u200d\u2642\ufe0f", "man shrugging: Medium Skin Tone", []string{"man_shrugging_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fe\u200d\u2642\ufe0f", "man shrugging: Medium-Dark Skin Tone", []string{"man_shrugging_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3ff\u200d\u2642\ufe0f", "man shrugging: Dark Skin Tone", []string{"man_shrugging_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f3a4", "man singer: Light Skin Tone", []string{"man_singer_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f3a4", "man singer: Medium-Light Skin Tone", []string{"man_singer_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f3a4", "man singer: Medium Skin Tone", []string{"man_singer_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f3a4", "man singer: Medium-Dark Skin Tone", []string{"man_singer_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f3a4", "man singer: Dark Skin Tone", []string{"man_singer_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f393", "man student: Medium-Dark Skin Tone", []string{"man_student_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f393", "man student: Dark Skin Tone", []string{"man_student_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f393", "man student: Light Skin Tone", []string{"man_student_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f393", "man student: Medium-Light Skin Tone", []string{"man_student_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f393", "man student: Medium Skin Tone", []string{"man_student_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f3eb", "man teacher: Medium-Light Skin Tone", []string{"man_teacher_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f3eb", "man teacher: Medium Skin Tone", []string{"man_teacher_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f3eb", "man teacher: Medium-Dark Skin Tone", []string{"man_teacher_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f3eb", "man teacher: Dark Skin Tone", []string{"man_teacher_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f3eb", "man teacher: Light Skin Tone", []string{"man_teacher_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f4bb", "man technologist: Light Skin Tone", []string{"man_technologist_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f4bb", "man technologist: Medium-Light Skin Tone", []string{"man_technologist_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f4bb", "man technologist: Medium Skin Tone", []string{"man_technologist_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f4bb", "man technologist: Medium-Dark Skin Tone", []string{"man_technologist_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f4bb", "man technologist: Dark Skin Tone", []string{"man_technologist_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f472\U0001f3fb", "person with skullcap: Light Skin Tone", []string{"man_with_gua_pi_mao_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f472\U0001f3fc", "person with skullcap: Medium-Light Skin Tone", []string{"man_with_gua_pi_mao_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f472\U0001f3fd", "person with skullcap: Medium Skin Tone", []string{"man_with_gua_pi_mao_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f472\U0001f3fe", "person with skullcap: Medium-Dark Skin Tone", []string{"man_with_gua_pi_mao_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f472\U0001f3ff", "person with skullcap: Dark Skin Tone", []string{"man_with_gua_pi_mao_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f9af", "man with white cane: Medium-Dark Skin Tone", []string{"man_with_probing_cane_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f9af", "man with white cane: Dark Skin Tone", []string{"man_with_probing_cane_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f9af", "man with white cane: Light Skin Tone", []string{"man_with_probing_cane_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f9af", "man with white cane: Medium-Light Skin Tone", []string{"man_with_probing_cane_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f9af", "man with white cane: Medium Skin Tone", []string{"man_with_probing_cane_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fe\u200d\u2642\ufe0f", "man wearing turban: Medium-Dark Skin Tone", []string{"man_with_turban_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3ff\u200d\u2642\ufe0f", "man wearing turban: Dark Skin Tone", []string{"man_with_turban_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fb\u200d\u2642\ufe0f", "man wearing turban: Light Skin Tone", []string{"man_with_turban_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fc\u200d\u2642\ufe0f", "man wearing turban: Medium-Light Skin Tone", []string{"man_with_turban_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fd\u200d\u2642\ufe0f", "man wearing turban: Medium Skin Tone", []string{"man_with_turban_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fb", "person getting massage: Light Skin Tone", []string{"massage_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fc", "person getting massage: Medium-Light Skin Tone", []string{"massage_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fd", "person getting massage: Medium Skin Tone", []string{"massage_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fe", "person getting massage: Medium-Dark Skin Tone", []string{"massage_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3ff", "person getting massage: Dark Skin Tone", []string{"massage_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fe\u200d\u2642\ufe0f", "man getting massage: Medium-Dark Skin Tone", []string{"massage_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3ff\u200d\u2642\ufe0f", "man getting massage: Dark Skin Tone", []string{"massage_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fb\u200d\u2642\ufe0f", "man getting massage: Light Skin Tone", []string{"massage_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fc\u200d\u2642\ufe0f", "man getting massage: Medium-Light Skin Tone", []string{"massage_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fd\u200d\u2642\ufe0f", "man getting massage: Medium Skin Tone", []string{"massage_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fd\u200d\u2640\ufe0f", "woman getting massage: Medium Skin Tone", []string{"massage_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fe\u200d\u2640\ufe0f", "woman getting massage: Medium-Dark Skin Tone", []string{"massage_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3ff\u200d\u2640\ufe0f", "woman getting massage: Dark Skin Tone", []string{"massage_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fb\u200d\u2640\ufe0f", "woman getting massage: Light Skin Tone", []string{"massage_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f486\U0001f3fc\u200d\u2640\ufe0f", "woman getting massage: Medium-Light Skin Tone", []string{"massage_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f527", "mechanic: Light Skin Tone", []string{"mechanic_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f527", "mechanic: Medium-Light Skin Tone", []string{"mechanic_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f527", "mechanic: Medium Skin Tone", []string{"mechanic_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f527", "mechanic: Medium-Dark Skin Tone", []string{"mechanic_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f527", "mechanic: Dark Skin Tone", []string{"mechanic_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3ff\u200d\u2640\ufe0f", "mermaid: Dark Skin Tone", []string{"mermaid_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fb\u200d\u2640\ufe0f", "mermaid: Light Skin Tone", []string{"mermaid_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fc\u200d\u2640\ufe0f", "mermaid: Medium-Light Skin Tone", []string{"mermaid_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fd\u200d\u2640\ufe0f", "mermaid: Medium Skin Tone", []string{"mermaid_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fe\u200d\u2640\ufe0f", "mermaid: Medium-Dark Skin Tone", []string{"mermaid_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fb\u200d\u2642\ufe0f", "merman: Light Skin Tone", []string{"merman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fc\u200d\u2642\ufe0f", "merman: Medium-Light Skin Tone", []string{"merman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fd\u200d\u2642\ufe0f", "merman: Medium Skin Tone", []string{"merman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fe\u200d\u2642\ufe0f", "merman: Medium-Dark Skin Tone", []string{"merman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3ff\u200d\u2642\ufe0f", "merman: Dark Skin Tone", []string{"merman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fb", "merperson: Light Skin Tone", []string{"merperson_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fc", "merperson: Medium-Light Skin Tone", []string{"merperson_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fd", "merperson: Medium Skin Tone", []string{"merperson_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3fe", "merperson: Medium-Dark Skin Tone", []string{"merperson_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9dc\U0001f3ff", "merperson: Dark Skin Tone", []string{"merperson_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f918\U0001f3fc", "sign of the horns: Medium-Light Skin Tone", []string{"metal_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f918\U0001f3fd", "sign of the horns: Medium Skin Tone", []string{"metal_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f918\U0001f3fe", "sign of the horns: Medium-Dark Skin Tone", []string{"metal_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f918\U0001f3ff", "sign of the horns: Dark Skin Tone", []string{"metal_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f918\U0001f3fb", "sign of the horns: Light Skin Tone", []string{"metal_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f595\U0001f3fb", "middle finger: Light Skin Tone", []string{"middle_finger_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f595\U0001f3fc", "middle finger: Medium-Light Skin Tone", []string{"middle_finger_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f595\U0001f3fd", "middle finger: Medium Skin Tone", []string{"middle_finger_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f595\U0001f3fe", "middle finger: Medium-Dark Skin Tone", []string{"middle_finger_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f595\U0001f3ff", "middle finger: Dark Skin Tone", []string{"middle_finger_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fe", "person mountain biking: Medium-Dark Skin Tone", []string{"mountain_bicyclist_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3ff", "person mountain biking: Dark Skin Tone", []string{"mountain_bicyclist_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fb", "person mountain biking: Light Skin Tone", []string{"mountain_bicyclist_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fc", "person mountain biking: Medium-Light Skin Tone", []string{"mountain_bicyclist_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fd", "person mountain biking: Medium Skin Tone", []string{"mountain_bicyclist_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fb\u200d\u2642\ufe0f", "man mountain biking: Light Skin Tone", []string{"mountain_biking_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fc\u200d\u2642\ufe0f", "man mountain biking: Medium-Light Skin Tone", []string{"mountain_biking_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fd\u200d\u2642\ufe0f", "man mountain biking: Medium Skin Tone", []string{"mountain_biking_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fe\u200d\u2642\ufe0f", "man mountain biking: Medium-Dark Skin Tone", []string{"mountain_biking_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3ff\u200d\u2642\ufe0f", "man mountain biking: Dark Skin Tone", []string{"mountain_biking_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fb\u200d\u2640\ufe0f", "woman mountain biking: Light Skin Tone", []string{"mountain_biking_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fc\u200d\u2640\ufe0f", "woman mountain biking: Medium-Light Skin Tone", []string{"mountain_biking_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fd\u200d\u2640\ufe0f", "woman mountain biking: Medium Skin Tone", []string{"mountain_biking_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3fe\u200d\u2640\ufe0f", "woman mountain biking: Medium-Dark Skin Tone", []string{"mountain_biking_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b5\U0001f3ff\u200d\u2640\ufe0f", "woman mountain biking: Dark Skin Tone", []string{"mountain_biking_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f936\U0001f3fb", "Mrs. Claus: Light Skin Tone", []string{"mrs_claus_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f936\U0001f3fc", "Mrs. Claus: Medium-Light Skin Tone", []string{"mrs_claus_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f936\U0001f3fd", "Mrs. Claus: Medium Skin Tone", []string{"mrs_claus_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f936\U0001f3fe", "Mrs. Claus: Medium-Dark Skin Tone", []string{"mrs_claus_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f936\U0001f3ff", "Mrs. Claus: Dark Skin Tone", []string{"mrs_claus_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f4aa\U0001f3ff", "flexed biceps: Dark Skin Tone", []string{"muscle_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f4aa\U0001f3fb", "flexed biceps: Light Skin Tone", []string{"muscle_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f4aa\U0001f3fc", "flexed biceps: Medium-Light Skin Tone", []string{"muscle_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f4aa\U0001f3fd", "flexed biceps: Medium Skin Tone", []string{"muscle_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f4aa\U0001f3fe", "flexed biceps: Medium-Dark Skin Tone", []string{"muscle_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f485\U0001f3ff", "nail polish: Dark Skin Tone", []string{"nail_care_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f485\U0001f3fb", "nail polish: Light Skin Tone", []string{"nail_care_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f485\U0001f3fc", "nail polish: Medium-Light Skin Tone", []string{"nail_care_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f485\U0001f3fd", "nail polish: Medium Skin Tone", []string{"nail_care_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f485\U0001f3fe", "nail polish: Medium-Dark Skin Tone", []string{"nail_care_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fd", "person gesturing NO: Medium Skin Tone", []string{"no_good_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fe", "person gesturing NO: Medium-Dark Skin Tone", []string{"no_good_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3ff", "person gesturing NO: Dark Skin Tone", []string{"no_good_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fb", "person gesturing NO: Light Skin Tone", []string{"no_good_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fc", "person gesturing NO: Medium-Light Skin Tone", []string{"no_good_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fd\u200d\u2642\ufe0f", "man gesturing NO: Medium Skin Tone", []string{"no_good_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fe\u200d\u2642\ufe0f", "man gesturing NO: Medium-Dark Skin Tone", []string{"no_good_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3ff\u200d\u2642\ufe0f", "man gesturing NO: Dark Skin Tone", []string{"no_good_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fb\u200d\u2642\ufe0f", "man gesturing NO: Light Skin Tone", []string{"no_good_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fc\u200d\u2642\ufe0f", "man gesturing NO: Medium-Light Skin Tone", []string{"no_good_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fb\u200d\u2640\ufe0f", "woman gesturing NO: Light Skin Tone", []string{"no_good_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fc\u200d\u2640\ufe0f", "woman gesturing NO: Medium-Light Skin Tone", []string{"no_good_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fd\u200d\u2640\ufe0f", "woman gesturing NO: Medium Skin Tone", []string{"no_good_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3fe\u200d\u2640\ufe0f", "woman gesturing NO: Medium-Dark Skin Tone", []string{"no_good_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f645\U0001f3ff\u200d\u2640\ufe0f", "woman gesturing NO: Dark Skin Tone", []string{"no_good_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f443\U0001f3fb", "nose: Light Skin Tone", []string{"nose_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f443\U0001f3fc", "nose: Medium-Light Skin Tone", []string{"nose_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f443\U0001f3fd", "nose: Medium Skin Tone", []string{"nose_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f443\U0001f3fe", "nose: Medium-Dark Skin Tone", []string{"nose_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f443\U0001f3ff", "nose: Dark Skin Tone", []string{"nose_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f4bc", "office worker: Light Skin Tone", []string{"office_worker_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f4bc", "office worker: Medium-Light Skin Tone", []string{"office_worker_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f4bc", "office worker: Medium Skin Tone", []string{"office_worker_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f4bc", "office worker: Medium-Dark Skin Tone", []string{"office_worker_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f4bc", "office worker: Dark Skin Tone", []string{"office_worker_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f44c\U0001f3fc", "OK hand: Medium-Light Skin Tone", []string{"ok_hand_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44c\U0001f3fd", "OK hand: Medium Skin Tone", []string{"ok_hand_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f44c\U0001f3fe", "OK hand: Medium-Dark Skin Tone", []string{"ok_hand_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f44c\U0001f3ff", "OK hand: Dark Skin Tone", []string{"ok_hand_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f44c\U0001f3fb", "OK hand: Light Skin Tone", []string{"ok_hand_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fb\u200d\u2642\ufe0f", "man gesturing OK: Light Skin Tone", []string{"ok_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fc\u200d\u2642\ufe0f", "man gesturing OK: Medium-Light Skin Tone", []string{"ok_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fd\u200d\u2642\ufe0f", "man gesturing OK: Medium Skin Tone", []string{"ok_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fe\u200d\u2642\ufe0f", "man gesturing OK: Medium-Dark Skin Tone", []string{"ok_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3ff\u200d\u2642\ufe0f", "man gesturing OK: Dark Skin Tone", []string{"ok_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fb", "person gesturing OK: Light Skin Tone", []string{"ok_person_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fc", "person gesturing OK: Medium-Light Skin Tone", []string{"ok_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fd", "person gesturing OK: Medium Skin Tone", []string{"ok_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fe", "person gesturing OK: Medium-Dark Skin Tone", []string{"ok_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3ff", "person gesturing OK: Dark Skin Tone", []string{"ok_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fe\u200d\u2640\ufe0f", "woman gesturing OK: Medium-Dark Skin Tone", []string{"ok_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3ff\u200d\u2640\ufe0f", "woman gesturing OK: Dark Skin Tone", []string{"ok_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fb\u200d\u2640\ufe0f", "woman gesturing OK: Light Skin Tone", []string{"ok_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fc\u200d\u2640\ufe0f", "woman gesturing OK: Medium-Light Skin Tone", []string{"ok_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f646\U0001f3fd\u200d\u2640\ufe0f", "woman gesturing OK: Medium Skin Tone", []string{"ok_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d3\U0001f3fb", "older person: Light Skin Tone", []string{"older_adult_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d3\U0001f3fc", "older person: Medium-Light Skin Tone", []string{"older_adult_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d3\U0001f3fd", "older person: Medium Skin Tone", []string{"older_adult_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d3\U0001f3fe", "older person: Medium-Dark Skin Tone", []string{"older_adult_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d3\U0001f3ff", "older person: Dark Skin Tone", []string{"older_adult_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f474\U0001f3fb", "old man: Light Skin Tone", []string{"older_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f474\U0001f3fc", "old man: Medium-Light Skin Tone", []string{"older_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f474\U0001f3fd", "old man: Medium Skin Tone", []string{"older_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f474\U0001f3fe", "old man: Medium-Dark Skin Tone", []string{"older_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f474\U0001f3ff", "old man: Dark Skin Tone", []string{"older_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f475\U0001f3fb", "old woman: Light Skin Tone", []string{"older_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f475\U0001f3fc", "old woman: Medium-Light Skin Tone", []string{"older_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f475\U0001f3fd", "old woman: Medium Skin Tone", []string{"older_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f475\U0001f3fe", "old woman: Medium-Dark Skin Tone", []string{"older_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f475\U0001f3ff", "old woman: Dark Skin Tone", []string{"older_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f450\U0001f3fb", "open hands: Light Skin Tone", []string{"open_hands_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f450\U0001f3fc", "open hands: Medium-Light Skin Tone", []string{"open_hands_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f450\U0001f3fd", "open hands: Medium Skin Tone", []string{"open_hands_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f450\U0001f3fe", "open hands: Medium-Dark Skin Tone", []string{"open_hands_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f450\U0001f3ff", "open hands: Dark Skin Tone", []string{"open_hands_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f932\U0001f3fe", "palms up together: Medium-Dark Skin Tone", []string{"palms_up_together_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f932\U0001f3ff", "palms up together: Dark Skin Tone", []string{"palms_up_together_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f932\U0001f3fb", "palms up together: Light Skin Tone", []string{"palms_up_together_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f932\U0001f3fc", "palms up together: Medium-Light Skin Tone", []string{"palms_up_together_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f932\U0001f3fd", "palms up together: Medium Skin Tone", []string{"palms_up_together_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands: Medium Skin Tone", []string{"people_holding_hands_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands: Medium-Dark Skin Tone", []string{"people_holding_hands_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands: Dark Skin Tone", []string{"people_holding_hands_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands: Light Skin Tone", []string{"people_holding_hands_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands: Medium-Light Skin Tone", []string{"people_holding_hands_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f9b2", "person: bald: Medium Skin Tone", []string{"person_bald_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f9b2", "person: bald: Medium-Dark Skin Tone", []string{"person_bald_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f9b2", "person: bald: Dark Skin Tone", []string{"person_bald_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f9b2", "person: bald: Light Skin Tone", []string{"person_bald_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f9b2", "person: bald: Medium-Light Skin Tone", []string{"person_bald_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f9b1", "person: curly hair: Light Skin Tone", []string{"person_curly_hair_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f9b1", "person: curly hair: Medium-Light Skin Tone", []string{"person_curly_hair_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f9b1", "person: curly hair: Medium Skin Tone", []string{"person_curly_hair_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f9b1", "person: curly hair: Medium-Dark Skin Tone", []string{"person_curly_hair_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f9b1", "person: curly hair: Dark Skin Tone", []string{"person_curly_hair_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f9bd", "person in manual wheelchair: Light Skin Tone", []string{"person_in_manual_wheelchair_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f9bd", "person in manual wheelchair: Medium-Light Skin Tone", []string{"person_in_manual_wheelchair_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f9bd", "person in manual wheelchair: Medium Skin Tone", []string{"person_in_manual_wheelchair_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f9bd", "person in manual wheelchair: Medium-Dark Skin Tone", []string{"person_in_manual_wheelchair_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f9bd", "person in manual wheelchair: Dark Skin Tone", []string{"person_in_manual_wheelchair_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f9bc", "person in motorized wheelchair: Dark Skin Tone", []string{"person_in_motorized_wheelchair_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f9bc", "person in motorized wheelchair: Light Skin Tone", []string{"person_in_motorized_wheelchair_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f9bc", "person in motorized wheelchair: Medium-Light Skin Tone", []string{"person_in_motorized_wheelchair_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f9bc", "person in motorized wheelchair: Medium Skin Tone", []string{"person_in_motorized_wheelchair_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f9bc", "person in motorized wheelchair: Medium-Dark Skin Tone", []string{"person_in_motorized_wheelchair_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f935\U0001f3fb", "person in tuxedo: Light Skin Tone", []string{"person_in_tuxedo_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f935\U0001f3fc", "person in tuxedo: Medium-Light Skin Tone", []string{"person_in_tuxedo_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f935\U0001f3fd", "person in tuxedo: Medium Skin Tone", []string{"person_in_tuxedo_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f935\U0001f3fe", "person in tuxedo: Medium-Dark Skin Tone", []string{"person_in_tuxedo_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f935\U0001f3ff", "person in tuxedo: Dark Skin Tone", []string{"person_in_tuxedo_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f9b0", "person: red hair: Medium-Light Skin Tone", []string{"person_red_hair_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f9b0", "person: red hair: Medium Skin Tone", []string{"person_red_hair_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f9b0", "person: red hair: Medium-Dark Skin Tone", []string{"person_red_hair_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f9b0", "person: red hair: Dark Skin Tone", []string{"person_red_hair_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f9b0", "person: red hair: Light Skin Tone", []string{"person_red_hair_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f9b3", "person: white hair: Light Skin Tone", []string{"person_white_hair_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f9b3", "person: white hair: Medium-Light Skin Tone", []string{"person_white_hair_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f9b3", "person: white hair: Medium Skin Tone", []string{"person_white_hair_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f9b3", "person: white hair: Medium-Dark Skin Tone", []string{"person_white_hair_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f9b3", "person: white hair: Dark Skin Tone", []string{"person_white_hair_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f9af", "person with white cane: Medium-Light Skin Tone", []string{"person_with_probing_cane_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f9af", "person with white cane: Medium Skin Tone", []string{"person_with_probing_cane_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f9af", "person with white cane: Medium-Dark Skin Tone", []string{"person_with_probing_cane_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f9af", "person with white cane: Dark Skin Tone", []string{"person_with_probing_cane_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f9af", "person with white cane: Light Skin Tone", []string{"person_with_probing_cane_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fb", "person wearing turban: Light Skin Tone", []string{"person_with_turban_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fc", "person wearing turban: Medium-Light Skin Tone", []string{"person_with_turban_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fd", "person wearing turban: Medium Skin Tone", []string{"person_with_turban_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fe", "person wearing turban: Medium-Dark Skin Tone", []string{"person_with_turban_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3ff", "person wearing turban: Dark Skin Tone", []string{"person_with_turban_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f470\U0001f3fc", "person with veil: Medium-Light Skin Tone", []string{"person_with_veil_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f470\U0001f3fd", "person with veil: Medium Skin Tone", []string{"person_with_veil_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f470\U0001f3fe", "person with veil: Medium-Dark Skin Tone", []string{"person_with_veil_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f470\U0001f3ff", "person with veil: Dark Skin Tone", []string{"person_with_veil_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f470\U0001f3fb", "person with veil: Light Skin Tone", []string{"person_with_veil_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\u2708\ufe0f", "pilot: Light Skin Tone", []string{"pilot_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\u2708\ufe0f", "pilot: Medium-Light Skin Tone", []string{"pilot_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\u2708\ufe0f", "pilot: Medium Skin Tone", []string{"pilot_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\u2708\ufe0f", "pilot: Medium-Dark Skin Tone", []string{"pilot_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\u2708\ufe0f", "pilot: Dark Skin Tone", []string{"pilot_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f90f\U0001f3fd", "pinching hand: Medium Skin Tone", []string{"pinching_hand_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f90f\U0001f3fe", "pinching hand: Medium-Dark Skin Tone", []string{"pinching_hand_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f90f\U0001f3ff", "pinching hand: Dark Skin Tone", []string{"pinching_hand_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f90f\U0001f3fb", "pinching hand: Light Skin Tone", []string{"pinching_hand_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f90f\U0001f3fc", "pinching hand: Medium-Light Skin Tone", []string{"pinching_hand_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f447\U0001f3ff", "backhand index pointing down: Dark Skin Tone", []string{"point_down_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f447\U0001f3fb", "backhand index pointing down: Light Skin Tone", []string{"point_down_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f447\U0001f3fc", "backhand index pointing down: Medium-Light Skin Tone", []string{"point_down_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f447\U0001f3fd", "backhand index pointing down: Medium Skin Tone", []string{"point_down_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f447\U0001f3fe", "backhand index pointing down: Medium-Dark Skin Tone", []string{"point_down_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f448\U0001f3fb", "backhand index pointing left: Light Skin Tone", []string{"point_left_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f448\U0001f3fc", "backhand index pointing left: Medium-Light Skin Tone", []string{"point_left_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f448\U0001f3fd", "backhand index pointing left: Medium Skin Tone", []string{"point_left_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f448\U0001f3fe", "backhand index pointing left: Medium-Dark Skin Tone", []string{"point_left_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f448\U0001f3ff", "backhand index pointing left: Dark Skin Tone", []string{"point_left_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f449\U0001f3fb", "backhand index pointing right: Light Skin Tone", []string{"point_right_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f449\U0001f3fc", "backhand index pointing right: Medium-Light Skin Tone", []string{"point_right_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f449\U0001f3fd", "backhand index pointing right: Medium Skin Tone", []string{"point_right_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f449\U0001f3fe", "backhand index pointing right: Medium-Dark Skin Tone", []string{"point_right_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f449\U0001f3ff", "backhand index pointing right: Dark Skin Tone", []string{"point_right_Dark_Skin_Tone"}, "12.0", false},
+	{"\u261d\U0001f3fb\ufe0f", "index pointing up: Light Skin Tone", []string{"point_up_Light_Skin_Tone"}, "12.0", false},
+	{"\u261d\U0001f3fc\ufe0f", "index pointing up: Medium-Light Skin Tone", []string{"point_up_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\u261d\U0001f3fd\ufe0f", "index pointing up: Medium Skin Tone", []string{"point_up_Medium_Skin_Tone"}, "12.0", false},
+	{"\u261d\U0001f3fe\ufe0f", "index pointing up: Medium-Dark Skin Tone", []string{"point_up_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\u261d\U0001f3ff\ufe0f", "index pointing up: Dark Skin Tone", []string{"point_up_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f446\U0001f3fb", "backhand index pointing up: Light Skin Tone", []string{"point_up_2_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f446\U0001f3fc", "backhand index pointing up: Medium-Light Skin Tone", []string{"point_up_2_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f446\U0001f3fd", "backhand index pointing up: Medium Skin Tone", []string{"point_up_2_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f446\U0001f3fe", "backhand index pointing up: Medium-Dark Skin Tone", []string{"point_up_2_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f446\U0001f3ff", "backhand index pointing up: Dark Skin Tone", []string{"point_up_2_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fb", "police officer: Light Skin Tone", []string{"police_officer_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fc", "police officer: Medium-Light Skin Tone", []string{"police_officer_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fd", "police officer: Medium Skin Tone", []string{"police_officer_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fe", "police officer: Medium-Dark Skin Tone", []string{"police_officer_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3ff", "police officer: Dark Skin Tone", []string{"police_officer_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fb\u200d\u2642\ufe0f", "man police officer: Light Skin Tone", []string{"policeman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fc\u200d\u2642\ufe0f", "man police officer: Medium-Light Skin Tone", []string{"policeman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fd\u200d\u2642\ufe0f", "man police officer: Medium Skin Tone", []string{"policeman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fe\u200d\u2642\ufe0f", "man police officer: Medium-Dark Skin Tone", []string{"policeman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3ff\u200d\u2642\ufe0f", "man police officer: Dark Skin Tone", []string{"policeman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fb\u200d\u2640\ufe0f", "woman police officer: Light Skin Tone", []string{"policewoman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fc\u200d\u2640\ufe0f", "woman police officer: Medium-Light Skin Tone", []string{"policewoman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fd\u200d\u2640\ufe0f", "woman police officer: Medium Skin Tone", []string{"policewoman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3fe\u200d\u2640\ufe0f", "woman police officer: Medium-Dark Skin Tone", []string{"policewoman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f46e\U0001f3ff\u200d\u2640\ufe0f", "woman police officer: Dark Skin Tone", []string{"policewoman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fc", "person pouting: Medium-Light Skin Tone", []string{"pouting_face_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fd", "person pouting: Medium Skin Tone", []string{"pouting_face_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fe", "person pouting: Medium-Dark Skin Tone", []string{"pouting_face_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3ff", "person pouting: Dark Skin Tone", []string{"pouting_face_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fb", "person pouting: Light Skin Tone", []string{"pouting_face_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fb\u200d\u2642\ufe0f", "man pouting: Light Skin Tone", []string{"pouting_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fc\u200d\u2642\ufe0f", "man pouting: Medium-Light Skin Tone", []string{"pouting_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fd\u200d\u2642\ufe0f", "man pouting: Medium Skin Tone", []string{"pouting_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fe\u200d\u2642\ufe0f", "man pouting: Medium-Dark Skin Tone", []string{"pouting_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3ff\u200d\u2642\ufe0f", "man pouting: Dark Skin Tone", []string{"pouting_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fd\u200d\u2640\ufe0f", "woman pouting: Medium Skin Tone", []string{"pouting_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fe\u200d\u2640\ufe0f", "woman pouting: Medium-Dark Skin Tone", []string{"pouting_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3ff\u200d\u2640\ufe0f", "woman pouting: Dark Skin Tone", []string{"pouting_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fb\u200d\u2640\ufe0f", "woman pouting: Light Skin Tone", []string{"pouting_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64e\U0001f3fc\u200d\u2640\ufe0f", "woman pouting: Medium-Light Skin Tone", []string{"pouting_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64f\U0001f3fb", "folded hands: Light Skin Tone", []string{"pray_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64f\U0001f3fc", "folded hands: Medium-Light Skin Tone", []string{"pray_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64f\U0001f3fd", "folded hands: Medium Skin Tone", []string{"pray_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f64f\U0001f3fe", "folded hands: Medium-Dark Skin Tone", []string{"pray_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64f\U0001f3ff", "folded hands: Dark Skin Tone", []string{"pray_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f930\U0001f3fd", "pregnant woman: Medium Skin Tone", []string{"pregnant_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f930\U0001f3fe", "pregnant woman: Medium-Dark Skin Tone", []string{"pregnant_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f930\U0001f3ff", "pregnant woman: Dark Skin Tone", []string{"pregnant_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f930\U0001f3fb", "pregnant woman: Light Skin Tone", []string{"pregnant_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f930\U0001f3fc", "pregnant woman: Medium-Light Skin Tone", []string{"pregnant_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f934\U0001f3fe", "prince: Medium-Dark Skin Tone", []string{"prince_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f934\U0001f3ff", "prince: Dark Skin Tone", []string{"prince_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f934\U0001f3fb", "prince: Light Skin Tone", []string{"prince_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f934\U0001f3fc", "prince: Medium-Light Skin Tone", []string{"prince_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f934\U0001f3fd", "prince: Medium Skin Tone", []string{"prince_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f478\U0001f3fb", "princess: Light Skin Tone", []string{"princess_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f478\U0001f3fc", "princess: Medium-Light Skin Tone", []string{"princess_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f478\U0001f3fd", "princess: Medium Skin Tone", []string{"princess_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f478\U0001f3fe", "princess: Medium-Dark Skin Tone", []string{"princess_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f478\U0001f3ff", "princess: Dark Skin Tone", []string{"princess_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f91a\U0001f3fb", "raised back of hand: Light Skin Tone", []string{"raised_back_of_hand_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f91a\U0001f3fc", "raised back of hand: Medium-Light Skin Tone", []string{"raised_back_of_hand_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f91a\U0001f3fd", "raised back of hand: Medium Skin Tone", []string{"raised_back_of_hand_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f91a\U0001f3fe", "raised back of hand: Medium-Dark Skin Tone", []string{"raised_back_of_hand_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f91a\U0001f3ff", "raised back of hand: Dark Skin Tone", []string{"raised_back_of_hand_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f590\U0001f3fe\ufe0f", "hand with fingers splayed: Medium-Dark Skin Tone", []string{"raised_hand_with_fingers_splayed_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f590\U0001f3ff\ufe0f", "hand with fingers splayed: Dark Skin Tone", []string{"raised_hand_with_fingers_splayed_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f590\U0001f3fb\ufe0f", "hand with fingers splayed: Light Skin Tone", []string{"raised_hand_with_fingers_splayed_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f590\U0001f3fc\ufe0f", "hand with fingers splayed: Medium-Light Skin Tone", []string{"raised_hand_with_fingers_splayed_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f590\U0001f3fd\ufe0f", "hand with fingers splayed: Medium Skin Tone", []string{"raised_hand_with_fingers_splayed_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f64c\U0001f3fb", "raising hands: Light Skin Tone", []string{"raised_hands_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64c\U0001f3fc", "raising hands: Medium-Light Skin Tone", []string{"raised_hands_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64c\U0001f3fd", "raising hands: Medium Skin Tone", []string{"raised_hands_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f64c\U0001f3fe", "raising hands: Medium-Dark Skin Tone", []string{"raised_hands_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64c\U0001f3ff", "raising hands: Dark Skin Tone", []string{"raised_hands_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fc", "person raising hand: Medium-Light Skin Tone", []string{"raising_hand_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fd", "person raising hand: Medium Skin Tone", []string{"raising_hand_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fe", "person raising hand: Medium-Dark Skin Tone", []string{"raising_hand_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3ff", "person raising hand: Dark Skin Tone", []string{"raising_hand_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fb", "person raising hand: Light Skin Tone", []string{"raising_hand_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3ff\u200d\u2642\ufe0f", "man raising hand: Dark Skin Tone", []string{"raising_hand_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fb\u200d\u2642\ufe0f", "man raising hand: Light Skin Tone", []string{"raising_hand_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fc\u200d\u2642\ufe0f", "man raising hand: Medium-Light Skin Tone", []string{"raising_hand_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fd\u200d\u2642\ufe0f", "man raising hand: Medium Skin Tone", []string{"raising_hand_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fe\u200d\u2642\ufe0f", "man raising hand: Medium-Dark Skin Tone", []string{"raising_hand_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fe\u200d\u2640\ufe0f", "woman raising hand: Medium-Dark Skin Tone", []string{"raising_hand_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3ff\u200d\u2640\ufe0f", "woman raising hand: Dark Skin Tone", []string{"raising_hand_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fb\u200d\u2640\ufe0f", "woman raising hand: Light Skin Tone", []string{"raising_hand_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fc\u200d\u2640\ufe0f", "woman raising hand: Medium-Light Skin Tone", []string{"raising_hand_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f64b\U0001f3fd\u200d\u2640\ufe0f", "woman raising hand: Medium Skin Tone", []string{"raising_hand_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f9b0", "man: red hair: Medium-Light Skin Tone", []string{"red_haired_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f9b0", "man: red hair: Medium Skin Tone", []string{"red_haired_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f9b0", "man: red hair: Medium-Dark Skin Tone", []string{"red_haired_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f9b0", "man: red hair: Dark Skin Tone", []string{"red_haired_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f9b0", "man: red hair: Light Skin Tone", []string{"red_haired_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f9b0", "woman: red hair: Light Skin Tone", []string{"red_haired_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f9b0", "woman: red hair: Medium-Light Skin Tone", []string{"red_haired_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f9b0", "woman: red hair: Medium Skin Tone", []string{"red_haired_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f9b0", "woman: red hair: Medium-Dark Skin Tone", []string{"red_haired_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f9b0", "woman: red hair: Dark Skin Tone", []string{"red_haired_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fb", "person rowing boat: Light Skin Tone", []string{"rowboat_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fc", "person rowing boat: Medium-Light Skin Tone", []string{"rowboat_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fd", "person rowing boat: Medium Skin Tone", []string{"rowboat_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fe", "person rowing boat: Medium-Dark Skin Tone", []string{"rowboat_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3ff", "person rowing boat: Dark Skin Tone", []string{"rowboat_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fb\u200d\u2642\ufe0f", "man rowing boat: Light Skin Tone", []string{"rowing_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fc\u200d\u2642\ufe0f", "man rowing boat: Medium-Light Skin Tone", []string{"rowing_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fd\u200d\u2642\ufe0f", "man rowing boat: Medium Skin Tone", []string{"rowing_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fe\u200d\u2642\ufe0f", "man rowing boat: Medium-Dark Skin Tone", []string{"rowing_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3ff\u200d\u2642\ufe0f", "man rowing boat: Dark Skin Tone", []string{"rowing_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fb\u200d\u2640\ufe0f", "woman rowing boat: Light Skin Tone", []string{"rowing_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fc\u200d\u2640\ufe0f", "woman rowing boat: Medium-Light Skin Tone", []string{"rowing_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fd\u200d\u2640\ufe0f", "woman rowing boat: Medium Skin Tone", []string{"rowing_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3fe\u200d\u2640\ufe0f", "woman rowing boat: Medium-Dark Skin Tone", []string{"rowing_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6a3\U0001f3ff\u200d\u2640\ufe0f", "woman rowing boat: Dark Skin Tone", []string{"rowing_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fb", "person running: Light Skin Tone", []string{"runner_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fc", "person running: Medium-Light Skin Tone", []string{"runner_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fd", "person running: Medium Skin Tone", []string{"runner_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fe", "person running: Medium-Dark Skin Tone", []string{"runner_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3ff", "person running: Dark Skin Tone", []string{"runner_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fb\u200d\u2642\ufe0f", "man running: Light Skin Tone", []string{"running_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fc\u200d\u2642\ufe0f", "man running: Medium-Light Skin Tone", []string{"running_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fd\u200d\u2642\ufe0f", "man running: Medium Skin Tone", []string{"running_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fe\u200d\u2642\ufe0f", "man running: Medium-Dark Skin Tone", []string{"running_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3ff\u200d\u2642\ufe0f", "man running: Dark Skin Tone", []string{"running_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fb\u200d\u2640\ufe0f", "woman running: Light Skin Tone", []string{"running_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fc\u200d\u2640\ufe0f", "woman running: Medium-Light Skin Tone", []string{"running_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fd\u200d\u2640\ufe0f", "woman running: Medium Skin Tone", []string{"running_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3fe\u200d\u2640\ufe0f", "woman running: Medium-Dark Skin Tone", []string{"running_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c3\U0001f3ff\u200d\u2640\ufe0f", "woman running: Dark Skin Tone", []string{"running_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f385\U0001f3fd", "Santa Claus: Medium Skin Tone", []string{"santa_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f385\U0001f3fe", "Santa Claus: Medium-Dark Skin Tone", []string{"santa_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f385\U0001f3ff", "Santa Claus: Dark Skin Tone", []string{"santa_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f385\U0001f3fb", "Santa Claus: Light Skin Tone", []string{"santa_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f385\U0001f3fc", "Santa Claus: Medium-Light Skin Tone", []string{"santa_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fb\u200d\u2642\ufe0f", "man in steamy room: Light Skin Tone", []string{"sauna_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fc\u200d\u2642\ufe0f", "man in steamy room: Medium-Light Skin Tone", []string{"sauna_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fd\u200d\u2642\ufe0f", "man in steamy room: Medium Skin Tone", []string{"sauna_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fe\u200d\u2642\ufe0f", "man in steamy room: Medium-Dark Skin Tone", []string{"sauna_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3ff\u200d\u2642\ufe0f", "man in steamy room: Dark Skin Tone", []string{"sauna_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fb", "person in steamy room: Light Skin Tone", []string{"sauna_person_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fc", "person in steamy room: Medium-Light Skin Tone", []string{"sauna_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fd", "person in steamy room: Medium Skin Tone", []string{"sauna_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fe", "person in steamy room: Medium-Dark Skin Tone", []string{"sauna_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3ff", "person in steamy room: Dark Skin Tone", []string{"sauna_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fb\u200d\u2640\ufe0f", "woman in steamy room: Light Skin Tone", []string{"sauna_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fc\u200d\u2640\ufe0f", "woman in steamy room: Medium-Light Skin Tone", []string{"sauna_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fd\u200d\u2640\ufe0f", "woman in steamy room: Medium Skin Tone", []string{"sauna_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3fe\u200d\u2640\ufe0f", "woman in steamy room: Medium-Dark Skin Tone", []string{"sauna_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d6\U0001f3ff\u200d\u2640\ufe0f", "woman in steamy room: Dark Skin Tone", []string{"sauna_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f52c", "scientist: Medium-Light Skin Tone", []string{"scientist_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f52c", "scientist: Medium Skin Tone", []string{"scientist_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f52c", "scientist: Medium-Dark Skin Tone", []string{"scientist_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f52c", "scientist: Dark Skin Tone", []string{"scientist_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f52c", "scientist: Light Skin Tone", []string{"scientist_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f933\U0001f3fc", "selfie: Medium-Light Skin Tone", []string{"selfie_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f933\U0001f3fd", "selfie: Medium Skin Tone", []string{"selfie_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f933\U0001f3fe", "selfie: Medium-Dark Skin Tone", []string{"selfie_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f933\U0001f3ff", "selfie: Dark Skin Tone", []string{"selfie_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f933\U0001f3fb", "selfie: Light Skin Tone", []string{"selfie_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fe", "person shrugging: Medium-Dark Skin Tone", []string{"shrug_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3ff", "person shrugging: Dark Skin Tone", []string{"shrug_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fb", "person shrugging: Light Skin Tone", []string{"shrug_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fc", "person shrugging: Medium-Light Skin Tone", []string{"shrug_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fd", "person shrugging: Medium Skin Tone", []string{"shrug_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f3a4", "singer: Light Skin Tone", []string{"singer_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f3a4", "singer: Medium-Light Skin Tone", []string{"singer_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f3a4", "singer: Medium Skin Tone", []string{"singer_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f3a4", "singer: Medium-Dark Skin Tone", []string{"singer_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f3a4", "singer: Dark Skin Tone", []string{"singer_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6cc\U0001f3fc", "person in bed: Medium-Light Skin Tone", []string{"sleeping_bed_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6cc\U0001f3fd", "person in bed: Medium Skin Tone", []string{"sleeping_bed_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6cc\U0001f3fe", "person in bed: Medium-Dark Skin Tone", []string{"sleeping_bed_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6cc\U0001f3ff", "person in bed: Dark Skin Tone", []string{"sleeping_bed_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6cc\U0001f3fb", "person in bed: Light Skin Tone", []string{"sleeping_bed_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c2\U0001f3ff", "snowboarder: Dark Skin Tone", []string{"snowboarder_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c2\U0001f3fb", "snowboarder: Light Skin Tone", []string{"snowboarder_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c2\U0001f3fc", "snowboarder: Medium-Light Skin Tone", []string{"snowboarder_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c2\U0001f3fd", "snowboarder: Medium Skin Tone", []string{"snowboarder_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c2\U0001f3fe", "snowboarder: Medium-Dark Skin Tone", []string{"snowboarder_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fb\u200d\u2642\ufe0f", "man standing: Light Skin Tone", []string{"standing_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fc\u200d\u2642\ufe0f", "man standing: Medium-Light Skin Tone", []string{"standing_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fd\u200d\u2642\ufe0f", "man standing: Medium Skin Tone", []string{"standing_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fe\u200d\u2642\ufe0f", "man standing: Medium-Dark Skin Tone", []string{"standing_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3ff\u200d\u2642\ufe0f", "man standing: Dark Skin Tone", []string{"standing_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fd", "person standing: Medium Skin Tone", []string{"standing_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fe", "person standing: Medium-Dark Skin Tone", []string{"standing_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3ff", "person standing: Dark Skin Tone", []string{"standing_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fb", "person standing: Light Skin Tone", []string{"standing_person_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fc", "person standing: Medium-Light Skin Tone", []string{"standing_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fb\u200d\u2640\ufe0f", "woman standing: Light Skin Tone", []string{"standing_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fc\u200d\u2640\ufe0f", "woman standing: Medium-Light Skin Tone", []string{"standing_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fd\u200d\u2640\ufe0f", "woman standing: Medium Skin Tone", []string{"standing_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3fe\u200d\u2640\ufe0f", "woman standing: Medium-Dark Skin Tone", []string{"standing_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9cd\U0001f3ff\u200d\u2640\ufe0f", "woman standing: Dark Skin Tone", []string{"standing_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f393", "student: Medium Skin Tone", []string{"student_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f393", "student: Medium-Dark Skin Tone", []string{"student_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f393", "student: Dark Skin Tone", []string{"student_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f393", "student: Light Skin Tone", []string{"student_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f393", "student: Medium-Light Skin Tone", []string{"student_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fb", "superhero: Light Skin Tone", []string{"superhero_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fc", "superhero: Medium-Light Skin Tone", []string{"superhero_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fd", "superhero: Medium Skin Tone", []string{"superhero_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fe", "superhero: Medium-Dark Skin Tone", []string{"superhero_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3ff", "superhero: Dark Skin Tone", []string{"superhero_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fb\u200d\u2642\ufe0f", "man superhero: Light Skin Tone", []string{"superhero_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fc\u200d\u2642\ufe0f", "man superhero: Medium-Light Skin Tone", []string{"superhero_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fd\u200d\u2642\ufe0f", "man superhero: Medium Skin Tone", []string{"superhero_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fe\u200d\u2642\ufe0f", "man superhero: Medium-Dark Skin Tone", []string{"superhero_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3ff\u200d\u2642\ufe0f", "man superhero: Dark Skin Tone", []string{"superhero_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3ff\u200d\u2640\ufe0f", "woman superhero: Dark Skin Tone", []string{"superhero_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fb\u200d\u2640\ufe0f", "woman superhero: Light Skin Tone", []string{"superhero_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fc\u200d\u2640\ufe0f", "woman superhero: Medium-Light Skin Tone", []string{"superhero_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fd\u200d\u2640\ufe0f", "woman superhero: Medium Skin Tone", []string{"superhero_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b8\U0001f3fe\u200d\u2640\ufe0f", "woman superhero: Medium-Dark Skin Tone", []string{"superhero_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fe", "supervillain: Medium-Dark Skin Tone", []string{"supervillain_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3ff", "supervillain: Dark Skin Tone", []string{"supervillain_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fb", "supervillain: Light Skin Tone", []string{"supervillain_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fc", "supervillain: Medium-Light Skin Tone", []string{"supervillain_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fd", "supervillain: Medium Skin Tone", []string{"supervillain_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3ff\u200d\u2642\ufe0f", "man supervillain: Dark Skin Tone", []string{"supervillain_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fb\u200d\u2642\ufe0f", "man supervillain: Light Skin Tone", []string{"supervillain_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fc\u200d\u2642\ufe0f", "man supervillain: Medium-Light Skin Tone", []string{"supervillain_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fd\u200d\u2642\ufe0f", "man supervillain: Medium Skin Tone", []string{"supervillain_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fe\u200d\u2642\ufe0f", "man supervillain: Medium-Dark Skin Tone", []string{"supervillain_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fd\u200d\u2640\ufe0f", "woman supervillain: Medium Skin Tone", []string{"supervillain_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fe\u200d\u2640\ufe0f", "woman supervillain: Medium-Dark Skin Tone", []string{"supervillain_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3ff\u200d\u2640\ufe0f", "woman supervillain: Dark Skin Tone", []string{"supervillain_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fb\u200d\u2640\ufe0f", "woman supervillain: Light Skin Tone", []string{"supervillain_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9b9\U0001f3fc\u200d\u2640\ufe0f", "woman supervillain: Medium-Light Skin Tone", []string{"supervillain_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fc", "person surfing: Medium-Light Skin Tone", []string{"surfer_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fd", "person surfing: Medium Skin Tone", []string{"surfer_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fe", "person surfing: Medium-Dark Skin Tone", []string{"surfer_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3ff", "person surfing: Dark Skin Tone", []string{"surfer_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fb", "person surfing: Light Skin Tone", []string{"surfer_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fb\u200d\u2642\ufe0f", "man surfing: Light Skin Tone", []string{"surfing_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fc\u200d\u2642\ufe0f", "man surfing: Medium-Light Skin Tone", []string{"surfing_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fd\u200d\u2642\ufe0f", "man surfing: Medium Skin Tone", []string{"surfing_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fe\u200d\u2642\ufe0f", "man surfing: Medium-Dark Skin Tone", []string{"surfing_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3ff\u200d\u2642\ufe0f", "man surfing: Dark Skin Tone", []string{"surfing_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fb\u200d\u2640\ufe0f", "woman surfing: Light Skin Tone", []string{"surfing_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fc\u200d\u2640\ufe0f", "woman surfing: Medium-Light Skin Tone", []string{"surfing_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fd\u200d\u2640\ufe0f", "woman surfing: Medium Skin Tone", []string{"surfing_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3fe\u200d\u2640\ufe0f", "woman surfing: Medium-Dark Skin Tone", []string{"surfing_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3c4\U0001f3ff\u200d\u2640\ufe0f", "woman surfing: Dark Skin Tone", []string{"surfing_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3ff", "person swimming: Dark Skin Tone", []string{"swimmer_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fb", "person swimming: Light Skin Tone", []string{"swimmer_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fc", "person swimming: Medium-Light Skin Tone", []string{"swimmer_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fd", "person swimming: Medium Skin Tone", []string{"swimmer_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fe", "person swimming: Medium-Dark Skin Tone", []string{"swimmer_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fb\u200d\u2642\ufe0f", "man swimming: Light Skin Tone", []string{"swimming_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fc\u200d\u2642\ufe0f", "man swimming: Medium-Light Skin Tone", []string{"swimming_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fd\u200d\u2642\ufe0f", "man swimming: Medium Skin Tone", []string{"swimming_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fe\u200d\u2642\ufe0f", "man swimming: Medium-Dark Skin Tone", []string{"swimming_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3ff\u200d\u2642\ufe0f", "man swimming: Dark Skin Tone", []string{"swimming_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fc\u200d\u2640\ufe0f", "woman swimming: Medium-Light Skin Tone", []string{"swimming_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fd\u200d\u2640\ufe0f", "woman swimming: Medium Skin Tone", []string{"swimming_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fe\u200d\u2640\ufe0f", "woman swimming: Medium-Dark Skin Tone", []string{"swimming_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3ff\u200d\u2640\ufe0f", "woman swimming: Dark Skin Tone", []string{"swimming_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3ca\U0001f3fb\u200d\u2640\ufe0f", "woman swimming: Light Skin Tone", []string{"swimming_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f3eb", "teacher: Medium-Light Skin Tone", []string{"teacher_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f3eb", "teacher: Medium Skin Tone", []string{"teacher_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f3eb", "teacher: Medium-Dark Skin Tone", []string{"teacher_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f3eb", "teacher: Dark Skin Tone", []string{"teacher_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f3eb", "teacher: Light Skin Tone", []string{"teacher_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fb\u200d\U0001f4bb", "technologist: Light Skin Tone", []string{"technologist_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fc\u200d\U0001f4bb", "technologist: Medium-Light Skin Tone", []string{"technologist_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fd\u200d\U0001f4bb", "technologist: Medium Skin Tone", []string{"technologist_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3fe\u200d\U0001f4bb", "technologist: Medium-Dark Skin Tone", []string{"technologist_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d1\U0001f3ff\u200d\U0001f4bb", "technologist: Dark Skin Tone", []string{"technologist_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3ff\u200d\u2642\ufe0f", "man tipping hand: Dark Skin Tone", []string{"tipping_hand_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fb\u200d\u2642\ufe0f", "man tipping hand: Light Skin Tone", []string{"tipping_hand_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fc\u200d\u2642\ufe0f", "man tipping hand: Medium-Light Skin Tone", []string{"tipping_hand_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fd\u200d\u2642\ufe0f", "man tipping hand: Medium Skin Tone", []string{"tipping_hand_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fe\u200d\u2642\ufe0f", "man tipping hand: Medium-Dark Skin Tone", []string{"tipping_hand_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fb", "person tipping hand: Light Skin Tone", []string{"tipping_hand_person_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fc", "person tipping hand: Medium-Light Skin Tone", []string{"tipping_hand_person_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fd", "person tipping hand: Medium Skin Tone", []string{"tipping_hand_person_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fe", "person tipping hand: Medium-Dark Skin Tone", []string{"tipping_hand_person_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3ff", "person tipping hand: Dark Skin Tone", []string{"tipping_hand_person_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fd\u200d\u2640\ufe0f", "woman tipping hand: Medium Skin Tone", []string{"tipping_hand_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fe\u200d\u2640\ufe0f", "woman tipping hand: Medium-Dark Skin Tone", []string{"tipping_hand_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3ff\u200d\u2640\ufe0f", "woman tipping hand: Dark Skin Tone", []string{"tipping_hand_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fb\u200d\u2640\ufe0f", "woman tipping hand: Light Skin Tone", []string{"tipping_hand_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f481\U0001f3fc\u200d\u2640\ufe0f", "woman tipping hand: Medium-Light Skin Tone", []string{"tipping_hand_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46c\U0001f3fb", "men holding hands: Light Skin Tone", []string{"two_men_holding_hands_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46c\U0001f3fc", "men holding hands: Medium-Light Skin Tone", []string{"two_men_holding_hands_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46c\U0001f3fd", "men holding hands: Medium Skin Tone", []string{"two_men_holding_hands_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f46c\U0001f3fe", "men holding hands: Medium-Dark Skin Tone", []string{"two_men_holding_hands_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f46c\U0001f3ff", "men holding hands: Dark Skin Tone", []string{"two_men_holding_hands_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f46d\U0001f3fb", "women holding hands: Light Skin Tone", []string{"two_women_holding_hands_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46d\U0001f3fc", "women holding hands: Medium-Light Skin Tone", []string{"two_women_holding_hands_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f46d\U0001f3fd", "women holding hands: Medium Skin Tone", []string{"two_women_holding_hands_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f46d\U0001f3fe", "women holding hands: Medium-Dark Skin Tone", []string{"two_women_holding_hands_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f46d\U0001f3ff", "women holding hands: Dark Skin Tone", []string{"two_women_holding_hands_Dark_Skin_Tone"}, "12.0", false},
+	{"\u270c\U0001f3fb\ufe0f", "victory hand: Light Skin Tone", []string{"v_Light_Skin_Tone"}, "12.0", false},
+	{"\u270c\U0001f3fc\ufe0f", "victory hand: Medium-Light Skin Tone", []string{"v_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\u270c\U0001f3fd\ufe0f", "victory hand: Medium Skin Tone", []string{"v_Medium_Skin_Tone"}, "12.0", false},
+	{"\u270c\U0001f3fe\ufe0f", "victory hand: Medium-Dark Skin Tone", []string{"v_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\u270c\U0001f3ff\ufe0f", "victory hand: Dark Skin Tone", []string{"v_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fb", "vampire: Light Skin Tone", []string{"vampire_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fc", "vampire: Medium-Light Skin Tone", []string{"vampire_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fd", "vampire: Medium Skin Tone", []string{"vampire_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fe", "vampire: Medium-Dark Skin Tone", []string{"vampire_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3ff", "vampire: Dark Skin Tone", []string{"vampire_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fb\u200d\u2642\ufe0f", "man vampire: Light Skin Tone", []string{"vampire_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fc\u200d\u2642\ufe0f", "man vampire: Medium-Light Skin Tone", []string{"vampire_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fd\u200d\u2642\ufe0f", "man vampire: Medium Skin Tone", []string{"vampire_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fe\u200d\u2642\ufe0f", "man vampire: Medium-Dark Skin Tone", []string{"vampire_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3ff\u200d\u2642\ufe0f", "man vampire: Dark Skin Tone", []string{"vampire_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fd\u200d\u2640\ufe0f", "woman vampire: Medium Skin Tone", []string{"vampire_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fe\u200d\u2640\ufe0f", "woman vampire: Medium-Dark Skin Tone", []string{"vampire_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3ff\u200d\u2640\ufe0f", "woman vampire: Dark Skin Tone", []string{"vampire_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fb\u200d\u2640\ufe0f", "woman vampire: Light Skin Tone", []string{"vampire_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9db\U0001f3fc\u200d\u2640\ufe0f", "woman vampire: Medium-Light Skin Tone", []string{"vampire_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f596\U0001f3fb", "vulcan salute: Light Skin Tone", []string{"vulcan_salute_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f596\U0001f3fc", "vulcan salute: Medium-Light Skin Tone", []string{"vulcan_salute_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f596\U0001f3fd", "vulcan salute: Medium Skin Tone", []string{"vulcan_salute_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f596\U0001f3fe", "vulcan salute: Medium-Dark Skin Tone", []string{"vulcan_salute_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f596\U0001f3ff", "vulcan salute: Dark Skin Tone", []string{"vulcan_salute_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fb", "person walking: Light Skin Tone", []string{"walking_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fc", "person walking: Medium-Light Skin Tone", []string{"walking_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fd", "person walking: Medium Skin Tone", []string{"walking_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fe", "person walking: Medium-Dark Skin Tone", []string{"walking_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3ff", "person walking: Dark Skin Tone", []string{"walking_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fb\u200d\u2642\ufe0f", "man walking: Light Skin Tone", []string{"walking_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fc\u200d\u2642\ufe0f", "man walking: Medium-Light Skin Tone", []string{"walking_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fd\u200d\u2642\ufe0f", "man walking: Medium Skin Tone", []string{"walking_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fe\u200d\u2642\ufe0f", "man walking: Medium-Dark Skin Tone", []string{"walking_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3ff\u200d\u2642\ufe0f", "man walking: Dark Skin Tone", []string{"walking_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fb\u200d\u2640\ufe0f", "woman walking: Light Skin Tone", []string{"walking_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fc\u200d\u2640\ufe0f", "woman walking: Medium-Light Skin Tone", []string{"walking_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fd\u200d\u2640\ufe0f", "woman walking: Medium Skin Tone", []string{"walking_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3fe\u200d\u2640\ufe0f", "woman walking: Medium-Dark Skin Tone", []string{"walking_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f6b6\U0001f3ff\u200d\u2640\ufe0f", "woman walking: Dark Skin Tone", []string{"walking_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fd", "person playing water polo: Medium Skin Tone", []string{"water_polo_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fe", "person playing water polo: Medium-Dark Skin Tone", []string{"water_polo_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3ff", "person playing water polo: Dark Skin Tone", []string{"water_polo_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fb", "person playing water polo: Light Skin Tone", []string{"water_polo_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fc", "person playing water polo: Medium-Light Skin Tone", []string{"water_polo_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44b\U0001f3fc", "waving hand: Medium-Light Skin Tone", []string{"wave_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f44b\U0001f3fd", "waving hand: Medium Skin Tone", []string{"wave_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f44b\U0001f3fe", "waving hand: Medium-Dark Skin Tone", []string{"wave_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f44b\U0001f3ff", "waving hand: Dark Skin Tone", []string{"wave_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f44b\U0001f3fb", "waving hand: Light Skin Tone", []string{"wave_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fb\ufe0f", "person lifting weights: Light Skin Tone", []string{"weight_lifting_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fc\ufe0f", "person lifting weights: Medium-Light Skin Tone", []string{"weight_lifting_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fd\ufe0f", "person lifting weights: Medium Skin Tone", []string{"weight_lifting_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fe\ufe0f", "person lifting weights: Medium-Dark Skin Tone", []string{"weight_lifting_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3ff\ufe0f", "person lifting weights: Dark Skin Tone", []string{"weight_lifting_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fb\ufe0f\u200d\u2642\ufe0f", "man lifting weights: Light Skin Tone", []string{"weight_lifting_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fc\ufe0f\u200d\u2642\ufe0f", "man lifting weights: Medium-Light Skin Tone", []string{"weight_lifting_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fd\ufe0f\u200d\u2642\ufe0f", "man lifting weights: Medium Skin Tone", []string{"weight_lifting_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fe\ufe0f\u200d\u2642\ufe0f", "man lifting weights: Medium-Dark Skin Tone", []string{"weight_lifting_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3ff\ufe0f\u200d\u2642\ufe0f", "man lifting weights: Dark Skin Tone", []string{"weight_lifting_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3ff\ufe0f\u200d\u2640\ufe0f", "woman lifting weights: Dark Skin Tone", []string{"weight_lifting_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fb\ufe0f\u200d\u2640\ufe0f", "woman lifting weights: Light Skin Tone", []string{"weight_lifting_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fc\ufe0f\u200d\u2640\ufe0f", "woman lifting weights: Medium-Light Skin Tone", []string{"weight_lifting_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fd\ufe0f\u200d\u2640\ufe0f", "woman lifting weights: Medium Skin Tone", []string{"weight_lifting_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f3cb\U0001f3fe\ufe0f\u200d\u2640\ufe0f", "woman lifting weights: Medium-Dark Skin Tone", []string{"weight_lifting_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fb\u200d\U0001f9b3", "man: white hair: Light Skin Tone", []string{"white_haired_man_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fc\u200d\U0001f9b3", "man: white hair: Medium-Light Skin Tone", []string{"white_haired_man_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fd\u200d\U0001f9b3", "man: white hair: Medium Skin Tone", []string{"white_haired_man_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3fe\u200d\U0001f9b3", "man: white hair: Medium-Dark Skin Tone", []string{"white_haired_man_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f468\U0001f3ff\u200d\U0001f9b3", "man: white hair: Dark Skin Tone", []string{"white_haired_man_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f9b3", "woman: white hair: Medium-Dark Skin Tone", []string{"white_haired_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f9b3", "woman: white hair: Dark Skin Tone", []string{"white_haired_woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f9b3", "woman: white hair: Light Skin Tone", []string{"white_haired_woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f9b3", "woman: white hair: Medium-Light Skin Tone", []string{"white_haired_woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f9b3", "woman: white hair: Medium Skin Tone", []string{"white_haired_woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb", "woman: Light Skin Tone", []string{"woman_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc", "woman: Medium-Light Skin Tone", []string{"woman_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd", "woman: Medium Skin Tone", []string{"woman_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe", "woman: Medium-Dark Skin Tone", []string{"woman_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff", "woman: Dark Skin Tone", []string{"woman_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f3a8", "woman artist: Light Skin Tone", []string{"woman_artist_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f3a8", "woman artist: Medium-Light Skin Tone", []string{"woman_artist_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f3a8", "woman artist: Medium Skin Tone", []string{"woman_artist_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f3a8", "woman artist: Medium-Dark Skin Tone", []string{"woman_artist_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f3a8", "woman artist: Dark Skin Tone", []string{"woman_artist_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f680", "woman astronaut: Light Skin Tone", []string{"woman_astronaut_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f680", "woman astronaut: Medium-Light Skin Tone", []string{"woman_astronaut_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f680", "woman astronaut: Medium Skin Tone", []string{"woman_astronaut_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f680", "woman astronaut: Medium-Dark Skin Tone", []string{"woman_astronaut_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f680", "woman astronaut: Dark Skin Tone", []string{"woman_astronaut_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fb\u200d\u2640\ufe0f", "woman cartwheeling: Light Skin Tone", []string{"woman_cartwheeling_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fc\u200d\u2640\ufe0f", "woman cartwheeling: Medium-Light Skin Tone", []string{"woman_cartwheeling_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fd\u200d\u2640\ufe0f", "woman cartwheeling: Medium Skin Tone", []string{"woman_cartwheeling_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3fe\u200d\u2640\ufe0f", "woman cartwheeling: Medium-Dark Skin Tone", []string{"woman_cartwheeling_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f938\U0001f3ff\u200d\u2640\ufe0f", "woman cartwheeling: Dark Skin Tone", []string{"woman_cartwheeling_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f373", "woman cook: Medium-Light Skin Tone", []string{"woman_cook_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f373", "woman cook: Medium Skin Tone", []string{"woman_cook_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f373", "woman cook: Medium-Dark Skin Tone", []string{"woman_cook_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f373", "woman cook: Dark Skin Tone", []string{"woman_cook_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f373", "woman cook: Light Skin Tone", []string{"woman_cook_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f483\U0001f3fd", "woman dancing: Medium Skin Tone", []string{"woman_dancing_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f483\U0001f3fe", "woman dancing: Medium-Dark Skin Tone", []string{"woman_dancing_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f483\U0001f3ff", "woman dancing: Dark Skin Tone", []string{"woman_dancing_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f483\U0001f3fb", "woman dancing: Light Skin Tone", []string{"woman_dancing_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f483\U0001f3fc", "woman dancing: Medium-Light Skin Tone", []string{"woman_dancing_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fb\u200d\u2640\ufe0f", "woman facepalming: Light Skin Tone", []string{"woman_facepalming_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fc\u200d\u2640\ufe0f", "woman facepalming: Medium-Light Skin Tone", []string{"woman_facepalming_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fd\u200d\u2640\ufe0f", "woman facepalming: Medium Skin Tone", []string{"woman_facepalming_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3fe\u200d\u2640\ufe0f", "woman facepalming: Medium-Dark Skin Tone", []string{"woman_facepalming_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f926\U0001f3ff\u200d\u2640\ufe0f", "woman facepalming: Dark Skin Tone", []string{"woman_facepalming_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f3ed", "woman factory worker: Light Skin Tone", []string{"woman_factory_worker_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f3ed", "woman factory worker: Medium-Light Skin Tone", []string{"woman_factory_worker_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f3ed", "woman factory worker: Medium Skin Tone", []string{"woman_factory_worker_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f3ed", "woman factory worker: Medium-Dark Skin Tone", []string{"woman_factory_worker_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f3ed", "woman factory worker: Dark Skin Tone", []string{"woman_factory_worker_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f33e", "woman farmer: Light Skin Tone", []string{"woman_farmer_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f33e", "woman farmer: Medium-Light Skin Tone", []string{"woman_farmer_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f33e", "woman farmer: Medium Skin Tone", []string{"woman_farmer_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f33e", "woman farmer: Medium-Dark Skin Tone", []string{"woman_farmer_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f33e", "woman farmer: Dark Skin Tone", []string{"woman_farmer_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f692", "woman firefighter: Medium-Light Skin Tone", []string{"woman_firefighter_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f692", "woman firefighter: Medium Skin Tone", []string{"woman_firefighter_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f692", "woman firefighter: Medium-Dark Skin Tone", []string{"woman_firefighter_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f692", "woman firefighter: Dark Skin Tone", []string{"woman_firefighter_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f692", "woman firefighter: Light Skin Tone", []string{"woman_firefighter_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\u2695\ufe0f", "woman health worker: Light Skin Tone", []string{"woman_health_worker_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\u2695\ufe0f", "woman health worker: Medium-Light Skin Tone", []string{"woman_health_worker_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\u2695\ufe0f", "woman health worker: Medium Skin Tone", []string{"woman_health_worker_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\u2695\ufe0f", "woman health worker: Medium-Dark Skin Tone", []string{"woman_health_worker_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\u2695\ufe0f", "woman health worker: Dark Skin Tone", []string{"woman_health_worker_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f9bd", "woman in manual wheelchair: Light Skin Tone", []string{"woman_in_manual_wheelchair_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f9bd", "woman in manual wheelchair: Medium-Light Skin Tone", []string{"woman_in_manual_wheelchair_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f9bd", "woman in manual wheelchair: Medium Skin Tone", []string{"woman_in_manual_wheelchair_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f9bd", "woman in manual wheelchair: Medium-Dark Skin Tone", []string{"woman_in_manual_wheelchair_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f9bd", "woman in manual wheelchair: Dark Skin Tone", []string{"woman_in_manual_wheelchair_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f9bc", "woman in motorized wheelchair: Medium-Dark Skin Tone", []string{"woman_in_motorized_wheelchair_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f9bc", "woman in motorized wheelchair: Dark Skin Tone", []string{"woman_in_motorized_wheelchair_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f9bc", "woman in motorized wheelchair: Light Skin Tone", []string{"woman_in_motorized_wheelchair_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f9bc", "woman in motorized wheelchair: Medium-Light Skin Tone", []string{"woman_in_motorized_wheelchair_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f9bc", "woman in motorized wheelchair: Medium Skin Tone", []string{"woman_in_motorized_wheelchair_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\u2696\ufe0f", "woman judge: Light Skin Tone", []string{"woman_judge_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\u2696\ufe0f", "woman judge: Medium-Light Skin Tone", []string{"woman_judge_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\u2696\ufe0f", "woman judge: Medium Skin Tone", []string{"woman_judge_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\u2696\ufe0f", "woman judge: Medium-Dark Skin Tone", []string{"woman_judge_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\u2696\ufe0f", "woman judge: Dark Skin Tone", []string{"woman_judge_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fb\u200d\u2640\ufe0f", "woman juggling: Light Skin Tone", []string{"woman_juggling_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fc\u200d\u2640\ufe0f", "woman juggling: Medium-Light Skin Tone", []string{"woman_juggling_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fd\u200d\u2640\ufe0f", "woman juggling: Medium Skin Tone", []string{"woman_juggling_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3fe\u200d\u2640\ufe0f", "woman juggling: Medium-Dark Skin Tone", []string{"woman_juggling_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f939\U0001f3ff\u200d\u2640\ufe0f", "woman juggling: Dark Skin Tone", []string{"woman_juggling_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f527", "woman mechanic: Light Skin Tone", []string{"woman_mechanic_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f527", "woman mechanic: Medium-Light Skin Tone", []string{"woman_mechanic_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f527", "woman mechanic: Medium Skin Tone", []string{"woman_mechanic_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f527", "woman mechanic: Medium-Dark Skin Tone", []string{"woman_mechanic_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f527", "woman mechanic: Dark Skin Tone", []string{"woman_mechanic_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f4bc", "woman office worker: Light Skin Tone", []string{"woman_office_worker_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f4bc", "woman office worker: Medium-Light Skin Tone", []string{"woman_office_worker_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f4bc", "woman office worker: Medium Skin Tone", []string{"woman_office_worker_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f4bc", "woman office worker: Medium-Dark Skin Tone", []string{"woman_office_worker_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f4bc", "woman office worker: Dark Skin Tone", []string{"woman_office_worker_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\u2708\ufe0f", "woman pilot: Dark Skin Tone", []string{"woman_pilot_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\u2708\ufe0f", "woman pilot: Light Skin Tone", []string{"woman_pilot_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\u2708\ufe0f", "woman pilot: Medium-Light Skin Tone", []string{"woman_pilot_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\u2708\ufe0f", "woman pilot: Medium Skin Tone", []string{"woman_pilot_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\u2708\ufe0f", "woman pilot: Medium-Dark Skin Tone", []string{"woman_pilot_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fb\u200d\u2640\ufe0f", "woman playing handball: Light Skin Tone", []string{"woman_playing_handball_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fc\u200d\u2640\ufe0f", "woman playing handball: Medium-Light Skin Tone", []string{"woman_playing_handball_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fd\u200d\u2640\ufe0f", "woman playing handball: Medium Skin Tone", []string{"woman_playing_handball_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3fe\u200d\u2640\ufe0f", "woman playing handball: Medium-Dark Skin Tone", []string{"woman_playing_handball_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93e\U0001f3ff\u200d\u2640\ufe0f", "woman playing handball: Dark Skin Tone", []string{"woman_playing_handball_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fc\u200d\u2640\ufe0f", "woman playing water polo: Medium-Light Skin Tone", []string{"woman_playing_water_polo_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fd\u200d\u2640\ufe0f", "woman playing water polo: Medium Skin Tone", []string{"woman_playing_water_polo_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fe\u200d\u2640\ufe0f", "woman playing water polo: Medium-Dark Skin Tone", []string{"woman_playing_water_polo_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3ff\u200d\u2640\ufe0f", "woman playing water polo: Dark Skin Tone", []string{"woman_playing_water_polo_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f93d\U0001f3fb\u200d\u2640\ufe0f", "woman playing water polo: Light Skin Tone", []string{"woman_playing_water_polo_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f52c", "woman scientist: Light Skin Tone", []string{"woman_scientist_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f52c", "woman scientist: Medium-Light Skin Tone", []string{"woman_scientist_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f52c", "woman scientist: Medium Skin Tone", []string{"woman_scientist_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f52c", "woman scientist: Medium-Dark Skin Tone", []string{"woman_scientist_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f52c", "woman scientist: Dark Skin Tone", []string{"woman_scientist_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fb\u200d\u2640\ufe0f", "woman shrugging: Light Skin Tone", []string{"woman_shrugging_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fc\u200d\u2640\ufe0f", "woman shrugging: Medium-Light Skin Tone", []string{"woman_shrugging_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fd\u200d\u2640\ufe0f", "woman shrugging: Medium Skin Tone", []string{"woman_shrugging_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3fe\u200d\u2640\ufe0f", "woman shrugging: Medium-Dark Skin Tone", []string{"woman_shrugging_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f937\U0001f3ff\u200d\u2640\ufe0f", "woman shrugging: Dark Skin Tone", []string{"woman_shrugging_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f3a4", "woman singer: Medium-Light Skin Tone", []string{"woman_singer_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f3a4", "woman singer: Medium Skin Tone", []string{"woman_singer_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f3a4", "woman singer: Medium-Dark Skin Tone", []string{"woman_singer_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f3a4", "woman singer: Dark Skin Tone", []string{"woman_singer_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f3a4", "woman singer: Light Skin Tone", []string{"woman_singer_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f393", "woman student: Medium-Light Skin Tone", []string{"woman_student_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f393", "woman student: Medium Skin Tone", []string{"woman_student_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f393", "woman student: Medium-Dark Skin Tone", []string{"woman_student_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f393", "woman student: Dark Skin Tone", []string{"woman_student_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f393", "woman student: Light Skin Tone", []string{"woman_student_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f3eb", "woman teacher: Dark Skin Tone", []string{"woman_teacher_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f3eb", "woman teacher: Light Skin Tone", []string{"woman_teacher_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f3eb", "woman teacher: Medium-Light Skin Tone", []string{"woman_teacher_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f3eb", "woman teacher: Medium Skin Tone", []string{"woman_teacher_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f3eb", "woman teacher: Medium-Dark Skin Tone", []string{"woman_teacher_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f4bb", "woman technologist: Light Skin Tone", []string{"woman_technologist_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f4bb", "woman technologist: Medium-Light Skin Tone", []string{"woman_technologist_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f4bb", "woman technologist: Medium Skin Tone", []string{"woman_technologist_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f4bb", "woman technologist: Medium-Dark Skin Tone", []string{"woman_technologist_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f4bb", "woman technologist: Dark Skin Tone", []string{"woman_technologist_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d5\U0001f3fc", "woman with headscarf: Medium-Light Skin Tone", []string{"woman_with_headscarf_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d5\U0001f3fd", "woman with headscarf: Medium Skin Tone", []string{"woman_with_headscarf_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d5\U0001f3fe", "woman with headscarf: Medium-Dark Skin Tone", []string{"woman_with_headscarf_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d5\U0001f3ff", "woman with headscarf: Dark Skin Tone", []string{"woman_with_headscarf_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f9d5\U0001f3fb", "woman with headscarf: Light Skin Tone", []string{"woman_with_headscarf_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fc\u200d\U0001f9af", "woman with white cane: Medium-Light Skin Tone", []string{"woman_with_probing_cane_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fd\u200d\U0001f9af", "woman with white cane: Medium Skin Tone", []string{"woman_with_probing_cane_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fe\u200d\U0001f9af", "woman with white cane: Medium-Dark Skin Tone", []string{"woman_with_probing_cane_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3ff\u200d\U0001f9af", "woman with white cane: Dark Skin Tone", []string{"woman_with_probing_cane_Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f469\U0001f3fb\u200d\U0001f9af", "woman with white cane: Light Skin Tone", []string{"woman_with_probing_cane_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fb\u200d\u2640\ufe0f", "woman wearing turban: Light Skin Tone", []string{"woman_with_turban_Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fc\u200d\u2640\ufe0f", "woman wearing turban: Medium-Light Skin Tone", []string{"woman_with_turban_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fd\u200d\u2640\ufe0f", "woman wearing turban: Medium Skin Tone", []string{"woman_with_turban_Medium_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3fe\u200d\u2640\ufe0f", "woman wearing turban: Medium-Dark Skin Tone", []string{"woman_with_turban_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\U0001f473\U0001f3ff\u200d\u2640\ufe0f", "woman wearing turban: Dark Skin Tone", []string{"woman_with_turban_Dark_Skin_Tone"}, "12.0", false},
+	{"\u270d\U0001f3fb\ufe0f", "writing hand: Light Skin Tone", []string{"writing_hand_Light_Skin_Tone"}, "12.0", false},
+	{"\u270d\U0001f3fc\ufe0f", "writing hand: Medium-Light Skin Tone", []string{"writing_hand_Medium-Light_Skin_Tone"}, "12.0", false},
+	{"\u270d\U0001f3fd\ufe0f", "writing hand: Medium Skin Tone", []string{"writing_hand_Medium_Skin_Tone"}, "12.0", false},
+	{"\u270d\U0001f3fe\ufe0f", "writing hand: Medium-Dark Skin Tone", []string{"writing_hand_Medium-Dark_Skin_Tone"}, "12.0", false},
+	{"\u270d\U0001f3ff\ufe0f", "writing hand: Dark Skin Tone", []string{"writing_hand_Dark_Skin_Tone"}, "12.0", false},
 }
diff --git a/modules/eventsource/manager_run.go b/modules/eventsource/manager_run.go
index 75d3ee5b01..ccfe2e0709 100644
--- a/modules/eventsource/manager_run.go
+++ b/modules/eventsource/manager_run.go
@@ -17,6 +17,9 @@ import (
 
 // Init starts this eventsource
 func (m *Manager) Init() {
+	if setting.UI.Notification.EventSourceUpdateTime <= 0 {
+		return
+	}
 	go graceful.GetManager().RunWithShutdownContext(m.Run)
 }
 
diff --git a/modules/git/blame.go b/modules/git/blame.go
index 5a9ae9a74f..c2129c9e1c 100644
--- a/modules/git/blame.go
+++ b/modules/git/blame.go
@@ -27,7 +27,7 @@ type BlameReader struct {
 	cmd     *exec.Cmd
 	pid     int64
 	output  io.ReadCloser
-	scanner *bufio.Scanner
+	reader  *bufio.Reader
 	lastSha *string
 	cancel  context.CancelFunc
 }
@@ -38,23 +38,30 @@ var shaLineRegex = regexp.MustCompile("^([a-z0-9]{40})")
 func (r *BlameReader) NextPart() (*BlamePart, error) {
 	var blamePart *BlamePart
 
-	scanner := r.scanner
+	reader := r.reader
 
 	if r.lastSha != nil {
 		blamePart = &BlamePart{*r.lastSha, make([]string, 0)}
 	}
 
-	for scanner.Scan() {
-		line := scanner.Text()
+	var line []byte
+	var isPrefix bool
+	var err error
+
+	for err != io.EOF {
+		line, isPrefix, err = reader.ReadLine()
+		if err != nil && err != io.EOF {
+			return blamePart, err
+		}
 
-		// Skip empty lines
 		if len(line) == 0 {
+			// isPrefix will be false
 			continue
 		}
 
-		lines := shaLineRegex.FindStringSubmatch(line)
+		lines := shaLineRegex.FindSubmatch(line)
 		if lines != nil {
-			sha1 := lines[1]
+			sha1 := string(lines[1])
 
 			if blamePart == nil {
 				blamePart = &BlamePart{sha1, make([]string, 0)}
@@ -62,12 +69,27 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
 
 			if blamePart.Sha != sha1 {
 				r.lastSha = &sha1
+				// need to munch to end of line...
+				for isPrefix {
+					_, isPrefix, err = reader.ReadLine()
+					if err != nil && err != io.EOF {
+						return blamePart, err
+					}
+				}
 				return blamePart, nil
 			}
 		} else if line[0] == '\t' {
 			code := line[1:]
 
-			blamePart.Lines = append(blamePart.Lines, code)
+			blamePart.Lines = append(blamePart.Lines, string(code))
+		}
+
+		// need to munch to end of line...
+		for isPrefix {
+			_, isPrefix, err = reader.ReadLine()
+			if err != nil && err != io.EOF {
+				return blamePart, err
+			}
 		}
 	}
 
@@ -79,7 +101,9 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
 // Close BlameReader - don't run NextPart after invoking that
 func (r *BlameReader) Close() error {
 	defer process.GetManager().Remove(r.pid)
-	defer r.cancel()
+	r.cancel()
+
+	_ = r.output.Close()
 
 	if err := r.cmd.Wait(); err != nil {
 		return fmt.Errorf("Wait: %v", err)
@@ -89,19 +113,19 @@ func (r *BlameReader) Close() error {
 }
 
 // CreateBlameReader creates reader for given repository, commit and file
-func CreateBlameReader(repoPath, commitID, file string) (*BlameReader, error) {
+func CreateBlameReader(ctx context.Context, repoPath, commitID, file string) (*BlameReader, error) {
 	gitRepo, err := OpenRepository(repoPath)
 	if err != nil {
 		return nil, err
 	}
 	gitRepo.Close()
 
-	return createBlameReader(repoPath, GitExecutable, "blame", commitID, "--porcelain", "--", file)
+	return createBlameReader(ctx, repoPath, GitExecutable, "blame", commitID, "--porcelain", "--", file)
 }
 
-func createBlameReader(dir string, command ...string) (*BlameReader, error) {
-	// FIXME: graceful: This should have a timeout
-	ctx, cancel := context.WithCancel(DefaultContext)
+func createBlameReader(ctx context.Context, dir string, command ...string) (*BlameReader, error) {
+	// Here we use the provided context - this should be tied to the request performing the blame so that it does not hang around.
+	ctx, cancel := context.WithCancel(ctx)
 	cmd := exec.CommandContext(ctx, command[0], command[1:]...)
 	cmd.Dir = dir
 	cmd.Stderr = os.Stderr
@@ -119,13 +143,13 @@ func createBlameReader(dir string, command ...string) (*BlameReader, error) {
 
 	pid := process.GetManager().Add(fmt.Sprintf("GetBlame [repo_path: %s]", dir), cancel)
 
-	scanner := bufio.NewScanner(stdout)
+	reader := bufio.NewReader(stdout)
 
 	return &BlameReader{
 		cmd,
 		pid,
 		stdout,
-		scanner,
+		reader,
 		nil,
 		cancel,
 	}, nil
diff --git a/modules/git/blame_test.go b/modules/git/blame_test.go
index 1752312d81..734d63ee14 100644
--- a/modules/git/blame_test.go
+++ b/modules/git/blame_test.go
@@ -5,6 +5,7 @@
 package git
 
 import (
+	"context"
 	"io/ioutil"
 	"testing"
 
@@ -93,8 +94,10 @@ func TestReadingBlameOutput(t *testing.T) {
 	if _, err = tempFile.WriteString(exampleBlame); err != nil {
 		panic(err)
 	}
+	ctx, cancel := context.WithCancel(context.Background())
+	defer cancel()
 
-	blameReader, err := createBlameReader("", "cat", tempFile.Name())
+	blameReader, err := createBlameReader(ctx, "", "cat", tempFile.Name())
 	if err != nil {
 		panic(err)
 	}
diff --git a/modules/git/commit.go b/modules/git/commit.go
index 5e492e27ea..5ba8c2c8af 100644
--- a/modules/git/commit.go
+++ b/modules/git/commit.go
@@ -271,11 +271,12 @@ func AllCommitsCount(repoPath string) (int64, error) {
 	return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
 }
 
-func commitsCount(repoPath, revision, relpath string) (int64, error) {
+func commitsCount(repoPath string, revision, relpath []string) (int64, error) {
 	cmd := NewCommand("rev-list", "--count")
-	cmd.AddArguments(revision)
+	cmd.AddArguments(revision...)
 	if len(relpath) > 0 {
-		cmd.AddArguments("--", relpath)
+		cmd.AddArguments("--")
+		cmd.AddArguments(relpath...)
 	}
 
 	stdout, err := cmd.RunInDir(repoPath)
@@ -288,7 +289,7 @@ func commitsCount(repoPath, revision, relpath string) (int64, error) {
 
 // CommitsCount returns number of total commits of until given revision.
 func CommitsCount(repoPath, revision string) (int64, error) {
-	return commitsCount(repoPath, revision, "")
+	return commitsCount(repoPath, []string{revision}, []string{})
 }
 
 // CommitsCount returns number of total commits of until current revision.
diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go
index c5f6d6cdd6..bab3d8852c 100644
--- a/modules/git/repo_commit.go
+++ b/modules/git/repo_commit.go
@@ -46,7 +46,7 @@ func (repo *Repository) GetBranchCommitID(name string) (string, error) {
 
 // GetTagCommitID returns last commit ID string of given tag.
 func (repo *Repository) GetTagCommitID(name string) (string, error) {
-	stdout, err := NewCommand("rev-list", "-n", "1", name).RunInDir(repo.Path)
+	stdout, err := NewCommand("rev-list", "-n", "1", TagPrefix+name).RunInDir(repo.Path)
 	if err != nil {
 		if strings.Contains(err.Error(), "unknown revision or path") {
 			return "", ErrNotExist{name, ""}
@@ -293,7 +293,7 @@ func (repo *Repository) FileChangedBetweenCommits(filename, id1, id2 string) (bo
 
 // FileCommitsCount return the number of files at a revison
 func (repo *Repository) FileCommitsCount(revision, file string) (int64, error) {
-	return commitsCount(repo.Path, revision, file)
+	return commitsCount(repo.Path, []string{revision}, []string{file})
 }
 
 // CommitsByFileAndRange return the commits according revison file and the page
@@ -319,6 +319,11 @@ func (repo *Repository) CommitsByFileAndRangeNoFollow(revision, file string, pag
 // FilesCountBetween return the number of files changed between two commits
 func (repo *Repository) FilesCountBetween(startCommitID, endCommitID string) (int, error) {
 	stdout, err := NewCommand("diff", "--name-only", startCommitID+"..."+endCommitID).RunInDir(repo.Path)
+	if err != nil && strings.Contains(err.Error(), "no merge base") {
+		// git >= 2.28 now returns an error if startCommitID and endCommitID have become unrelated.
+		// previously it would return the results of git diff --name-only startCommitID endCommitID so let's try that...
+		stdout, err = NewCommand("diff", "--name-only", startCommitID, endCommitID).RunInDir(repo.Path)
+	}
 	if err != nil {
 		return 0, err
 	}
@@ -333,6 +338,11 @@ func (repo *Repository) CommitsBetween(last *Commit, before *Commit) (*list.List
 		stdout, err = NewCommand("rev-list", last.ID.String()).RunInDirBytes(repo.Path)
 	} else {
 		stdout, err = NewCommand("rev-list", before.ID.String()+"..."+last.ID.String()).RunInDirBytes(repo.Path)
+		if err != nil && strings.Contains(err.Error(), "no merge base") {
+			// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
+			// previously it would return the results of git rev-list before last so let's try that...
+			stdout, err = NewCommand("rev-list", before.ID.String(), last.ID.String()).RunInDirBytes(repo.Path)
+		}
 	}
 	if err != nil {
 		return nil, err
@@ -348,6 +358,11 @@ func (repo *Repository) CommitsBetweenLimit(last *Commit, before *Commit, limit,
 		stdout, err = NewCommand("rev-list", "--max-count", strconv.Itoa(limit), "--skip", strconv.Itoa(skip), last.ID.String()).RunInDirBytes(repo.Path)
 	} else {
 		stdout, err = NewCommand("rev-list", "--max-count", strconv.Itoa(limit), "--skip", strconv.Itoa(skip), before.ID.String()+"..."+last.ID.String()).RunInDirBytes(repo.Path)
+		if err != nil && strings.Contains(err.Error(), "no merge base") {
+			// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
+			// previously it would return the results of git rev-list --max-count n before last so let's try that...
+			stdout, err = NewCommand("rev-list", "--max-count", strconv.Itoa(limit), "--skip", strconv.Itoa(skip), before.ID.String(), last.ID.String()).RunInDirBytes(repo.Path)
+		}
 	}
 	if err != nil {
 		return nil, err
@@ -373,7 +388,14 @@ func (repo *Repository) CommitsBetweenIDs(last, before string) (*list.List, erro
 
 // CommitsCountBetween return numbers of commits between two commits
 func (repo *Repository) CommitsCountBetween(start, end string) (int64, error) {
-	return commitsCount(repo.Path, start+"..."+end, "")
+	count, err := commitsCount(repo.Path, []string{start + "..." + end}, []string{})
+	if err != nil && strings.Contains(err.Error(), "no merge base") {
+		// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
+		// previously it would return the results of git rev-list before last so let's try that...
+		return commitsCount(repo.Path, []string{start, end}, []string{})
+	}
+
+	return count, err
 }
 
 // commitsBefore the limit is depth, not total number of returned commits.
diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go
index 5bc7f9ca5a..16ea068db2 100644
--- a/modules/git/repo_compare.go
+++ b/modules/git/repo_compare.go
@@ -6,6 +6,7 @@
 package git
 
 import (
+	"bytes"
 	"container/list"
 	"fmt"
 	"io"
@@ -66,7 +67,7 @@ func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string)
 	compareInfo := new(CompareInfo)
 	compareInfo.MergeBase, remoteBranch, err = repo.GetMergeBase(tmpRemote, baseBranch, headBranch)
 	if err == nil {
-		// We have a common base
+		// We have a common base - therefore we know that ... should work
 		logs, err := NewCommand("log", compareInfo.MergeBase+"..."+headBranch, prettyLogFormat).RunInDirBytes(repo.Path)
 		if err != nil {
 			return nil, err
@@ -85,6 +86,11 @@ func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string)
 
 	// Count number of changed files.
 	stdout, err := NewCommand("diff", "--name-only", remoteBranch+"..."+headBranch).RunInDir(repo.Path)
+	if err != nil && strings.Contains(err.Error(), "no merge base") {
+		// git >= 2.28 now returns an error if base and head have become unrelated.
+		// previously it would return the results of git diff --name-only base head so let's try that...
+		stdout, err = NewCommand("diff", "--name-only", remoteBranch, headBranch).RunInDir(repo.Path)
+	}
 	if err != nil {
 		return nil, err
 	}
@@ -108,12 +114,24 @@ func (repo *Repository) GetDiff(base, head string, w io.Writer) error {
 
 // GetPatch generates and returns format-patch data between given revisions.
 func (repo *Repository) GetPatch(base, head string, w io.Writer) error {
-	return NewCommand("format-patch", "--binary", "--stdout", base+"..."+head).
-		RunInDirPipeline(repo.Path, w, nil)
+	stderr := new(bytes.Buffer)
+	err := NewCommand("format-patch", "--binary", "--stdout", base+"..."+head).
+		RunInDirPipeline(repo.Path, w, stderr)
+	if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) {
+		return NewCommand("format-patch", "--binary", "--stdout", base, head).
+			RunInDirPipeline(repo.Path, w, nil)
+	}
+	return err
 }
 
 // GetDiffFromMergeBase generates and return patch data from merge base to head
 func (repo *Repository) GetDiffFromMergeBase(base, head string, w io.Writer) error {
-	return NewCommand("diff", "-p", "--binary", base+"..."+head).
-		RunInDirPipeline(repo.Path, w, nil)
+	stderr := new(bytes.Buffer)
+	err := NewCommand("diff", "-p", "--binary", base+"..."+head).
+		RunInDirPipeline(repo.Path, w, stderr)
+	if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) {
+		return NewCommand("diff", "-p", "--binary", base, head).
+			RunInDirPipeline(repo.Path, w, nil)
+	}
+	return err
 }
diff --git a/modules/git/repo_language_stats.go b/modules/git/repo_language_stats.go
index ba58bcc2da..06ff704497 100644
--- a/modules/git/repo_language_stats.go
+++ b/modules/git/repo_language_stats.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"io"
 	"io/ioutil"
-	"math"
 
 	"code.gitea.io/gitea/modules/analyze"
 
@@ -18,10 +17,25 @@ import (
 	"github.com/go-git/go-git/v5/plumbing/object"
 )
 
-const fileSizeLimit int64 = 16 * 1024 * 1024
+const fileSizeLimit int64 = 16 * 1024 // 16 KiB
+const bigFileSize int64 = 1024 * 1024 // 1 MiB
+
+// specialLanguages defines list of languages that are excluded from the calculation
+// unless they are the only language present in repository. Only languages which under
+// normal circumstances are not considered to be code should be listed here.
+var specialLanguages = []string{
+	"XML",
+	"JSON",
+	"TOML",
+	"YAML",
+	"INI",
+	"SVG",
+	"Text",
+	"Markdown",
+}
 
 // GetLanguageStats calculates language stats for git repository at specified commit
-func (repo *Repository) GetLanguageStats(commitID string) (map[string]float32, error) {
+func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, error) {
 	r, err := git.PlainOpen(repo.Path)
 	if err != nil {
 		return nil, err
@@ -43,24 +57,35 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]float32, e
 	}
 
 	sizes := make(map[string]int64)
-	var total int64
 	err = tree.Files().ForEach(func(f *object.File) error {
-		if enry.IsVendor(f.Name) || enry.IsDotFile(f.Name) ||
+		if f.Size == 0 || enry.IsVendor(f.Name) || enry.IsDotFile(f.Name) ||
 			enry.IsDocumentation(f.Name) || enry.IsConfiguration(f.Name) {
 			return nil
 		}
 
+		// If content can not be read or file is too big just do detection by filename
+		var content []byte
+		if f.Size <= bigFileSize {
+			content, _ = readFile(f, fileSizeLimit)
+		}
+		if enry.IsGenerated(f.Name, content) {
+			return nil
+		}
+
 		// TODO: Use .gitattributes file for linguist overrides
 
-		language := analyze.GetCodeLanguageWithCallback(f.Name, func() ([]byte, error) {
-			return readFile(f, fileSizeLimit)
-		})
+		language := analyze.GetCodeLanguage(f.Name, content)
 		if language == enry.OtherLanguage || language == "" {
 			return nil
 		}
 
+		// group languages, such as Pug -> HTML; SCSS -> CSS
+		group := enry.GetLanguageGroup(language)
+		if group != "" {
+			language = group
+		}
+
 		sizes[language] += f.Size
-		total += f.Size
 
 		return nil
 	})
@@ -68,21 +93,14 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]float32, e
 		return nil, err
 	}
 
-	stats := make(map[string]float32)
-	var otherPerc float32 = 100
-	for language, size := range sizes {
-		perc := float32(math.Round(float64(size)/float64(total)*1000) / 10)
-		if perc <= 0.1 {
-			continue
+	// filter special languages unless they are the only language
+	if len(sizes) > 1 {
+		for _, language := range specialLanguages {
+			delete(sizes, language)
 		}
-		otherPerc -= perc
-		stats[language] = perc
 	}
-	otherPerc = float32(math.Round(float64(otherPerc)*10) / 10)
-	if otherPerc > 0 {
-		stats["other"] = otherPerc
-	}
-	return stats, nil
+
+	return sizes, nil
 }
 
 func readFile(f *object.File, limit int64) ([]byte, error) {
diff --git a/modules/git/submodule.go b/modules/git/submodule.go
index 222a5e4f8c..bb094bda5d 100644
--- a/modules/git/submodule.go
+++ b/modules/git/submodule.go
@@ -97,13 +97,13 @@ func getRefURL(refURL, urlPrefix, repoFullName string) string {
 
 	for _, scheme := range supportedSchemes {
 		if ref.Scheme == scheme {
-			if urlPrefixHostname == refHostname {
-				return urlPrefix + path.Clean(path.Join("/", ref.Path))
-			} else if ref.Scheme == "http" || ref.Scheme == "https" {
+			if ref.Scheme == "http" || ref.Scheme == "https" {
 				if len(ref.User.Username()) > 0 {
 					return ref.Scheme + "://" + fmt.Sprintf("%v", ref.User) + "@" + ref.Host + ref.Path
 				}
 				return ref.Scheme + "://" + ref.Host + ref.Path
+			} else if urlPrefixHostname == refHostname {
+				return urlPrefix + path.Clean(path.Join("/", ref.Path))
 			} else {
 				return "http://" + refHostname + ref.Path
 			}
diff --git a/modules/git/submodule_test.go b/modules/git/submodule_test.go
index 458c547dcb..fcb0c6fd67 100644
--- a/modules/git/submodule_test.go
+++ b/modules/git/submodule_test.go
@@ -28,6 +28,7 @@ func TestGetRefURL(t *testing.T) {
 		{"git://git@try.gitea.io:9999/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "https://try.gitea.io/go-gitea/gitea"},
 		{"ssh://git@127.0.0.1:9999/go-gitea/gitea", "https://127.0.0.1:3000/", "go-gitea/sdk", "https://127.0.0.1:3000/go-gitea/gitea"},
 		{"https://gitea.com:3000/user1/repo1.git", "https://127.0.0.1:3000/", "user/repo2", "https://gitea.com:3000/user1/repo1"},
+		{"https://example.gitea.com/gitea/user1/repo1.git", "https://example.gitea.com/gitea/", "user/repo2", "https://example.gitea.com/gitea/user1/repo1"},
 		{"https://username:password@github.com/username/repository.git", "/", "username/repository2", "https://username:password@github.com/username/repository"},
 		{"somethingbad", "https://127.0.0.1:3000/go-gitea/gitea", "/", ""},
 		{"git@localhost:user/repo", "https://localhost/", "user2/repo1", "https://localhost/user/repo"},
diff --git a/modules/git/tree_blob.go b/modules/git/tree_blob.go
index 4c5a80cb36..f9fc6db497 100644
--- a/modules/git/tree_blob.go
+++ b/modules/git/tree_blob.go
@@ -9,6 +9,7 @@ import (
 	"path"
 	"strings"
 
+	"github.com/go-git/go-git/v5/plumbing"
 	"github.com/go-git/go-git/v5/plumbing/filemode"
 	"github.com/go-git/go-git/v5/plumbing/object"
 )
@@ -35,6 +36,11 @@ func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) {
 		if i == len(parts)-1 {
 			entries, err := tree.ListEntries()
 			if err != nil {
+				if err == plumbing.ErrObjectNotFound {
+					return nil, ErrNotExist{
+						RelPath: relpath,
+					}
+				}
 				return nil, err
 			}
 			for _, v := range entries {
@@ -45,6 +51,11 @@ func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) {
 		} else {
 			tree, err = tree.SubTree(name)
 			if err != nil {
+				if err == plumbing.ErrObjectNotFound {
+					return nil, ErrNotExist{
+						RelPath: relpath,
+					}
+				}
 				return nil, err
 			}
 		}
diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go
index 42f0854576..9edaef6bdd 100644
--- a/modules/indexer/issues/indexer.go
+++ b/modules/indexer/issues/indexer.go
@@ -171,7 +171,7 @@ func InitIssueIndexer(syncReindex bool) {
 			log.Debug("Created Bleve Indexer")
 		case "elasticsearch":
 			graceful.GetManager().RunWithShutdownFns(func(_, atTerminate func(context.Context, func())) {
-				issueIndexer, err := NewElasticSearchIndexer(setting.Indexer.IssueConnStr, "gitea_issues")
+				issueIndexer, err := NewElasticSearchIndexer(setting.Indexer.IssueConnStr, setting.Indexer.IssueIndexerName)
 				if err != nil {
 					log.Fatal("Unable to initialize Elastic Search Issue Indexer at connection: %s Error: %v", setting.Indexer.IssueConnStr, err)
 				}
diff --git a/modules/indexer/stats/indexer_test.go b/modules/indexer/stats/indexer_test.go
index 29d0f6dbe4..4bcbaa9423 100644
--- a/modules/indexer/stats/indexer_test.go
+++ b/modules/indexer/stats/indexer_test.go
@@ -34,9 +34,10 @@ func TestRepoStatsIndex(t *testing.T) {
 
 	repo, err := models.GetRepositoryByID(1)
 	assert.NoError(t, err)
+	status, err := repo.GetIndexerStatus(models.RepoIndexerTypeStats)
+	assert.NoError(t, err)
+	assert.Equal(t, "65f1bf27bc3bf70f64657658635e66094edbcb4d", status.CommitSha)
 	langs, err := repo.GetTopLanguageStats(5)
 	assert.NoError(t, err)
-	assert.Len(t, langs, 1)
-	assert.Equal(t, "other", langs[0].Language)
-	assert.Equal(t, float32(100), langs[0].Percentage)
+	assert.Empty(t, langs)
 }
diff --git a/modules/indexer/stats/queue.go b/modules/indexer/stats/queue.go
index 9c83f9b412..8309cfcd3b 100644
--- a/modules/indexer/stats/queue.go
+++ b/modules/indexer/stats/queue.go
@@ -21,7 +21,7 @@ func handle(data ...queue.Data) {
 	for _, datum := range data {
 		opts := datum.(int64)
 		if err := indexer.Index(opts); err != nil {
-			log.Error("stats queue idexer.Index(%d) failed: %v", opts, err)
+			log.Error("stats queue indexer.Index(%d) failed: %v", opts, err)
 		}
 	}
 }
@@ -39,5 +39,11 @@ func initStatsQueue() error {
 
 // UpdateRepoIndexer update a repository's entries in the indexer
 func UpdateRepoIndexer(repo *models.Repository) error {
-	return statsQueue.Push(repo.ID)
+	if err := statsQueue.Push(repo.ID); err != nil {
+		if err != queue.ErrAlreadyInQueue {
+			return err
+		}
+		log.Debug("Repo ID: %d already queued", repo.ID)
+	}
+	return nil
 }
diff --git a/modules/log/colors.go b/modules/log/colors.go
index 282d0c919e..d8e5776735 100644
--- a/modules/log/colors.go
+++ b/modules/log/colors.go
@@ -355,7 +355,7 @@ func NewColoredValueBytes(value interface{}, colorBytes *[]byte) *ColoredValue {
 // The Value will be colored with FgCyan
 // If a ColoredValue is provided it is not changed
 func NewColoredIDValue(value interface{}) *ColoredValue {
-	return NewColoredValueBytes(&value, &fgCyanBytes)
+	return NewColoredValueBytes(value, &fgCyanBytes)
 }
 
 // Format will format the provided value and protect against ANSI color spoofing within the value
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 8fbfee6a53..41248654d8 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -65,10 +65,6 @@ var (
 
 	// EmojiShortCodeRegex find emoji by alias like :smile:
 	EmojiShortCodeRegex = regexp.MustCompile(`\:[\w\+\-]+\:{1}`)
-
-	// find emoji literal: search all emoji hex range as many times as they appear as
-	// some emojis (skin color etc..) are just two or more chained together
-	emojiRegex = regexp.MustCompile(`[\x{1F000}-\x{1FFFF}|\x{2000}-\x{32ff}|\x{fe4e5}-\x{fe4ee}|\x{200D}|\x{FE0F}|\x{e0000}-\x{e007f}]+`)
 )
 
 // CSS class for action keywords (e.g. "closes: #1")
@@ -922,8 +918,7 @@ func emojiShortCodeProcessor(ctx *postProcessCtx, node *html.Node) {
 
 // emoji processor to match emoji and add emoji class
 func emojiProcessor(ctx *postProcessCtx, node *html.Node) {
-	m := emojiRegex.FindStringSubmatchIndex(node.Data)
-
+	m := emoji.FindEmojiSubmatchIndex(node.Data)
 	if m == nil {
 		return
 	}
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index 65d2d327d6..d535e4341b 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -263,6 +263,12 @@ func TestRender_emoji(t *testing.T) {
 	test(
 		"Some text with :smile: in the middle",
 		`

Some text with ๐Ÿ˜„ in the middle

`) + test( + "Some text with ๐Ÿ˜„๐Ÿ˜„ 2 emoji next to each other", + `

Some text with ๐Ÿ˜„๐Ÿ˜„ 2 emoji next to each other

`) + test( + "๐Ÿ˜Ž๐Ÿคช๐Ÿ”๐Ÿค‘โ“", + `

๐Ÿ˜Ž๐Ÿคช๐Ÿ”๐Ÿค‘โ“

`) // should match nothing test( diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go index bf02a22d5e..9447424644 100644 --- a/modules/markup/markdown/goldmark.go +++ b/modules/markup/markdown/goldmark.go @@ -151,6 +151,16 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa v.AppendChild(v, newChild) } } + case *ast.Text: + if v.SoftLineBreak() && !v.HardLineBreak() { + renderMetas := pc.Get(renderMetasKey).(map[string]string) + mode := renderMetas["mode"] + if mode != "document" { + v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInComments) + } else { + v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInDocuments) + } + } } return ast.WalkContinue, nil }) diff --git a/modules/markup/markdown/markdown.go b/modules/markup/markdown/markdown.go index e50301ffe4..515d684686 100644 --- a/modules/markup/markdown/markdown.go +++ b/modules/markup/markdown/markdown.go @@ -29,17 +29,19 @@ var once = sync.Once{} var urlPrefixKey = parser.NewContextKey() var isWikiKey = parser.NewContextKey() +var renderMetasKey = parser.NewContextKey() // NewGiteaParseContext creates a parser.Context with the gitea context set -func NewGiteaParseContext(urlPrefix string, isWiki bool) parser.Context { +func NewGiteaParseContext(urlPrefix string, metas map[string]string, isWiki bool) parser.Context { pc := parser.NewContext(parser.WithIDs(newPrefixedIDs())) pc.Set(urlPrefixKey, urlPrefix) pc.Set(isWikiKey, isWiki) + pc.Set(renderMetasKey, metas) return pc } -// RenderRaw renders Markdown to HTML without handling special links. -func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte { +// render renders Markdown to HTML without handling special links. +func render(body []byte, urlPrefix string, metas map[string]string, wikiMarkdown bool) []byte { once.Do(func() { converter = goldmark.New( goldmark.WithExtensions(extension.Table, @@ -75,12 +77,9 @@ func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte { ), ) - if setting.Markdown.EnableHardLineBreak { - converter.Renderer().AddOptions(html.WithHardWraps()) - } }) - pc := NewGiteaParseContext(urlPrefix, wikiMarkdown) + pc := NewGiteaParseContext(urlPrefix, metas, wikiMarkdown) var buf bytes.Buffer if err := converter.Convert(giteautil.NormalizeEOL(body), &buf, parser.WithContext(pc)); err != nil { log.Error("Unable to render: %v", err) @@ -112,7 +111,7 @@ func (Parser) Extensions() []string { // Render implements markup.Parser func (Parser) Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte { - return RenderRaw(rawBytes, urlPrefix, isWiki) + return render(rawBytes, urlPrefix, metas, isWiki) } // Render renders Markdown to HTML with all specific handling stuff. @@ -120,6 +119,11 @@ func Render(rawBytes []byte, urlPrefix string, metas map[string]string) []byte { return markup.Render("a.md", rawBytes, urlPrefix, metas) } +// RenderRaw renders Markdown to HTML without handling special links. +func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte { + return render(body, urlPrefix, map[string]string{}, wikiMarkdown) +} + // RenderString renders Markdown to HTML with special links and returns string type. func RenderString(raw, urlPrefix string, metas map[string]string) string { return markup.RenderString("a.md", raw, urlPrefix, metas) diff --git a/modules/migrations/base/repo.go b/modules/migrations/base/repo.go index 5cfb0de920..d2052da90d 100644 --- a/modules/migrations/base/repo.go +++ b/modules/migrations/base/repo.go @@ -7,13 +7,14 @@ package base // Repository defines a standard repository information type Repository struct { - Name string - Owner string - IsPrivate bool - IsMirror bool - Description string - AuthUsername string - AuthPassword string - CloneURL string - OriginalURL string + Name string + Owner string + IsPrivate bool + IsMirror bool + Description string + AuthUsername string + AuthPassword string + CloneURL string + OriginalURL string + DefaultBranch string } diff --git a/modules/migrations/error.go b/modules/migrations/error.go index a48484d156..b2e2315fc8 100644 --- a/modules/migrations/error.go +++ b/modules/migrations/error.go @@ -8,7 +8,7 @@ package migrations import ( "errors" - "github.com/google/go-github/v24/github" + "github.com/google/go-github/v32/github" ) var ( diff --git a/modules/migrations/gitea.go b/modules/migrations/gitea.go index 8da1bd4683..ac8cf260a5 100644 --- a/modules/migrations/gitea.go +++ b/modules/migrations/gitea.go @@ -28,8 +28,9 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/services/pull" - gouuid "github.com/satori/go.uuid" + gouuid "github.com/google/uuid" ) var ( @@ -93,12 +94,15 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate } var remoteAddr = repo.CloneURL - if len(opts.AuthUsername) > 0 { + if len(opts.AuthToken) > 0 || len(opts.AuthUsername) > 0 { u, err := url.Parse(repo.CloneURL) if err != nil { return err } u.User = url.UserPassword(opts.AuthUsername, opts.AuthPassword) + if len(opts.AuthToken) > 0 { + u.User = url.UserPassword("oauth2", opts.AuthToken) + } remoteAddr = u.String() } @@ -119,6 +123,7 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate if err != nil { return err } + r.DefaultBranch = repo.DefaultBranch r, err = repository.MigrateRepositoryGitData(g.doer, owner, r, structs.MigrateRepoOption{ RepoName: g.repoName, @@ -260,7 +265,7 @@ func (g *GiteaLocalUploader) CreateReleases(releases ...*base.Release) error { for _, asset := range release.Assets { var attach = models.Attachment{ - UUID: gouuid.NewV4().String(), + UUID: gouuid.New().String(), Name: asset.Name, DownloadCount: int64(*asset.DownloadCount), Size: int64(*asset.Size), @@ -524,6 +529,7 @@ func (g *GiteaLocalUploader) CreatePullRequests(prs ...*base.PullRequest) error } for _, pr := range gprs { g.issues.Store(pr.Issue.Index, pr.Issue.ID) + pull.AddToTaskQueue(pr) } return nil } diff --git a/modules/migrations/gitea_test.go b/modules/migrations/gitea_test.go index 3f03cbab31..7834dc26ee 100644 --- a/modules/migrations/gitea_test.go +++ b/modules/migrations/gitea_test.go @@ -26,7 +26,7 @@ func TestGiteaUploadRepo(t *testing.T) { user := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User) var ( - downloader = NewGithubDownloaderV3("", "", "go-xorm", "builder") + downloader = NewGithubDownloaderV3("", "", "", "go-xorm", "builder") repoName = "builder-" + time.Now().Format("2006-01-02-15-04-05") uploader = NewGiteaLocalUploader(graceful.GetManager().HammerContext(), user, user.Name, repoName) ) diff --git a/modules/migrations/github.go b/modules/migrations/github.go index b6bdab09f4..570c91bfd6 100644 --- a/modules/migrations/github.go +++ b/modules/migrations/github.go @@ -18,7 +18,7 @@ import ( "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" - "github.com/google/go-github/v24/github" + "github.com/google/go-github/v32/github" "golang.org/x/oauth2" ) @@ -60,7 +60,7 @@ func (f *GithubDownloaderV3Factory) New(opts base.MigrateOptions) (base.Download log.Trace("Create github downloader: %s/%s", oldOwner, oldName) - return NewGithubDownloaderV3(opts.AuthUsername, opts.AuthPassword, oldOwner, oldName), nil + return NewGithubDownloaderV3(opts.AuthUsername, opts.AuthPassword, opts.AuthToken, oldOwner, oldName), nil } // GitServiceType returns the type of git service @@ -81,7 +81,7 @@ type GithubDownloaderV3 struct { } // NewGithubDownloaderV3 creates a github Downloader via github v3 API -func NewGithubDownloaderV3(userName, password, repoOwner, repoName string) *GithubDownloaderV3 { +func NewGithubDownloaderV3(userName, password, token, repoOwner, repoName string) *GithubDownloaderV3 { var downloader = GithubDownloaderV3{ userName: userName, password: password, @@ -90,23 +90,19 @@ func NewGithubDownloaderV3(userName, password, repoOwner, repoName string) *Gith repoName: repoName, } - var client *http.Client - if userName != "" { - if password == "" { - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: userName}, - ) - client = oauth2.NewClient(downloader.ctx, ts) - } else { - client = &http.Client{ - Transport: &http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - req.SetBasicAuth(userName, password) - return nil, nil - }, - }, - } - } + client := &http.Client{ + Transport: &http.Transport{ + Proxy: func(req *http.Request) (*url.URL, error) { + req.SetBasicAuth(userName, password) + return nil, nil + }, + }, + } + if token != "" { + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: token}, + ) + client = oauth2.NewClient(downloader.ctx, ts) } downloader.client = github.NewClient(client) return &downloader @@ -154,14 +150,20 @@ func (g *GithubDownloaderV3) GetRepoInfo() (*base.Repository, error) { } g.rate = &resp.Rate + defaultBranch := "" + if gr.DefaultBranch != nil { + defaultBranch = *gr.DefaultBranch + } + // convert github repo to stand Repo return &base.Repository{ - Owner: g.repoOwner, - Name: gr.GetName(), - IsPrivate: *gr.Private, - Description: gr.GetDescription(), - OriginalURL: gr.GetHTMLURL(), - CloneURL: gr.GetCloneURL(), + Owner: g.repoOwner, + Name: gr.GetName(), + IsPrivate: *gr.Private, + Description: gr.GetDescription(), + OriginalURL: gr.GetHTMLURL(), + CloneURL: gr.GetCloneURL(), + DefaultBranch: defaultBranch, }, nil } @@ -364,7 +366,7 @@ func (g *GithubDownloaderV3) GetIssues(page, perPage int) ([]*base.Issue, bool, } var labels = make([]*base.Label, 0, len(issue.Labels)) for _, l := range issue.Labels { - labels = append(labels, convertGithubLabel(&l)) + labels = append(labels, convertGithubLabel(l)) } var email string @@ -425,8 +427,8 @@ func (g *GithubDownloaderV3) GetComments(issueNumber int64) ([]*base.Comment, er asc = "asc" ) opt := &github.IssueListCommentsOptions{ - Sort: created, - Direction: asc, + Sort: &created, + Direction: &asc, ListOptions: github.ListOptions{ PerPage: 100, }, diff --git a/modules/migrations/github_test.go b/modules/migrations/github_test.go index 814c771e8c..bffacabc5d 100644 --- a/modules/migrations/github_test.go +++ b/modules/migrations/github_test.go @@ -64,18 +64,19 @@ func assertLabelEqual(t *testing.T, name, color, description string, label *base func TestGitHubDownloadRepo(t *testing.T) { GithubLimitRateRemaining = 3 //Wait at 3 remaining since we could have 3 CI in // - downloader := NewGithubDownloaderV3(os.Getenv("GITHUB_READ_TOKEN"), "", "go-gitea", "test_repo") + downloader := NewGithubDownloaderV3("", "", os.Getenv("GITHUB_READ_TOKEN"), "go-gitea", "test_repo") err := downloader.RefreshRate() assert.NoError(t, err) repo, err := downloader.GetRepoInfo() assert.NoError(t, err) assert.EqualValues(t, &base.Repository{ - Name: "test_repo", - Owner: "go-gitea", - Description: "Test repository for testing migration from github to gitea", - CloneURL: "https://github.com/go-gitea/test_repo.git", - OriginalURL: "https://github.com/go-gitea/test_repo", + Name: "test_repo", + Owner: "go-gitea", + Description: "Test repository for testing migration from github to gitea", + CloneURL: "https://github.com/go-gitea/test_repo.git", + OriginalURL: "https://github.com/go-gitea/test_repo", + DefaultBranch: "master", }, repo) topics, err := downloader.GetTopics() diff --git a/modules/migrations/gitlab.go b/modules/migrations/gitlab.go index 8e1c7d0a83..02b5aa5887 100644 --- a/modules/migrations/gitlab.go +++ b/modules/migrations/gitlab.go @@ -56,10 +56,11 @@ func (f *GitlabDownloaderFactory) New(opts base.MigrateOptions) (base.Downloader baseURL := u.Scheme + "://" + u.Host repoNameSpace := strings.TrimPrefix(u.Path, "/") + repoNameSpace = strings.TrimSuffix(repoNameSpace, ".git") log.Trace("Create gitlab downloader. BaseURL: %s RepoName: %s", baseURL, repoNameSpace) - return NewGitlabDownloader(baseURL, repoNameSpace, opts.AuthUsername, opts.AuthPassword), nil + return NewGitlabDownloader(baseURL, repoNameSpace, opts.AuthUsername, opts.AuthPassword, opts.AuthToken), nil } // GitServiceType returns the type of git service @@ -85,15 +86,12 @@ type GitlabDownloader struct { // NewGitlabDownloader creates a gitlab Downloader via gitlab API // Use either a username/password, personal token entered into the username field, or anonymous/public access // Note: Public access only allows very basic access -func NewGitlabDownloader(baseURL, repoPath, username, password string) *GitlabDownloader { - var gitlabClient *gitlab.Client - var err error - if username != "" { - if password == "" { - gitlabClient, err = gitlab.NewClient(username) - } else { - gitlabClient, err = gitlab.NewBasicAuthClient(username, password, gitlab.WithBaseURL(baseURL)) - } +func NewGitlabDownloader(baseURL, repoPath, username, password, token string) *GitlabDownloader { + gitlabClient, err := gitlab.NewClient(token, gitlab.WithBaseURL(baseURL)) + // Only use basic auth if token is blank and password is NOT + // Basic auth will fail with empty strings, but empty token will allow anonymous public API usage + if token == "" && password != "" { + gitlabClient, err = gitlab.NewBasicAuthClient(username, password, gitlab.WithBaseURL(baseURL)) } if err != nil { @@ -157,12 +155,13 @@ func (g *GitlabDownloader) GetRepoInfo() (*base.Repository, error) { // convert gitlab repo to stand Repo return &base.Repository{ - Owner: owner, - Name: gr.Name, - IsPrivate: private, - Description: gr.Description, - OriginalURL: gr.WebURL, - CloneURL: gr.HTTPURLToRepo, + Owner: owner, + Name: gr.Name, + IsPrivate: private, + Description: gr.Description, + OriginalURL: gr.WebURL, + CloneURL: gr.HTTPURLToRepo, + DefaultBranch: gr.DefaultBranch, }, nil } @@ -240,6 +239,19 @@ func (g *GitlabDownloader) GetMilestones() ([]*base.Milestone, error) { return milestones, nil } +func (g *GitlabDownloader) normalizeColor(val string) string { + val = strings.TrimLeft(val, "#") + val = strings.ToLower(val) + if len(val) == 3 { + c := []rune(val) + val = fmt.Sprintf("%c%c%c%c%c%c", c[0], c[0], c[1], c[1], c[2], c[2]) + } + if len(val) != 6 { + return "" + } + return val +} + // GetLabels returns labels func (g *GitlabDownloader) GetLabels() ([]*base.Label, error) { if g == nil { @@ -258,7 +270,7 @@ func (g *GitlabDownloader) GetLabels() ([]*base.Label, error) { for _, label := range ls { baseLabel := &base.Label{ Name: label.Name, - Color: strings.TrimLeft(label.Color, "#)"), + Color: g.normalizeColor(label.Color), Description: label.Description, } labels = append(labels, baseLabel) diff --git a/modules/migrations/gitlab_test.go b/modules/migrations/gitlab_test.go index 003da5bbdf..2c7b19046f 100644 --- a/modules/migrations/gitlab_test.go +++ b/modules/migrations/gitlab_test.go @@ -27,7 +27,7 @@ func TestGitlabDownloadRepo(t *testing.T) { t.Skipf("Can't access test repo, skipping %s", t.Name()) } - downloader := NewGitlabDownloader("https://gitlab.com", "gitea/test_repo", gitlabPersonalAccessToken, "") + downloader := NewGitlabDownloader("https://gitlab.com", "gitea/test_repo", "", "", gitlabPersonalAccessToken) if downloader == nil { t.Fatal("NewGitlabDownloader is nil") } @@ -35,11 +35,12 @@ func TestGitlabDownloadRepo(t *testing.T) { assert.NoError(t, err) // Repo Owner is blank in Gitlab Group repos assert.EqualValues(t, &base.Repository{ - Name: "test_repo", - Owner: "", - Description: "Test repository for testing migration from gitlab to gitea", - CloneURL: "https://gitlab.com/gitea/test_repo.git", - OriginalURL: "https://gitlab.com/gitea/test_repo", + Name: "test_repo", + Owner: "", + Description: "Test repository for testing migration from gitlab to gitea", + CloneURL: "https://gitlab.com/gitea/test_repo.git", + OriginalURL: "https://gitlab.com/gitea/test_repo", + DefaultBranch: "master", }, repo) topics, err := downloader.GetTopics() diff --git a/modules/migrations/migrate.go b/modules/migrations/migrate.go index c970ba6920..5c666379d5 100644 --- a/modules/migrations/migrate.go +++ b/modules/migrations/migrate.go @@ -36,6 +36,12 @@ func MigrateRepository(ctx context.Context, doer *models.User, ownerName string, theFactory base.DownloaderFactory ) + // determine if user is token + if len(opts.AuthUsername) != 0 && len(opts.AuthPassword) == 0 { + opts.AuthToken = opts.AuthUsername + opts.AuthUsername = "" + } + for _, factory := range factories { if match, err := factory.Match(opts); err != nil { return nil, err @@ -78,7 +84,7 @@ func MigrateRepository(ctx context.Context, doer *models.User, ownerName string, } if err2 := models.CreateRepositoryNotice(fmt.Sprintf("Migrate repository from %s failed: %v", opts.OriginalURL, err)); err2 != nil { - log.Error("create respotiry notice failed: ", err2) + log.Error("create repository notice failed: ", err2) } return nil, err } diff --git a/modules/notification/action/action.go b/modules/notification/action/action.go index 9956940f30..5fde862fd1 100644 --- a/modules/notification/action/action.go +++ b/modules/notification/action/action.go @@ -92,13 +92,22 @@ func (a *actionNotifier) NotifyCreateIssueComment(doer *models.User, repo *model act := &models.Action{ ActUserID: doer.ID, ActUser: doer, - Content: fmt.Sprintf("%d|%s", issue.Index, comment.Content), RepoID: issue.Repo.ID, Repo: issue.Repo, Comment: comment, CommentID: comment.ID, IsPrivate: issue.Repo.IsPrivate, } + + content := "" + + if len(comment.Content) > 200 { + content = comment.Content[:strings.LastIndex(comment.Content[0:200], " ")] + "โ€ฆ" + } else { + content = comment.Content + } + act.Content = fmt.Sprintf("%d|%s", issue.Index, content) + if issue.IsPull { act.OpType = models.ActionCommentPull } else { diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index 625cf119a9..c8b6bae724 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -99,30 +99,26 @@ func (m *webhookNotifier) NotifyForkRepository(doer *models.User, oldRepo, repo func (m *webhookNotifier) NotifyCreateRepository(doer *models.User, u *models.User, repo *models.Repository) { // Add to hook queue for created repo after session commit. - if u.IsOrganization() { - if err := webhook_module.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{ - Action: api.HookRepoCreated, - Repository: repo.APIFormat(models.AccessModeOwner), - Organization: u.APIFormat(), - Sender: doer.APIFormat(), - }); err != nil { - log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) - } + if err := webhook_module.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{ + Action: api.HookRepoCreated, + Repository: repo.APIFormat(models.AccessModeOwner), + Organization: u.APIFormat(), + Sender: doer.APIFormat(), + }); err != nil { + log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) } } func (m *webhookNotifier) NotifyDeleteRepository(doer *models.User, repo *models.Repository) { u := repo.MustOwner() - if u.IsOrganization() { - if err := webhook_module.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{ - Action: api.HookRepoDeleted, - Repository: repo.APIFormat(models.AccessModeOwner), - Organization: u.APIFormat(), - Sender: doer.APIFormat(), - }); err != nil { - log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) - } + if err := webhook_module.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{ + Action: api.HookRepoDeleted, + Repository: repo.APIFormat(models.AccessModeOwner), + Organization: u.APIFormat(), + Sender: doer.APIFormat(), + }); err != nil { + log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err) } } diff --git a/modules/public/public.go b/modules/public/public.go index fb8d9c1955..790f418a20 100644 --- a/modules/public/public.go +++ b/modules/public/public.go @@ -6,6 +6,7 @@ package public import ( "encoding/base64" + "fmt" "log" "net/http" "path" @@ -30,12 +31,13 @@ type Options struct { Prefix string } -// List of known entries inside the `public` directory -var knownEntries = []string{ +// KnownPublicEntries list all direct children in the `public` directory +var KnownPublicEntries = []string{ "css", "fomantic", "img", "js", + "serviceworker.js", "vendor", } @@ -114,7 +116,7 @@ func (opts *Options) handle(ctx *macaron.Context, log *log.Logger, opt *Options) if len(parts) < 2 { return false } - for _, entry := range knownEntries { + for _, entry := range KnownPublicEntries { if entry == parts[1] { ctx.Resp.WriteHeader(404) return true @@ -158,7 +160,7 @@ func (opts *Options) handle(ctx *macaron.Context, log *log.Logger, opt *Options) // Add an Expires header to the static content if opt.ExpiresAfter > 0 { ctx.Resp.Header().Set("Expires", time.Now().Add(opt.ExpiresAfter).UTC().Format(http.TimeFormat)) - tag := GenerateETag(string(fi.Size()), fi.Name(), fi.ModTime().UTC().Format(http.TimeFormat)) + tag := GenerateETag(fmt.Sprint(fi.Size()), fi.Name(), fi.ModTime().UTC().Format(http.TimeFormat)) ctx.Resp.Header().Set("ETag", tag) if ctx.Req.Header.Get("If-None-Match") == tag { ctx.Resp.WriteHeader(304) diff --git a/modules/queue/setting.go b/modules/queue/setting.go index c47e85f756..786a08a3b0 100644 --- a/modules/queue/setting.go +++ b/modules/queue/setting.go @@ -75,6 +75,7 @@ func CreateQueue(name string, handle HandlerFunc, exemplar interface{}) Queue { MaxAttempts: q.MaxAttempts, Config: cfg, QueueLength: q.Length, + Name: name, }, exemplar) } if err != nil { diff --git a/modules/repofiles/action.go b/modules/repofiles/action.go index 44ca285ef0..dfef5d55b0 100644 --- a/modules/repofiles/action.go +++ b/modules/repofiles/action.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" "html" + "time" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" @@ -176,7 +177,7 @@ func CommitRepoAction(optsList ...*CommitRepoActionOptions) error { var err error if repo != nil { // Change repository empty status and update last updated time. - if err := models.UpdateRepository(repo, false); err != nil { + if err := models.UpdateRepositoryUpdatedTime(repo.ID, time.Now()); err != nil { return fmt.Errorf("UpdateRepository: %v", err) } } @@ -204,6 +205,10 @@ func CommitRepoAction(optsList ...*CommitRepoActionOptions) error { } gitRepo.Close() } + // Update the is empty and default_branch columns + if err := models.UpdateRepositoryCols(repo, "default_branch", "is_empty"); err != nil { + return fmt.Errorf("UpdateRepositoryCols: %v", err) + } } opType := models.ActionCommitRepo @@ -274,7 +279,7 @@ func CommitRepoAction(optsList ...*CommitRepoActionOptions) error { if repo != nil { // Change repository empty status and update last updated time. - if err := models.UpdateRepository(repo, false); err != nil { + if err := models.UpdateRepositoryUpdatedTime(repo.ID, time.Now()); err != nil { return fmt.Errorf("UpdateRepository: %v", err) } } diff --git a/modules/repofiles/temp_repo.go b/modules/repofiles/temp_repo.go index 89f9b0b208..ca35b51c29 100644 --- a/modules/repofiles/temp_repo.go +++ b/modules/repofiles/temp_repo.go @@ -278,7 +278,7 @@ func (t *TemporaryUploadRepository) DiffIndex() (*gitdiff.Diff, error) { var diff *gitdiff.Diff var finalErr error - if err := git.NewCommand("diff-index", "--cached", "-p", "HEAD"). + if err := git.NewCommand("diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD"). RunInDirTimeoutEnvFullPipelineFunc(nil, 30*time.Second, t.basePath, stdoutWriter, stderr, nil, func(ctx context.Context, cancel context.CancelFunc) error { _ = stdoutWriter.Close() diff, finalErr = gitdiff.ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdoutReader) diff --git a/modules/repository/branch.go b/modules/repository/branch.go index 418ba25c89..358e59f39f 100644 --- a/modules/repository/branch.go +++ b/modules/repository/branch.go @@ -9,7 +9,6 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/log" ) // GetBranch returns a branch by its name @@ -74,39 +73,9 @@ func CreateNewBranch(doer *models.User, repo *models.Repository, oldBranchName, return fmt.Errorf("OldBranch: %s does not exist. Cannot create new branch from this", oldBranchName) } - basePath, err := models.CreateTemporaryPath("branch-maker") - if err != nil { - return err - } - defer func() { - if err := models.RemoveTemporaryPath(basePath); err != nil { - log.Error("CreateNewBranch: RemoveTemporaryPath: %s", err) - } - }() - - if err := git.Clone(repo.RepoPath(), basePath, git.CloneRepoOptions{ - Bare: true, - Shared: true, - }); err != nil { - log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err) - return fmt.Errorf("Failed to clone repository: %s (%v)", repo.FullName(), err) - } - - gitRepo, err := git.OpenRepository(basePath) - if err != nil { - log.Error("Unable to open temporary repository: %s (%v)", basePath, err) - return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err) - } - defer gitRepo.Close() - - if err = gitRepo.CreateBranch(branchName, oldBranchName); err != nil { - log.Error("Unable to create branch: %s from %s. (%v)", branchName, oldBranchName, err) - return fmt.Errorf("Unable to create branch: %s from %s. (%v)", branchName, oldBranchName, err) - } - - if err = git.Push(basePath, git.PushOptions{ - Remote: "origin", - Branch: branchName, + if err := git.Push(repo.RepoPath(), git.PushOptions{ + Remote: repo.RepoPath(), + Branch: fmt.Sprintf("%s:%s%s", oldBranchName, git.BranchPrefix, branchName), Env: models.PushingEnvironment(doer, repo), }); err != nil { if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) { @@ -124,39 +93,10 @@ func CreateNewBranchFromCommit(doer *models.User, repo *models.Repository, commi if err := checkBranchName(repo, branchName); err != nil { return err } - basePath, err := models.CreateTemporaryPath("branch-maker") - if err != nil { - return err - } - defer func() { - if err := models.RemoveTemporaryPath(basePath); err != nil { - log.Error("CreateNewBranchFromCommit: RemoveTemporaryPath: %s", err) - } - }() - if err := git.Clone(repo.RepoPath(), basePath, git.CloneRepoOptions{ - Bare: true, - Shared: true, - }); err != nil { - log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err) - return fmt.Errorf("Failed to clone repository: %s (%v)", repo.FullName(), err) - } - - gitRepo, err := git.OpenRepository(basePath) - if err != nil { - log.Error("Unable to open temporary repository: %s (%v)", basePath, err) - return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err) - } - defer gitRepo.Close() - - if err = gitRepo.CreateBranch(branchName, commit); err != nil { - log.Error("Unable to create branch: %s from %s. (%v)", branchName, commit, err) - return fmt.Errorf("Unable to create branch: %s from %s. (%v)", branchName, commit, err) - } - - if err = git.Push(basePath, git.PushOptions{ - Remote: "origin", - Branch: branchName, + if err := git.Push(repo.RepoPath(), git.PushOptions{ + Remote: repo.RepoPath(), + Branch: fmt.Sprintf("%s:%s%s", commit, git.BranchPrefix, branchName), Env: models.PushingEnvironment(doer, repo), }); err != nil { if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) { diff --git a/modules/repository/create.go b/modules/repository/create.go index 5c0aae30da..0aafb7c21a 100644 --- a/modules/repository/create.go +++ b/modules/repository/create.go @@ -23,6 +23,10 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (_ *m } } + if len(opts.DefaultBranch) == 0 { + opts.DefaultBranch = setting.Repository.DefaultBranch + } + repo := &models.Repository{ OwnerID: u.ID, Owner: u, @@ -47,7 +51,7 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (_ *m // No need for init mirror. if !opts.IsMirror { repoPath := models.RepoPath(u.Name, repo.Name) - if err = initRepository(ctx, repoPath, u, repo, opts); err != nil { + if err = initRepository(ctx, repoPath, doer, repo, opts); err != nil { if err2 := os.RemoveAll(repoPath); err2 != nil { log.Error("initRepository: %v", err) return fmt.Errorf( diff --git a/modules/repository/init.go b/modules/repository/init.go index f468ca0435..5bdfa7490d 100644 --- a/modules/repository/init.go +++ b/modules/repository/init.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" "github.com/mcuadros/go-version" "github.com/unknwon/com" @@ -147,7 +148,7 @@ func initRepoCommit(tmpPath string, repo *models.Repository, u *models.User, def } if len(defaultBranch) == 0 { - defaultBranch = "master" + defaultBranch = setting.Repository.DefaultBranch } if stdout, err := git.NewCommand("push", "origin", "master:"+defaultBranch). @@ -213,6 +214,13 @@ func initRepository(ctx models.DBContext, repoPath string, u *models.User, repo repo.DefaultBranch = "master" if len(opts.DefaultBranch) > 0 { repo.DefaultBranch = opts.DefaultBranch + gitRepo, err := git.OpenRepository(repo.RepoPath()) + if err != nil { + return fmt.Errorf("openRepository: %v", err) + } + if err = gitRepo.SetDefaultBranch(repo.DefaultBranch); err != nil { + return fmt.Errorf("setDefaultBranch: %v", err) + } } if err = models.UpdateRepositoryCtx(ctx, repo, false); err != nil { diff --git a/modules/repository/repo.go b/modules/repository/repo.go index d57b16c913..2651dc0480 100644 --- a/modules/repository/repo.go +++ b/modules/repository/repo.go @@ -102,18 +102,22 @@ func MigrateRepositoryGitData(doer, u *models.User, repo *models.Repository, opt return repo, fmt.Errorf("git.IsEmpty: %v", err) } - if !opts.Releases && !repo.IsEmpty { - // Try to get HEAD branch and set it as default branch. - headBranch, err := gitRepo.GetHEADBranch() - if err != nil { - return repo, fmt.Errorf("GetHEADBranch: %v", err) - } - if headBranch != nil { - repo.DefaultBranch = headBranch.Name + if !repo.IsEmpty { + if len(repo.DefaultBranch) == 0 { + // Try to get HEAD branch and set it as default branch. + headBranch, err := gitRepo.GetHEADBranch() + if err != nil { + return repo, fmt.Errorf("GetHEADBranch: %v", err) + } + if headBranch != nil { + repo.DefaultBranch = headBranch.Name + } } - if err = SyncReleasesWithTags(repo, gitRepo); err != nil { - log.Error("Failed to synchronize tags to releases for repository: %v", err) + if !opts.Releases { + if err = SyncReleasesWithTags(repo, gitRepo); err != nil { + log.Error("Failed to synchronize tags to releases for repository: %v", err) + } } } diff --git a/modules/session/memory.go b/modules/session/memory.go deleted file mode 100644 index 4f72feac9b..0000000000 --- a/modules/session/memory.go +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2013 Beego Authors -// Copyright 2014 The Macaron Authors -// Copyright 2019 The Gitea Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package session - -import ( - "container/list" - "fmt" - "sync" - "time" - - "gitea.com/macaron/session" -) - -// MemStore represents a in-memory session store implementation. -type MemStore struct { - sid string - lock sync.RWMutex - data map[interface{}]interface{} - lastAccess time.Time -} - -// NewMemStore creates and returns a memory session store. -func NewMemStore(sid string) *MemStore { - return &MemStore{ - sid: sid, - data: make(map[interface{}]interface{}), - lastAccess: time.Now(), - } -} - -// Set sets value to given key in session. -func (s *MemStore) Set(key, val interface{}) error { - s.lock.Lock() - defer s.lock.Unlock() - - s.data[key] = val - return nil -} - -// Get gets value by given key in session. -func (s *MemStore) Get(key interface{}) interface{} { - s.lock.RLock() - defer s.lock.RUnlock() - - return s.data[key] -} - -// Delete deletes a key from session. -func (s *MemStore) Delete(key interface{}) error { - s.lock.Lock() - defer s.lock.Unlock() - - delete(s.data, key) - return nil -} - -// ID returns current session ID. -func (s *MemStore) ID() string { - return s.sid -} - -// Release releases resource and save data to provider. -func (*MemStore) Release() error { - return nil -} - -// Flush deletes all session data. -func (s *MemStore) Flush() error { - s.lock.Lock() - defer s.lock.Unlock() - - s.data = make(map[interface{}]interface{}) - return nil -} - -// MemProvider represents a in-memory session provider implementation. -type MemProvider struct { - lock sync.RWMutex - maxLifetime int64 - data map[string]*list.Element - // A priority list whose lastAccess newer gets higher priority. - list *list.List -} - -// Init initializes memory session provider. -func (p *MemProvider) Init(maxLifetime int64, _ string) error { - p.lock.Lock() - p.maxLifetime = maxLifetime - p.lock.Unlock() - return nil -} - -// update expands time of session store by given ID. -func (p *MemProvider) update(sid string) error { - p.lock.Lock() - defer p.lock.Unlock() - - if e, ok := p.data[sid]; ok { - e.Value.(*MemStore).lastAccess = time.Now() - p.list.MoveToFront(e) - return nil - } - return nil -} - -// Read returns raw session store by session ID. -func (p *MemProvider) Read(sid string) (_ session.RawStore, err error) { - p.lock.RLock() - e, ok := p.data[sid] - p.lock.RUnlock() - - if ok { - if err = p.update(sid); err != nil { - return nil, err - } - return e.Value.(*MemStore), nil - } - - // Create a new session. - p.lock.Lock() - defer p.lock.Unlock() - - s := NewMemStore(sid) - p.data[sid] = p.list.PushBack(s) - return s, nil -} - -// Exist returns true if session with given ID exists. -func (p *MemProvider) Exist(sid string) bool { - p.lock.RLock() - defer p.lock.RUnlock() - - _, ok := p.data[sid] - return ok -} - -// Destroy deletes a session by session ID. -func (p *MemProvider) Destroy(sid string) error { - p.lock.Lock() - defer p.lock.Unlock() - - e, ok := p.data[sid] - if !ok { - return nil - } - - p.list.Remove(e) - delete(p.data, sid) - return nil -} - -// Regenerate regenerates a session store from old session ID to new one. -func (p *MemProvider) Regenerate(oldsid, sid string) (session.RawStore, error) { - if p.Exist(sid) { - return nil, fmt.Errorf("new sid '%s' already exists", sid) - } - - s, err := p.Read(oldsid) - if err != nil { - return nil, err - } - - if err = p.Destroy(oldsid); err != nil { - return nil, err - } - - s.(*MemStore).sid = sid - - p.lock.Lock() - defer p.lock.Unlock() - p.data[sid] = p.list.PushBack(s) - return s, nil -} - -// Count counts and returns number of sessions. -func (p *MemProvider) Count() int { - return p.list.Len() -} - -// GC calls GC to clean expired sessions. -func (p *MemProvider) GC() { - p.lock.RLock() - for { - // No session in the list. - e := p.list.Back() - if e == nil { - break - } - - if (e.Value.(*MemStore).lastAccess.Unix() + p.maxLifetime) < time.Now().Unix() { - p.lock.RUnlock() - p.lock.Lock() - p.list.Remove(e) - delete(p.data, e.Value.(*MemStore).sid) - p.lock.Unlock() - p.lock.RLock() - } else { - break - } - } - p.lock.RUnlock() -} diff --git a/modules/session/virtual.go b/modules/session/virtual.go index 027960a289..c8e1e210cb 100644 --- a/modules/session/virtual.go +++ b/modules/session/virtual.go @@ -5,7 +5,6 @@ package session import ( - "container/list" "encoding/json" "fmt" "sync" @@ -37,7 +36,7 @@ func (o *VirtualSessionProvider) Init(gclifetime int64, config string) error { // This is only slightly more wrong than modules/setting/session.go:23 switch opts.Provider { case "memory": - o.provider = &MemProvider{list: list.New(), data: make(map[string]*list.Element)} + o.provider = &session.MemProvider{} case "file": o.provider = &session.FileProvider{} case "redis": @@ -107,10 +106,11 @@ func init() { // VirtualStore represents a virtual session store implementation. type VirtualStore struct { - p *VirtualSessionProvider - sid string - lock sync.RWMutex - data map[interface{}]interface{} + p *VirtualSessionProvider + sid string + lock sync.RWMutex + data map[interface{}]interface{} + released bool } // NewVirtualStore creates and returns a virtual session store. @@ -164,7 +164,7 @@ func (s *VirtualStore) Release() error { // Now ensure that we don't exist! realProvider := s.p.provider - if realProvider.Exist(s.sid) { + if !s.released && realProvider.Exist(s.sid) { // This is an error! return fmt.Errorf("new sid '%s' already exists", s.sid) } @@ -172,12 +172,19 @@ func (s *VirtualStore) Release() error { if err != nil { return err } + if err := realStore.Flush(); err != nil { + return err + } for key, value := range s.data { if err := realStore.Set(key, value); err != nil { return err } } - return realStore.Release() + err = realStore.Release() + if err == nil { + s.released = true + } + return err } return nil } diff --git a/modules/setting/cache.go b/modules/setting/cache.go index 34a212db18..af47bd085a 100644 --- a/modules/setting/cache.go +++ b/modules/setting/cache.go @@ -23,7 +23,7 @@ type Cache struct { var ( // CacheService the global cache CacheService = struct { - Cache + Cache `ini:"cache"` LastCommit struct { Enabled bool diff --git a/modules/setting/cron.go b/modules/setting/cron.go index c8228ddaa8..9475887ecc 100644 --- a/modules/setting/cron.go +++ b/modules/setting/cron.go @@ -4,8 +4,26 @@ package setting +import "reflect" + // GetCronSettings maps the cron subsection to the provided config func GetCronSettings(name string, config interface{}) (interface{}, error) { - err := Cfg.Section("cron." + name).MapTo(config) - return config, err + if err := Cfg.Section("cron." + name).MapTo(config); err != nil { + return config, err + } + + typ := reflect.TypeOf(config).Elem() + val := reflect.ValueOf(config).Elem() + + for i := 0; i < typ.NumField(); i++ { + field := val.Field(i) + tpField := typ.Field(i) + if tpField.Type.Kind() == reflect.Struct && tpField.Anonymous { + if err := Cfg.Section("cron." + name).MapTo(field.Addr().Interface()); err != nil { + return config, err + } + } + } + + return config, nil } diff --git a/modules/setting/cron_test.go b/modules/setting/cron_test.go new file mode 100644 index 0000000000..8670a92bac --- /dev/null +++ b/modules/setting/cron_test.go @@ -0,0 +1,47 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package setting + +import ( + "testing" + + "github.com/stretchr/testify/assert" + ini "gopkg.in/ini.v1" +) + +func Test_GetCronSettings(t *testing.T) { + + type BaseStruct struct { + Base bool + Second string + } + + type Extended struct { + BaseStruct + Extend bool + } + + iniStr := ` +[cron.test] +Base = true +Second = white rabbit +Extend = true +` + Cfg, _ = ini.Load([]byte(iniStr)) + + extended := &Extended{ + BaseStruct: BaseStruct{ + Second: "queen of hearts", + }, + } + + _, err := GetCronSettings("test", extended) + + assert.NoError(t, err) + assert.True(t, extended.Base) + assert.EqualValues(t, extended.Second, "white rabbit") + assert.True(t, extended.Extend) + +} diff --git a/modules/setting/database.go b/modules/setting/database.go index 85043e8c11..4e84f8f8d1 100644 --- a/modules/setting/database.go +++ b/modules/setting/database.go @@ -105,7 +105,7 @@ func DBConnStr() (string, error) { switch Database.Type { case "mysql": connType := "tcp" - if Database.Host[0] == '/' { // looks like a unix socket + if len(Database.Host) > 0 && Database.Host[0] == '/' { // looks like a unix socket connType = "unix" } tls := Database.SSLMode @@ -163,7 +163,7 @@ func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, db // ParseMSSQLHostPort splits the host into host and port func ParseMSSQLHostPort(info string) (string, string) { - host, port := "127.0.0.1", "1433" + host, port := "127.0.0.1", "0" if strings.Contains(info, ":") { host = strings.Split(info, ":")[0] port = strings.Split(info, ":")[1] diff --git a/modules/setting/repository.go b/modules/setting/repository.go index 8af3eaaf46..164ba733e7 100644 --- a/modules/setting/repository.go +++ b/modules/setting/repository.go @@ -40,6 +40,7 @@ var ( DisabledRepoUnits []string DefaultRepoUnits []string PrefixArchiveFiles bool + DefaultBranch string // Repository editor settings Editor struct { @@ -201,6 +202,7 @@ func newRepository() { Repository.DisableHTTPGit = sec.Key("DISABLE_HTTP_GIT").MustBool() Repository.UseCompatSSHURI = sec.Key("USE_COMPAT_SSH_URI").MustBool() Repository.MaxCreationLimit = sec.Key("MAX_CREATION_LIMIT").MustInt(-1) + Repository.DefaultBranch = sec.Key("DEFAULT_BRANCH").MustString("master") RepoRootPath = sec.Key("ROOT").MustString(path.Join(homeDir, "gitea-repositories")) forcePathSeparator(RepoRootPath) if !filepath.IsAbs(RepoRootPath) { diff --git a/modules/setting/setting.go b/modules/setting/setting.go index ede4687c81..42a01cc11a 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -256,12 +256,14 @@ var ( // Markdown settings Markdown = struct { - EnableHardLineBreak bool - CustomURLSchemes []string `ini:"CUSTOM_URL_SCHEMES"` - FileExtensions []string + EnableHardLineBreakInComments bool + EnableHardLineBreakInDocuments bool + CustomURLSchemes []string `ini:"CUSTOM_URL_SCHEMES"` + FileExtensions []string }{ - EnableHardLineBreak: true, - FileExtensions: strings.Split(".md,.markdown,.mdown,.mkd", ","), + EnableHardLineBreakInComments: true, + EnableHardLineBreakInDocuments: false, + FileExtensions: strings.Split(".md,.markdown,.mdown,.mkd", ","), } // Admin settings @@ -664,7 +666,10 @@ func NewContext() { PortToRedirect = sec.Key("PORT_TO_REDIRECT").MustString("80") OfflineMode = sec.Key("OFFLINE_MODE").MustBool() DisableRouterLog = sec.Key("DISABLE_ROUTER_LOG").MustBool() - StaticRootPath = sec.Key("STATIC_ROOT_PATH").MustString(AppWorkPath) + if len(StaticRootPath) == 0 { + StaticRootPath = AppWorkPath + } + StaticRootPath = sec.Key("STATIC_ROOT_PATH").MustString(StaticRootPath) StaticCacheTime = sec.Key("STATIC_CACHE_TIME").MustDuration(6 * time.Hour) AppDataPath = sec.Key("APP_DATA_PATH").MustString(path.Join(AppWorkPath, "data")) EnableGzip = sec.Key("ENABLE_GZIP").MustBool() @@ -728,6 +733,8 @@ func NewContext() { for _, key := range minimumKeySizes { if key.MustInt() != -1 { SSH.MinimumKeySizes[strings.ToLower(key.Name())] = key.MustInt() + } else { + delete(SSH.MinimumKeySizes, strings.ToLower(key.Name())) } } SSH.AuthorizedKeysBackup = sec.Key("SSH_AUTHORIZED_KEYS_BACKUP").MustBool(true) @@ -999,15 +1006,15 @@ func NewContext() { if len(Langs) == 0 { Langs = []string{ "en-US", "zh-CN", "zh-HK", "zh-TW", "de-DE", "fr-FR", "nl-NL", "lv-LV", - "ru-RU", "uk-UA", "ja-JP", "es-ES", "pt-BR", "pl-PL", "bg-BG", "it-IT", - "fi-FI", "tr-TR", "cs-CZ", "sr-SP", "sv-SE", "ko-KR"} + "ru-RU", "uk-UA", "ja-JP", "es-ES", "pt-BR", "pt-PT", "pl-PL", "bg-BG", + "it-IT", "fi-FI", "tr-TR", "cs-CZ", "sr-SP", "sv-SE", "ko-KR"} } Names = Cfg.Section("i18n").Key("NAMES").Strings(",") if len(Names) == 0 { Names = []string{"English", "็ฎ€ไฝ“ไธญๆ–‡", "็น้ซ”ไธญๆ–‡๏ผˆ้ฆ™ๆธฏ๏ผ‰", "็น้ซ”ไธญๆ–‡๏ผˆๅฐ็ฃ๏ผ‰", "Deutsch", "franรงais", "Nederlands", "latvieลกu", "ั€ัƒััะบะธะน", "ะฃะบั€ะฐั—ะฝััŒะบะฐ", "ๆ—ฅๆœฌ่ชž", - "espaรฑol", "portuguรชs do Brasil", "polski", "ะฑัŠะปะณะฐั€ัะบะธ", "italiano", - "suomi", "Tรผrkรงe", "ฤeลกtina", "ัั€ะฟัะบะธ", "svenska", "ํ•œ๊ตญ์–ด"} + "espaรฑol", "portuguรชs do Brasil", "Portuguรชs de Portugal", "polski", "ะฑัŠะปะณะฐั€ัะบะธ", + "italiano", "suomi", "Tรผrkรงe", "ฤeลกtina", "ัั€ะฟัะบะธ", "svenska", "ํ•œ๊ตญ์–ด"} } dateLangs = Cfg.Section("i18n.datelang").KeysHash() @@ -1025,8 +1032,8 @@ func NewContext() { newMarkup() sec = Cfg.Section("U2F") - U2F.TrustedFacets, _ = shellquote.Split(sec.Key("TRUSTED_FACETS").MustString(strings.TrimRight(AppURL, "/"))) - U2F.AppID = sec.Key("APP_ID").MustString(strings.TrimRight(AppURL, "/")) + U2F.TrustedFacets, _ = shellquote.Split(sec.Key("TRUSTED_FACETS").MustString(strings.TrimSuffix(AppURL, AppSubURL+"/"))) + U2F.AppID = sec.Key("APP_ID").MustString(strings.TrimSuffix(AppURL, "/")) zip.Verbose = false @@ -1069,7 +1076,7 @@ func loadInternalToken(sec *ini.Section) string { return token } - return string(buf) + return strings.TrimSpace(string(buf)) default: log.Fatal("Unsupported URI-Scheme %q (INTERNAL_TOKEN_URI = %q)", tempURI.Scheme, uri) } diff --git a/modules/structs/pull.go b/modules/structs/pull.go index c4ec7d416a..90b3807ddb 100644 --- a/modules/structs/pull.go +++ b/modules/structs/pull.go @@ -82,6 +82,7 @@ type CreatePullRequestOption struct { type EditPullRequestOption struct { Title string `json:"title"` Body string `json:"body"` + Base string `json:"base"` Assignee string `json:"assignee"` Assignees []string `json:"assignees"` Milestone int64 `json:"milestone"` diff --git a/modules/structs/repo.go b/modules/structs/repo.go index 70de9b7469..778dc0f5b8 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -213,6 +213,7 @@ type MigrateRepoOption struct { CloneAddr string `json:"clone_addr" binding:"Required"` AuthUsername string `json:"auth_username"` AuthPassword string `json:"auth_password"` + AuthToken string `json:"auth_token"` // required: true UID int `json:"uid" binding:"Required"` // required: true diff --git a/modules/task/migrate.go b/modules/task/migrate.go index d3b4fa45f0..881ffd2321 100644 --- a/modules/task/migrate.go +++ b/modules/task/migrate.go @@ -5,7 +5,6 @@ package task import ( - "bytes" "errors" "fmt" "strings" @@ -38,10 +37,8 @@ func handleCreateError(owner *models.User, err error, name string) error { func runMigrateTask(t *models.Task) (err error) { defer func() { if e := recover(); e != nil { - var buf bytes.Buffer - fmt.Fprintf(&buf, "Handler crashed with error: %v", log.Stack(2)) - - err = errors.New(buf.String()) + err = fmt.Errorf("PANIC whilst trying to do migrate task: %v\nStacktrace: %v", err, log.Stack(2)) + log.Critical("PANIC during runMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d]: %v", t.ID, t.DoerID, t.RepoID, t.OwnerID, err) } if err == nil { @@ -51,14 +48,14 @@ func runMigrateTask(t *models.Task) (err error) { return } - log.Error("FinishMigrateTask failed: %s", err.Error()) + log.Error("FinishMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d] failed: %v", t.ID, t.DoerID, t.RepoID, t.OwnerID, err) } t.EndTime = timeutil.TimeStampNow() t.Status = structs.TaskStatusFailed t.Errors = err.Error() if err := t.UpdateCols("status", "errors", "end_time"); err != nil { - log.Error("Task UpdateCols failed: %s", err.Error()) + log.Error("Task UpdateCols failed: %v", err) } if t.Repo != nil { diff --git a/modules/templates/dynamic.go b/modules/templates/dynamic.go index 6153e8d027..bd1c4d06c5 100644 --- a/modules/templates/dynamic.go +++ b/modules/templates/dynamic.go @@ -48,18 +48,6 @@ func JSONRenderer() macaron.Handler { }) } -// JSRenderer implements the macaron handler for serving JS templates. -func JSRenderer() macaron.Handler { - return macaron.Renderer(macaron.RenderOptions{ - Funcs: NewFuncMap(), - Directory: path.Join(setting.StaticRootPath, "templates"), - AppendDirectories: []string{ - path.Join(setting.CustomPath, "templates"), - }, - HTMLContentType: "application/javascript", - }) -} - // Mailer provides the templates required for sending notification mails. func Mailer() (*texttmpl.Template, *template.Template) { for _, funcs := range NewTextFuncMap() { diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 374f13af0f..f952b36593 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -164,9 +164,16 @@ func NewFuncMap() []template.FuncMap { mimeType := mime.TypeByExtension(filepath.Ext(filename)) return strings.HasPrefix(mimeType, "image/") }, - "TabSizeClass": func(ec *editorconfig.Editorconfig, filename string) string { + "TabSizeClass": func(ec interface{}, filename string) string { + var ( + value *editorconfig.Editorconfig + ok bool + ) if ec != nil { - def, err := ec.GetDefinitionForFilename(filename) + if value, ok = ec.(*editorconfig.Editorconfig); !ok || value == nil { + return "tab-size-8" + } + def, err := value.GetDefinitionForFilename(filename) if err != nil { log.Error("tab size class: getting definition for filename: %v", err) return "tab-size-8" @@ -282,8 +289,8 @@ func NewFuncMap() []template.FuncMap { return "" } }, - "NotificationSettings": func() map[string]int { - return map[string]int{ + "NotificationSettings": func() map[string]interface{} { + return map[string]interface{}{ "MinTimeout": int(setting.UI.Notification.MinTimeout / time.Millisecond), "TimeoutStep": int(setting.UI.Notification.TimeoutStep / time.Millisecond), "MaxTimeout": int(setting.UI.Notification.MaxTimeout / time.Millisecond), @@ -612,7 +619,7 @@ func ActionContent2Commits(act Actioner) *repository.PushCommits { // DiffTypeToStr returns diff type name func DiffTypeToStr(diffType int) string { diffTypes := map[int]string{ - 1: "add", 2: "modify", 3: "del", 4: "rename", + 1: "add", 2: "modify", 3: "del", 4: "rename", 5: "copy", } return diffTypes[diffType] } diff --git a/modules/templates/static.go b/modules/templates/static.go index 5bc4e33e1c..a3aff5e567 100644 --- a/modules/templates/static.go +++ b/modules/templates/static.go @@ -132,15 +132,6 @@ func JSONRenderer() macaron.Handler { }) } -// JSRenderer implements the macaron handler for serving JS templates. -func JSRenderer() macaron.Handler { - return macaron.Renderer(macaron.RenderOptions{ - Funcs: NewFuncMap(), - TemplateFileSystem: NewTemplateFileSystem(), - HTMLContentType: "application/javascript", - }) -} - // Mailer provides the templates required for sending notification mails. func Mailer() (*texttmpl.Template, *template.Template) { for _, funcs := range NewTextFuncMap() { diff --git a/modules/timeutil/timestamp.go b/modules/timeutil/timestamp.go index f70da9db74..b1c60c3084 100644 --- a/modules/timeutil/timestamp.go +++ b/modules/timeutil/timestamp.go @@ -75,6 +75,11 @@ func (ts TimeStamp) FormatShort() string { return ts.Format("Jan 02, 2006") } +// FormatDate formats a date in YYYY-MM-DD server time zone +func (ts TimeStamp) FormatDate() string { + return time.Unix(int64(ts), 0).String()[:10] +} + // IsZero is zero time func (ts TimeStamp) IsZero() bool { return ts.AsTimeInLocation(time.Local).IsZero() diff --git a/modules/webhook/dingtalk.go b/modules/webhook/dingtalk.go index f2dd5a79ed..4e0e52451a 100644 --- a/modules/webhook/dingtalk.go +++ b/modules/webhook/dingtalk.go @@ -264,7 +264,11 @@ func GetDingtalkPayload(p api.Payloader, event models.HookEventType, meta string case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: return getDingtalkIssuesPayload(p.(*api.IssuePayload)) case models.HookEventIssueComment, models.HookEventPullRequestComment: - return getDingtalkIssueCommentPayload(p.(*api.IssueCommentPayload)) + pl, ok := p.(*api.IssueCommentPayload) + if ok { + return getDingtalkIssueCommentPayload(pl) + } + return getDingtalkPullRequestPayload(p.(*api.PullRequestPayload)) case models.HookEventPush: return getDingtalkPushPayload(p.(*api.PushPayload)) case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, diff --git a/modules/webhook/discord.go b/modules/webhook/discord.go index e455a102bd..761129d8d9 100644 --- a/modules/webhook/discord.go +++ b/modules/webhook/discord.go @@ -408,7 +408,11 @@ func GetDiscordPayload(p api.Payloader, event models.HookEventType, meta string) case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: return getDiscordIssuesPayload(p.(*api.IssuePayload), discord) case models.HookEventIssueComment, models.HookEventPullRequestComment: - return getDiscordIssueCommentPayload(p.(*api.IssueCommentPayload), discord) + pl, ok := p.(*api.IssueCommentPayload) + if ok { + return getDiscordIssueCommentPayload(pl, discord) + } + return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), discord) case models.HookEventPush: return getDiscordPushPayload(p.(*api.PushPayload), discord) case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, diff --git a/modules/webhook/feishu.go b/modules/webhook/feishu.go index 57eb909c48..4beda9014c 100644 --- a/modules/webhook/feishu.go +++ b/modules/webhook/feishu.go @@ -183,13 +183,17 @@ func GetFeishuPayload(p api.Payloader, event models.HookEventType, meta string) return getFeishuForkPayload(p.(*api.ForkPayload)) case models.HookEventIssues: return getFeishuIssuesPayload(p.(*api.IssuePayload)) - case models.HookEventIssueComment: - return getFeishuIssueCommentPayload(p.(*api.IssueCommentPayload)) + case models.HookEventIssueComment, models.HookEventPullRequestComment: + pl, ok := p.(*api.IssueCommentPayload) + if ok { + return getFeishuIssueCommentPayload(pl) + } + return getFeishuPullRequestPayload(p.(*api.PullRequestPayload)) case models.HookEventPush: return getFeishuPushPayload(p.(*api.PushPayload)) case models.HookEventPullRequest: return getFeishuPullRequestPayload(p.(*api.PullRequestPayload)) - case models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewRejected, models.HookEventPullRequestComment: + case models.HookEventPullRequestReviewApproved, models.HookEventPullRequestReviewRejected: return getFeishuPullRequestApprovalPayload(p.(*api.PullRequestPayload), event) case models.HookEventRepository: return getFeishuRepositoryPayload(p.(*api.RepositoryPayload)) diff --git a/modules/webhook/general.go b/modules/webhook/general.go index bc9a10b529..ec247a2410 100644 --- a/modules/webhook/general.go +++ b/modules/webhook/general.go @@ -119,6 +119,8 @@ func getPullRequestPayloadInfo(p *api.PullRequestPayload, linkFormatter linkForm linkFormatter(mileStoneLink, p.PullRequest.Milestone.Title), titleLink) case api.HookIssueDemilestoned: text = fmt.Sprintf("[%s] Pull request milestone cleared: %s", repoLink, titleLink) + case api.HookIssueReviewed: + text = fmt.Sprintf("[%s] Pull request reviewed: %s", repoLink, titleLink) } if withSender { text += fmt.Sprintf(" by %s", linkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)) diff --git a/modules/webhook/matrix.go b/modules/webhook/matrix.go index bf72e6e340..68c65623f7 100644 --- a/modules/webhook/matrix.go +++ b/modules/webhook/matrix.go @@ -230,7 +230,11 @@ func GetMatrixPayload(p api.Payloader, event models.HookEventType, meta string) case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: return getMatrixIssuesPayload(p.(*api.IssuePayload), matrix) case models.HookEventIssueComment, models.HookEventPullRequestComment: - return getMatrixIssueCommentPayload(p.(*api.IssueCommentPayload), matrix) + pl, ok := p.(*api.IssueCommentPayload) + if ok { + return getMatrixIssueCommentPayload(pl, matrix) + } + return getMatrixPullRequestPayload(p.(*api.PullRequestPayload), matrix) case models.HookEventPush: return getMatrixPushPayload(p.(*api.PushPayload), matrix) case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, diff --git a/modules/webhook/msteams.go b/modules/webhook/msteams.go index a0925010d6..e7ec396f29 100644 --- a/modules/webhook/msteams.go +++ b/modules/webhook/msteams.go @@ -558,7 +558,11 @@ func GetMSTeamsPayload(p api.Payloader, event models.HookEventType, meta string) case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: return getMSTeamsIssuesPayload(p.(*api.IssuePayload)) case models.HookEventIssueComment, models.HookEventPullRequestComment: - return getMSTeamsIssueCommentPayload(p.(*api.IssueCommentPayload)) + pl, ok := p.(*api.IssueCommentPayload) + if ok { + return getMSTeamsIssueCommentPayload(pl) + } + return getMSTeamsPullRequestPayload(p.(*api.PullRequestPayload)) case models.HookEventPush: return getMSTeamsPushPayload(p.(*api.PushPayload)) case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, diff --git a/modules/webhook/slack.go b/modules/webhook/slack.go index 1e9413efd6..4177bd1250 100644 --- a/modules/webhook/slack.go +++ b/modules/webhook/slack.go @@ -321,7 +321,11 @@ func GetSlackPayload(p api.Payloader, event models.HookEventType, meta string) ( case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: return getSlackIssuesPayload(p.(*api.IssuePayload), slack) case models.HookEventIssueComment, models.HookEventPullRequestComment: - return getSlackIssueCommentPayload(p.(*api.IssueCommentPayload), slack) + pl, ok := p.(*api.IssueCommentPayload) + if ok { + return getSlackIssueCommentPayload(pl, slack) + } + return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack) case models.HookEventPush: return getSlackPushPayload(p.(*api.PushPayload), slack) case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, diff --git a/modules/webhook/telegram.go b/modules/webhook/telegram.go index cf096e2c66..6d2f804a70 100644 --- a/modules/webhook/telegram.go +++ b/modules/webhook/telegram.go @@ -206,7 +206,11 @@ func GetTelegramPayload(p api.Payloader, event models.HookEventType, meta string case models.HookEventIssues, models.HookEventIssueAssign, models.HookEventIssueLabel, models.HookEventIssueMilestone: return getTelegramIssuesPayload(p.(*api.IssuePayload)) case models.HookEventIssueComment, models.HookEventPullRequestComment: - return getTelegramIssueCommentPayload(p.(*api.IssueCommentPayload)) + pl, ok := p.(*api.IssueCommentPayload) + if ok { + return getTelegramIssueCommentPayload(pl) + } + return getTelegramPullRequestPayload(p.(*api.PullRequestPayload)) case models.HookEventPush: return getTelegramPushPayload(p.(*api.PushPayload)) case models.HookEventPullRequest, models.HookEventPullRequestAssign, models.HookEventPullRequestLabel, diff --git a/options/locale/TRANSLATORS b/options/locale/TRANSLATORS index 98a47a6c53..3884207f0a 100644 --- a/options/locale/TRANSLATORS +++ b/options/locale/TRANSLATORS @@ -25,6 +25,7 @@ Damaris Padieu Daniel Speichert David Yzaguirre Dmitriy Nogay +Emanuel Angelo Enrico Testori hypertesto AT gmail DOT com Ezequiel Gonzalez Rial Gabriel Dugny diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index f6c9b43ee5..285cec4c21 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1647,6 +1647,7 @@ diff.review.placeholder = Review comment diff.review.comment = Comment diff.review.approve = Approve diff.review.reject = Request changes +diff.committed_by = committed by releases.desc = Track project versions and downloads. release.releases = Releases @@ -1842,12 +1843,12 @@ dashboard.operation_switch = Switch dashboard.operation_run = Run dashboard.clean_unbind_oauth = Clean unbound OAuth connections dashboard.clean_unbind_oauth_success = All unbound OAuth connections have been deleted. -dashboard.task.started=Started Task: %s -dashboard.task.process=Task: %s -dashboard.task.cancelled=Task: %s cancelled: %[3]s -dashboard.task.error=Error in Task: %s: %[3]s -dashboard.task.finished=Task: %s started by %s has finished -dashboard.task.unknown=Unknown task: %s +dashboard.task.started=Started Task: %[1]s +dashboard.task.process=Task: %[1]s +dashboard.task.cancelled=Task: %[1]s cancelled: %[3]s +dashboard.task.error=Error in Task: %[1]s: %[3]s +dashboard.task.finished=Task: %[1]s started by %[2]s has finished +dashboard.task.unknown=Unknown task: %[1]s dashboard.cron.started=Started Cron: %[1]s dashboard.cron.process=Cron: %[1]s dashboard.cron.cancelled=Cron: %s cancelled: %[3]s @@ -1872,7 +1873,6 @@ dashboard.resync_all_sshkeys.desc = (Not needed for the built-in SSH server.) dashboard.resync_all_hooks = Resynchronize pre-receive, update and post-receive hooks of all repositories. dashboard.reinit_missing_repos = Reinitialize all missing Git repositories for which records exist dashboard.sync_external_users = Synchronize external user data -dashboard.git_fsck = Execute health checks on all repositories dashboard.server_uptime = Server Uptime dashboard.current_goroutine = Current Goroutines dashboard.current_memory_usage = Current Memory Usage diff --git a/package-lock.json b/package-lock.json index 71183fed43..87e6991dd9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4007,6 +4007,11 @@ "es6-symbol": "^3.1.1" } }, + "escape-goat": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz", + "integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -14852,6 +14857,28 @@ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" }, + "workbox-core": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-5.1.3.tgz", + "integrity": "sha512-TFSIPxxciX9sFaj0FDiohBeIKpwMcCyNduydi9i3LChItcndDS6TJpErxybv8aBWeCMraXt33TWtF6kKuIObNw==" + }, + "workbox-routing": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-5.1.3.tgz", + "integrity": "sha512-F+sAp9Iy3lVl3BEG+pzXWVq4AftzjiFpHDaZ4Kf4vLoBoKQE0hIHet4zE5DpHqYdyw+Udhp4wrfHamX6PN6z1Q==", + "requires": { + "workbox-core": "^5.1.3" + } + }, + "workbox-strategies": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-5.1.3.tgz", + "integrity": "sha512-wiXHfmOKnWABeIVW+/ye0e00+2CcS5y7SIj2f9zcdy2ZLEbcOf7B+yOl5OrWpBGlTUwRjIYhV++ZqiKm3Dc+8w==", + "requires": { + "workbox-core": "^5.1.3", + "workbox-routing": "^5.1.3" + } + }, "worker-farm": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", diff --git a/package.json b/package.json index 7fb8246af2..fe2c6193cc 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "cssnano": "4.1.10", "domino": "2.1.5", "dropzone": "5.7.0", + "escape-goat": "3.0.0", "fast-glob": "3.2.2", "file-loader": "6.0.0", "fomantic-ui": "2.8.4", @@ -47,6 +48,8 @@ "webpack": "4.43.0", "webpack-cli": "3.3.11", "webpack-fix-style-only-entries": "0.4.0", + "workbox-routing": "5.1.3", + "workbox-strategies": "5.1.3", "worker-loader": "2.0.0" }, "devDependencies": { diff --git a/routers/admin/admin.go b/routers/admin/admin.go index 7595f4929d..e48e416258 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -153,8 +153,11 @@ func DashboardPost(ctx *context.Context, form auth.AdminDashboardForm) { ctx.Flash.Error(ctx.Tr("admin.dashboard.task.unknown", form.Op)) } } - - ctx.Redirect(setting.AppSubURL + "/admin") + if form.From == "monitor" { + ctx.Redirect(setting.AppSubURL + "/admin/monitor") + } else { + ctx.Redirect(setting.AppSubURL + "/admin") + } } // SendTestMail send test mail to confirm mail service is OK @@ -331,7 +334,7 @@ func MonitorCancel(ctx *context.Context) { pid := ctx.ParamsInt64("pid") process.GetManager().Cancel(pid) ctx.JSON(200, map[string]interface{}{ - "redirect": ctx.Repo.RepoLink + "/admin/monitor", + "redirect": setting.AppSubURL + "/admin/monitor", }) } diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 0d62b751cc..9253b5b2c4 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -184,14 +184,14 @@ func reqToken() macaron.Handler { ctx.RequireCSRF() return } - ctx.Context.Error(http.StatusUnauthorized) + ctx.Error(http.StatusUnauthorized, "reqToken", "token is required") } } func reqBasicAuth() macaron.Handler { return func(ctx *context.APIContext) { if !ctx.Context.IsBasicAuth { - ctx.Context.Error(http.StatusUnauthorized) + ctx.Error(http.StatusUnauthorized, "reqBasicAuth", "basic auth required") return } ctx.CheckForOTP() @@ -200,9 +200,9 @@ func reqBasicAuth() macaron.Handler { // reqSiteAdmin user should be the site admin func reqSiteAdmin() macaron.Handler { - return func(ctx *context.Context) { + return func(ctx *context.APIContext) { if !ctx.IsUserSiteAdmin() { - ctx.Error(http.StatusForbidden) + ctx.Error(http.StatusForbidden, "reqSiteAdmin", "user should be the site admin") return } } @@ -210,9 +210,9 @@ func reqSiteAdmin() macaron.Handler { // reqOwner user should be the owner of the repo or site admin. func reqOwner() macaron.Handler { - return func(ctx *context.Context) { + return func(ctx *context.APIContext) { if !ctx.IsUserRepoOwner() && !ctx.IsUserSiteAdmin() { - ctx.Error(http.StatusForbidden) + ctx.Error(http.StatusForbidden, "reqOwner", "user should be the owner of the repo") return } } @@ -220,9 +220,9 @@ func reqOwner() macaron.Handler { // reqAdmin user should be an owner or a collaborator with admin write of a repository, or site admin func reqAdmin() macaron.Handler { - return func(ctx *context.Context) { + return func(ctx *context.APIContext) { if !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { - ctx.Error(http.StatusForbidden) + ctx.Error(http.StatusForbidden, "reqAdmin", "user should be an owner or a collaborator with admin write of a repository") return } } @@ -230,9 +230,9 @@ func reqAdmin() macaron.Handler { // reqRepoWriter user should have a permission to write to a repo, or be a site admin func reqRepoWriter(unitTypes ...models.UnitType) macaron.Handler { - return func(ctx *context.Context) { + return func(ctx *context.APIContext) { if !ctx.IsUserRepoWriter(unitTypes) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { - ctx.Error(http.StatusForbidden) + ctx.Error(http.StatusForbidden, "reqRepoWriter", "user should have a permission to write to a repo") return } } @@ -240,9 +240,9 @@ func reqRepoWriter(unitTypes ...models.UnitType) macaron.Handler { // reqRepoReader user should have specific read permission or be a repo admin or a site admin func reqRepoReader(unitType models.UnitType) macaron.Handler { - return func(ctx *context.Context) { + return func(ctx *context.APIContext) { if !ctx.IsUserRepoReaderSpecific(unitType) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() { - ctx.Error(http.StatusForbidden) + ctx.Error(http.StatusForbidden, "reqRepoReader", "user should have specific read permission or be a repo admin or a site admin") return } } @@ -250,9 +250,9 @@ func reqRepoReader(unitType models.UnitType) macaron.Handler { // reqAnyRepoReader user should have any permission to read repository or permissions of site admin func reqAnyRepoReader() macaron.Handler { - return func(ctx *context.Context) { + return func(ctx *context.APIContext) { if !ctx.IsUserRepoReaderAny() && !ctx.IsUserSiteAdmin() { - ctx.Error(http.StatusForbidden) + ctx.Error(http.StatusForbidden, "reqAnyRepoReader", "user should have any permission to read repository or permissions of site admin") return } } @@ -397,7 +397,7 @@ func orgAssignment(args ...bool) macaron.Handler { if assignTeam { ctx.Org.Team, err = models.GetTeamByID(ctx.ParamsInt64(":teamid")) if err != nil { - if models.IsErrUserNotExist(err) { + if models.IsErrTeamNotExist(err) { ctx.NotFound() } else { ctx.Error(http.StatusInternalServerError, "GetTeamById", err) @@ -495,7 +495,6 @@ func mustNotBeArchived(ctx *context.APIContext) { } // RegisterRoutes registers all v1 APIs routes to web application. -// FIXME: custom form error response func RegisterRoutes(m *macaron.Macaron) { bind := binding.Bind @@ -628,7 +627,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/:username/:reponame", func() { m.Combo("").Get(reqAnyRepoReader(), repo.Get). Delete(reqToken(), reqOwner(), repo.Delete). - Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), context.RepoRef(), repo.Edit) + Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), context.RepoRefForAPI(), repo.Edit) m.Post("/transfer", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer) m.Combo("/notifications"). Get(reqToken(), notify.ListRepoNotifications). @@ -640,7 +639,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Combo("").Get(repo.GetHook). Patch(bind(api.EditHookOption{}), repo.EditHook). Delete(repo.DeleteHook) - m.Post("/tests", context.RepoRef(), repo.TestHook) + m.Post("/tests", context.RepoRefForAPI(), repo.TestHook) }) m.Group("/git", func() { m.Combo("").Get(repo.ListGitHooks) @@ -657,14 +656,14 @@ func RegisterRoutes(m *macaron.Macaron) { Put(reqAdmin(), bind(api.AddCollaboratorOption{}), repo.AddCollaborator). Delete(reqAdmin(), repo.DeleteCollaborator) }, reqToken()) - m.Get("/raw/*", context.RepoRefByType(context.RepoRefAny), reqRepoReader(models.UnitTypeCode), repo.GetRawFile) + m.Get("/raw/*", context.RepoRefForAPI(), reqRepoReader(models.UnitTypeCode), repo.GetRawFile) m.Get("/archive/*", reqRepoReader(models.UnitTypeCode), repo.GetArchive) m.Combo("/forks").Get(repo.ListForks). Post(reqToken(), reqRepoReader(models.UnitTypeCode), bind(api.CreateForkOption{}), repo.CreateFork) m.Group("/branches", func() { m.Get("", repo.ListBranches) - m.Get("/*", context.RepoRefByType(context.RepoRefBranch), repo.GetBranch) - m.Delete("/*", reqRepoWriter(models.UnitTypeCode), context.RepoRefByType(context.RepoRefBranch), repo.DeleteBranch) + m.Get("/*", repo.GetBranch) + m.Delete("/*", context.ReferencesGitRepo(false), reqRepoWriter(models.UnitTypeCode), repo.DeleteBranch) }, reqRepoReader(models.UnitTypeCode)) m.Group("/branch_protections", func() { m.Get("", repo.ListBranchProtections) @@ -785,7 +784,7 @@ func RegisterRoutes(m *macaron.Macaron) { }) }, reqRepoReader(models.UnitTypeReleases)) m.Post("/mirror-sync", reqToken(), reqRepoWriter(models.UnitTypeCode), repo.MirrorSync) - m.Get("/editorconfig/:filename", context.RepoRef(), reqRepoReader(models.UnitTypeCode), repo.GetEditorconfig) + m.Get("/editorconfig/:filename", context.RepoRefForAPI(), reqRepoReader(models.UnitTypeCode), repo.GetEditorconfig) m.Group("/pulls", func() { m.Combo("").Get(bind(api.ListPullRequestsOptions{}), repo.ListPullRequests). Post(reqToken(), mustNotBeArchived, bind(api.CreatePullRequestOption{}), repo.CreatePullRequest) @@ -827,9 +826,9 @@ func RegisterRoutes(m *macaron.Macaron) { }) m.Get("/refs", repo.GetGitAllRefs) m.Get("/refs/*", repo.GetGitRefs) - m.Get("/trees/:sha", context.RepoRef(), repo.GetTree) - m.Get("/blobs/:sha", context.RepoRef(), repo.GetBlob) - m.Get("/tags/:sha", context.RepoRef(), repo.GetTag) + m.Get("/trees/:sha", context.RepoRefForAPI(), repo.GetTree) + m.Get("/blobs/:sha", context.RepoRefForAPI(), repo.GetBlob) + m.Get("/tags/:sha", context.RepoRefForAPI(), repo.GetTag) }, reqRepoReader(models.UnitTypeCode)) m.Group("/contents", func() { m.Get("", repo.GetContentsList) diff --git a/routers/api/v1/misc/markdown.go b/routers/api/v1/misc/markdown.go index 5a44db5e8b..a10c288df4 100644 --- a/routers/api/v1/misc/markdown.go +++ b/routers/api/v1/misc/markdown.go @@ -48,10 +48,12 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) { } switch form.Mode { + case "comment": + fallthrough case "gfm": md := []byte(form.Text) urlPrefix := form.Context - var meta map[string]string + meta := map[string]string{} if !strings.HasPrefix(setting.AppSubURL+"/", urlPrefix) { // check if urlPrefix is already set to a URL linkRegex, _ := xurls.StrictMatchingScheme("https?://") @@ -61,7 +63,15 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) { } } if ctx.Repo != nil && ctx.Repo.Repository != nil { - meta = ctx.Repo.Repository.ComposeMetas() + // "gfm" = Github Flavored Markdown - set this to render as a document + if form.Mode == "gfm" { + meta = ctx.Repo.Repository.ComposeDocumentMetas() + } else { + meta = ctx.Repo.Repository.ComposeMetas() + } + } + if form.Mode == "gfm" { + meta["mode"] = "document" } if form.Wiki { _, err := ctx.Write([]byte(markdown.RenderWiki(md, urlPrefix, meta))) diff --git a/routers/api/v1/misc/markdown_test.go b/routers/api/v1/misc/markdown_test.go index 264a6010f9..6c81ec8eb4 100644 --- a/routers/api/v1/misc/markdown_test.go +++ b/routers/api/v1/misc/markdown_test.go @@ -94,7 +94,7 @@ Here are some links to the most important topics. You can find the full list of

Wine Staging on website wine-staging.com.

Here are some links to the most important topics. You can find the full list of pages at the sidebar.

-

Configuration
+

Configuration images/icon-bug.png

`, // Guard wiki sidebar: special syntax diff --git a/routers/api/v1/notify/repo.go b/routers/api/v1/notify/repo.go index 10c00c5467..a37dfd8b43 100644 --- a/routers/api/v1/notify/repo.go +++ b/routers/api/v1/notify/repo.go @@ -11,9 +11,37 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/routers/api/v1/utils" ) +func statusStringToNotificationStatus(status string) models.NotificationStatus { + switch strings.ToLower(strings.TrimSpace(status)) { + case "unread": + return models.NotificationStatusUnread + case "read": + return models.NotificationStatusRead + case "pinned": + return models.NotificationStatusPinned + default: + return 0 + } +} + +func statusStringsToNotificationStatuses(statuses []string, defaultStatuses []string) []models.NotificationStatus { + if len(statuses) == 0 { + statuses = defaultStatuses + } + results := make([]models.NotificationStatus, 0, len(statuses)) + for _, status := range statuses { + notificationStatus := statusStringToNotificationStatus(status) + if notificationStatus > 0 { + results = append(results, notificationStatus) + } + } + return results +} + // ListRepoNotifications list users's notification threads on a specific repo func ListRepoNotifications(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/notifications notification notifyGetRepoList @@ -39,6 +67,14 @@ func ListRepoNotifications(ctx *context.APIContext) { // description: If true, show notifications marked as read. Default value is false // type: string // required: false + // - name: status-types + // in: query + // description: "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned" + // type: array + // collectionFormat: multi + // items: + // type: string + // required: false // - name: since // in: query // description: Only show notifications updated after the given time. This is a timestamp in RFC 3339 format @@ -65,7 +101,7 @@ func ListRepoNotifications(ctx *context.APIContext) { before, since, err := utils.GetQueryBeforeSince(ctx) if err != nil { - ctx.InternalServerError(err) + ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } opts := models.FindNotificationOptions{ @@ -75,9 +111,10 @@ func ListRepoNotifications(ctx *context.APIContext) { UpdatedBeforeUnix: before, UpdatedAfterUnix: since, } - qAll := strings.Trim(ctx.Query("all"), " ") - if qAll != "true" { - opts.Status = models.NotificationStatusUnread + + if !ctx.QueryBool("all") { + statuses := ctx.QueryStrings("status-types") + opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread", "pinned"}) } nl, err := models.GetNotifications(opts) if err != nil { @@ -97,7 +134,7 @@ func ListRepoNotifications(ctx *context.APIContext) { func ReadRepoNotifications(ctx *context.APIContext) { // swagger:operation PUT /repos/{owner}/{repo}/notifications notification notifyReadRepoList // --- - // summary: Mark notification threads as read on a specific repo + // summary: Mark notification threads as read, pinned or unread on a specific repo // consumes: // - application/json // produces: @@ -113,6 +150,24 @@ func ReadRepoNotifications(ctx *context.APIContext) { // description: name of the repo // type: string // required: true + // - name: all + // in: query + // description: If true, mark all notifications on this repo. Default value is false + // type: string + // required: false + // - name: status-types + // in: query + // description: "Mark notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread." + // type: array + // collectionFormat: multi + // items: + // type: string + // required: false + // - name: to-status + // in: query + // description: Status to mark notifications as. Defaults to read. + // type: string + // required: false // - name: last_read_at // in: query // description: Describes the last point that notifications were checked. Anything updated since this time will not be updated. @@ -135,11 +190,17 @@ func ReadRepoNotifications(ctx *context.APIContext) { lastRead = tmpLastRead.Unix() } } + opts := models.FindNotificationOptions{ UserID: ctx.User.ID, RepoID: ctx.Repo.Repository.ID, UpdatedBeforeUnix: lastRead, - Status: models.NotificationStatusUnread, + } + + if !ctx.QueryBool("all") { + statuses := ctx.QueryStrings("status-types") + opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread"}) + log.Error("%v", opts.Status) } nl, err := models.GetNotifications(opts) if err != nil { @@ -147,8 +208,13 @@ func ReadRepoNotifications(ctx *context.APIContext) { return } + targetStatus := statusStringToNotificationStatus(ctx.Query("to-status")) + if targetStatus == 0 { + targetStatus = models.NotificationStatusRead + } + for _, n := range nl { - err := models.SetNotificationStatus(n.ID, ctx.User, models.NotificationStatusRead) + err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/notify/threads.go b/routers/api/v1/notify/threads.go index d0119e9938..86ae2dca31 100644 --- a/routers/api/v1/notify/threads.go +++ b/routers/api/v1/notify/threads.go @@ -62,6 +62,12 @@ func ReadThread(ctx *context.APIContext) { // description: id of notification thread // type: string // required: true + // - name: to-status + // in: query + // description: Status to mark notifications as + // type: string + // default: read + // required: false // responses: // "205": // "$ref": "#/responses/empty" @@ -75,7 +81,12 @@ func ReadThread(ctx *context.APIContext) { return } - err := models.SetNotificationStatus(n.ID, ctx.User, models.NotificationStatusRead) + targetStatus := statusStringToNotificationStatus(ctx.Query("to-status")) + if targetStatus == 0 { + targetStatus = models.NotificationStatusRead + } + + err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/notify/user.go b/routers/api/v1/notify/user.go index 7f731e25d4..57127c96fe 100644 --- a/routers/api/v1/notify/user.go +++ b/routers/api/v1/notify/user.go @@ -29,6 +29,14 @@ func ListNotifications(ctx *context.APIContext) { // description: If true, show notifications marked as read. Default value is false // type: string // required: false + // - name: status-types + // in: query + // description: "Show notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread & pinned." + // type: array + // collectionFormat: multi + // items: + // type: string + // required: false // - name: since // in: query // description: Only show notifications updated after the given time. This is a timestamp in RFC 3339 format @@ -55,7 +63,7 @@ func ListNotifications(ctx *context.APIContext) { before, since, err := utils.GetQueryBeforeSince(ctx) if err != nil { - ctx.InternalServerError(err) + ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } opts := models.FindNotificationOptions{ @@ -64,9 +72,9 @@ func ListNotifications(ctx *context.APIContext) { UpdatedBeforeUnix: before, UpdatedAfterUnix: since, } - qAll := strings.Trim(ctx.Query("all"), " ") - if qAll != "true" { - opts.Status = models.NotificationStatusUnread + if !ctx.QueryBool("all") { + statuses := ctx.QueryStrings("status-types") + opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread", "pinned"}) } nl, err := models.GetNotifications(opts) if err != nil { @@ -82,11 +90,11 @@ func ListNotifications(ctx *context.APIContext) { ctx.JSON(http.StatusOK, nl.APIFormat()) } -// ReadNotifications mark notification threads as read +// ReadNotifications mark notification threads as read, unread, or pinned func ReadNotifications(ctx *context.APIContext) { // swagger:operation PUT /notifications notification notifyReadList // --- - // summary: Mark notification threads as read + // summary: Mark notification threads as read, pinned or unread // consumes: // - application/json // produces: @@ -98,6 +106,24 @@ func ReadNotifications(ctx *context.APIContext) { // type: string // format: date-time // required: false + // - name: all + // in: query + // description: If true, mark all notifications on this repo. Default value is false + // type: string + // required: false + // - name: status-types + // in: query + // description: "Mark notifications with the provided status types. Options are: unread, read and/or pinned. Defaults to unread." + // type: array + // collectionFormat: multi + // items: + // type: string + // required: false + // - name: to-status + // in: query + // description: Status to mark notifications as, Defaults to read. + // type: string + // required: false // responses: // "205": // "$ref": "#/responses/empty" @@ -117,7 +143,10 @@ func ReadNotifications(ctx *context.APIContext) { opts := models.FindNotificationOptions{ UserID: ctx.User.ID, UpdatedBeforeUnix: lastRead, - Status: models.NotificationStatusUnread, + } + if !ctx.QueryBool("all") { + statuses := ctx.QueryStrings("status-types") + opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread"}) } nl, err := models.GetNotifications(opts) if err != nil { @@ -125,8 +154,13 @@ func ReadNotifications(ctx *context.APIContext) { return } + targetStatus := statusStringToNotificationStatus(ctx.Query("to-status")) + if targetStatus == 0 { + targetStatus = models.NotificationStatusRead + } + for _, n := range nl { - err := models.SetNotificationStatus(n.ID, ctx.User, models.NotificationStatusRead) + err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index b79761c875..9c671c8d1a 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -84,7 +84,7 @@ func ListUserOrgs(ctx *context.APIContext) { if ctx.Written() { return } - listUserOrgs(ctx, u, ctx.User.IsAdmin) + listUserOrgs(ctx, u, ctx.User != nil && (ctx.User.IsAdmin || ctx.User.ID == u.ID)) } // GetAll return list of all public organizations diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 57c74d7dab..74b8bbcd87 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -45,15 +45,12 @@ func GetBranch(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/Branch" + // "404": + // "$ref": "#/responses/notFound" - if ctx.Repo.TreePath != "" { - // if TreePath != "", then URL contained extra slashes - // (i.e. "master/subbranch" instead of "master"), so branch does - // not exist - ctx.NotFound() - return - } - branch, err := repo_module.GetBranch(ctx.Repo.Repository, ctx.Repo.BranchName) + branchName := ctx.Params("*") + + branch, err := repo_module.GetBranch(ctx.Repo.Repository, branchName) if err != nil { if git.IsErrBranchNotExist(err) { ctx.NotFound(err) @@ -69,7 +66,7 @@ func GetBranch(ctx *context.APIContext) { return } - branchProtection, err := ctx.Repo.Repository.GetBranchProtection(ctx.Repo.BranchName) + branchProtection, err := ctx.Repo.Repository.GetBranchProtection(branchName) if err != nil { ctx.Error(http.StatusInternalServerError, "GetBranchProtection", err) return @@ -112,21 +109,17 @@ func DeleteBranch(ctx *context.APIContext) { // "$ref": "#/responses/empty" // "403": // "$ref": "#/responses/error" + // "404": + // "$ref": "#/responses/notFound" - if ctx.Repo.TreePath != "" { - // if TreePath != "", then URL contained extra slashes - // (i.e. "master/subbranch" instead of "master"), so branch does - // not exist - ctx.NotFound() - return - } + branchName := ctx.Params("*") - if ctx.Repo.Repository.DefaultBranch == ctx.Repo.BranchName { + if ctx.Repo.Repository.DefaultBranch == branchName { ctx.Error(http.StatusForbidden, "DefaultBranch", fmt.Errorf("can not delete default branch")) return } - isProtected, err := ctx.Repo.Repository.IsProtectedBranch(ctx.Repo.BranchName, ctx.User) + isProtected, err := ctx.Repo.Repository.IsProtectedBranch(branchName, ctx.User) if err != nil { ctx.InternalServerError(err) return @@ -136,7 +129,7 @@ func DeleteBranch(ctx *context.APIContext) { return } - branch, err := repo_module.GetBranch(ctx.Repo.Repository, ctx.Repo.BranchName) + branch, err := repo_module.GetBranch(ctx.Repo.Repository, branchName) if err != nil { if git.IsErrBranchNotExist(err) { ctx.NotFound(err) @@ -152,7 +145,7 @@ func DeleteBranch(ctx *context.APIContext) { return } - if err := ctx.Repo.GitRepo.DeleteBranch(ctx.Repo.BranchName, git.DeleteBranchOptions{ + if err := ctx.Repo.GitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{ Force: true, }); err != nil { ctx.Error(http.StatusInternalServerError, "DeleteBranch", err) @@ -164,7 +157,7 @@ func DeleteBranch(ctx *context.APIContext) { ctx.Repo.Repository, ctx.Repo.BranchName, repofiles.PushUpdateOptions{ - RefFullName: git.BranchPrefix + ctx.Repo.BranchName, + RefFullName: git.BranchPrefix + branchName, OldCommitID: c.ID.String(), NewCommitID: git.EmptySHA, PusherID: ctx.User.ID, @@ -175,7 +168,7 @@ func DeleteBranch(ctx *context.APIContext) { log.Error("Update: %v", err) } - if err := ctx.Repo.Repository.AddDeletedBranch(ctx.Repo.BranchName, c.ID.String(), ctx.User.ID); err != nil { + if err := ctx.Repo.Repository.AddDeletedBranch(branchName, c.ID.String(), ctx.User.ID); err != nil { log.Warn("AddDeletedBranch: %v", err) } diff --git a/routers/api/v1/repo/commits.go b/routers/api/v1/repo/commits.go index f9bc2efa9a..5359079eff 100644 --- a/routers/api/v1/repo/commits.go +++ b/routers/api/v1/repo/commits.go @@ -296,7 +296,7 @@ func toCommit(ctx *context.APIContext, repo *models.Repository, commit *git.Comm }, Date: commit.Committer.When.Format(time.RFC3339), }, - Message: commit.Summary(), + Message: commit.Message(), Tree: &api.CommitMeta{ URL: repo.APIURL() + "/git/trees/" + commit.ID.String(), SHA: commit.ID.String(), diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index 02a7de9b58..9754bb7966 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -7,6 +7,7 @@ package repo import ( "encoding/base64" + "fmt" "net/http" "time" @@ -198,6 +199,16 @@ func CreateFile(ctx *context.APIContext, apiOpts api.CreateFileOptions) { // responses: // "201": // "$ref": "#/responses/FileResponse" + // "403": + // "$ref": "#/responses/error" + // "404": + // "$ref": "#/responses/notFound" + // "422": + // "$ref": "#/responses/error" + + if ctx.Repo.Repository.IsEmpty { + ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty")) + } if apiOpts.BranchName == "" { apiOpts.BranchName = ctx.Repo.Repository.DefaultBranch @@ -235,7 +246,7 @@ func CreateFile(ctx *context.APIContext, apiOpts api.CreateFileOptions) { } if fileResponse, err := createOrUpdateFile(ctx, opts); err != nil { - ctx.Error(http.StatusInternalServerError, "CreateFile", err) + handleCreateOrUpdateFileError(ctx, err) } else { ctx.JSON(http.StatusCreated, fileResponse) } @@ -274,6 +285,16 @@ func UpdateFile(ctx *context.APIContext, apiOpts api.UpdateFileOptions) { // responses: // "200": // "$ref": "#/responses/FileResponse" + // "403": + // "$ref": "#/responses/error" + // "404": + // "$ref": "#/responses/notFound" + // "422": + // "$ref": "#/responses/error" + + if ctx.Repo.Repository.IsEmpty { + ctx.Error(http.StatusUnprocessableEntity, "RepoIsEmpty", fmt.Errorf("repo is empty")) + } if apiOpts.BranchName == "" { apiOpts.BranchName = ctx.Repo.Repository.DefaultBranch @@ -313,12 +334,30 @@ func UpdateFile(ctx *context.APIContext, apiOpts api.UpdateFileOptions) { } if fileResponse, err := createOrUpdateFile(ctx, opts); err != nil { - ctx.Error(http.StatusInternalServerError, "UpdateFile", err) + handleCreateOrUpdateFileError(ctx, err) } else { ctx.JSON(http.StatusOK, fileResponse) } } +func handleCreateOrUpdateFileError(ctx *context.APIContext, err error) { + if models.IsErrUserCannotCommit(err) || models.IsErrFilePathProtected(err) { + ctx.Error(http.StatusForbidden, "Access", err) + return + } + if models.IsErrBranchAlreadyExists(err) || models.IsErrFilenameInvalid(err) || models.IsErrSHADoesNotMatch(err) || + models.IsErrFilePathInvalid(err) || models.IsErrRepoFileAlreadyExists(err) { + ctx.Error(http.StatusUnprocessableEntity, "Invalid", err) + return + } + if git.IsErrBranchNotExist(err) { + ctx.Error(http.StatusNotFound, "BranchDoesNotExist", err) + return + } + + ctx.Error(http.StatusInternalServerError, "UpdateFile", err) +} + // Called from both CreateFile or UpdateFile to handle both func createOrUpdateFile(ctx *context.APIContext, opts *repofiles.UpdateRepoFileOptions) (*api.FileResponse, error) { if !canWriteFiles(ctx.Repo) { diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index d51e80e18c..062ecc74d0 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -691,7 +691,7 @@ func UpdateIssueDeadline(ctx *context.APIContext, form api.EditDeadlineOption) { var deadline time.Time if form.Deadline != nil && !form.Deadline.IsZero() { deadline = time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(), - 23, 59, 59, 0, form.Deadline.Location()) + 23, 59, 59, 0, time.Local) deadlineUnix = timeutil.TimeStamp(deadline.Unix()) } diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index 6b7c2beac4..064a37bc14 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -56,7 +56,7 @@ func ListIssueComments(ctx *context.APIContext) { before, since, err := utils.GetQueryBeforeSince(ctx) if err != nil { - ctx.Error(http.StatusInternalServerError, "GetQueryBeforeSince", err) + ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) @@ -132,7 +132,7 @@ func ListRepoIssueComments(ctx *context.APIContext) { before, since, err := utils.GetQueryBeforeSince(ctx) if err != nil { - ctx.Error(http.StatusInternalServerError, "GetQueryBeforeSince", err) + ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go index 5e49ea4aae..584d11bb83 100644 --- a/routers/api/v1/repo/issue_reaction.go +++ b/routers/api/v1/repo/issue_reaction.go @@ -56,7 +56,11 @@ func GetIssueCommentReactions(ctx *context.APIContext) { return } - if !ctx.Repo.CanRead(models.UnitTypeIssues) { + if err := comment.LoadIssue(); err != nil { + ctx.Error(http.StatusInternalServerError, "comment.LoadIssue", err) + } + + if !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull) { ctx.Error(http.StatusForbidden, "GetIssueCommentReactions", errors.New("no permission to get reactions")) return } @@ -270,7 +274,7 @@ func GetIssueReactions(ctx *context.APIContext) { return } - if !ctx.Repo.CanRead(models.UnitTypeIssues) { + if !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull) { ctx.Error(http.StatusForbidden, "GetIssueReactions", errors.New("no permission to get reactions")) return } diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go index 19242d1fae..765bfc0b68 100644 --- a/routers/api/v1/repo/issue_tracked_time.go +++ b/routers/api/v1/repo/issue_tracked_time.go @@ -86,7 +86,7 @@ func ListTrackedTimes(ctx *context.APIContext) { } if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = utils.GetQueryBeforeSince(ctx); err != nil { - ctx.InternalServerError(err) + ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } @@ -491,7 +491,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) { var err error if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = utils.GetQueryBeforeSince(ctx); err != nil { - ctx.InternalServerError(err) + ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } @@ -554,7 +554,7 @@ func ListMyTrackedTimes(ctx *context.APIContext) { var err error if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = utils.GetQueryBeforeSince(ctx); err != nil { - ctx.InternalServerError(err) + ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index bddf4e48f7..ba5904424d 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -201,6 +201,12 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption // "422": // "$ref": "#/responses/validationError" + if form.Head == form.Base { + ctx.Error(http.StatusUnprocessableEntity, "BaseHeadSame", + "Invalid PullRequest: There are no changes between the head and the base") + return + } + var ( repo = ctx.Repo.Repository labelIDs []int64 @@ -382,6 +388,8 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { // "$ref": "#/responses/PullRequest" // "403": // "$ref": "#/responses/forbidden" + // "409": + // "$ref": "#/responses/error" // "412": // "$ref": "#/responses/error" // "422": @@ -508,6 +516,30 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { notification.NotifyIssueChangeStatus(ctx.User, issue, statusChangeComment, issue.IsClosed) } + // change pull target branch + if len(form.Base) != 0 && form.Base != pr.BaseBranch { + if !ctx.Repo.GitRepo.IsBranchExist(form.Base) { + ctx.Error(http.StatusNotFound, "NewBaseBranchNotExist", fmt.Errorf("new base '%s' not exist", form.Base)) + return + } + if err := pull_service.ChangeTargetBranch(pr, ctx.User, form.Base); err != nil { + if models.IsErrPullRequestAlreadyExists(err) { + ctx.Error(http.StatusConflict, "IsErrPullRequestAlreadyExists", err) + return + } else if models.IsErrIssueIsClosed(err) { + ctx.Error(http.StatusUnprocessableEntity, "IsErrIssueIsClosed", err) + return + } else if models.IsErrPullRequestHasMerged(err) { + ctx.Error(http.StatusConflict, "IsErrPullRequestHasMerged", err) + return + } else { + ctx.InternalServerError(err) + } + return + } + notification.NotifyPullRequestChangeTargetBranch(ctx.User, pr, form.Base) + } + // Refetch from database pr, err = models.GetPullRequestByIndex(ctx.Repo.Repository.ID, pr.Index) if err != nil { diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index a724ebcc37..8a2e3ed6a6 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -78,9 +78,9 @@ func Search(ctx *context.APIContext) { // in: query // description: include private repositories this user has access to (defaults to true) // type: boolean - // - name: onlyPrivate + // - name: is_private // in: query - // description: only include private repositories this user has access to (defaults to false) + // description: show only pubic, private or all repositories (defaults to all) // type: boolean // - name: template // in: query @@ -133,7 +133,6 @@ func Search(ctx *context.APIContext) { TopicOnly: ctx.QueryBool("topic"), Collaborate: util.OptionalBoolNone, Private: ctx.IsSigned && (ctx.Query("private") == "" || ctx.QueryBool("private")), - OnlyPrivate: ctx.IsSigned && ctx.QueryBool("onlyPrivate"), Template: util.OptionalBoolNone, StarredByID: ctx.QueryInt64("starredBy"), IncludeDescription: ctx.QueryBool("includeDesc"), @@ -169,6 +168,10 @@ func Search(ctx *context.APIContext) { opts.Archived = util.OptionalBoolOf(ctx.QueryBool("archived")) } + if ctx.Query("is_private") != "" { + opts.IsPrivate = util.OptionalBoolOf(ctx.QueryBool("is_private")) + } + var sortMode = ctx.Query("sort") if len(sortMode) > 0 { var sortOrder = ctx.Query("order") @@ -253,6 +256,12 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR return } + // reload repo from db to get a real state after creation + repo, err = models.GetRepositoryByID(repo.ID) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetRepositoryByID", err) + } + ctx.JSON(http.StatusCreated, repo.APIFormat(models.AccessModeOwner)) } diff --git a/routers/api/v1/repo/topic.go b/routers/api/v1/repo/topic.go index 530b92a10d..f256ab9422 100644 --- a/routers/api/v1/repo/topic.go +++ b/routers/api/v1/repo/topic.go @@ -275,12 +275,6 @@ func TopicSearch(ctx *context.APIContext) { kw := ctx.Query("q") listOptions := utils.GetListOptions(ctx) - if listOptions.Page < 1 { - listOptions.Page = 1 - } - if listOptions.PageSize < 1 { - listOptions.PageSize = 10 - } topics, err := models.FindTopics(&models.FindTopicOptions{ Keyword: kw, diff --git a/routers/api/v1/repo/transfer.go b/routers/api/v1/repo/transfer.go index 847028d106..b1271b7721 100644 --- a/routers/api/v1/repo/transfer.go +++ b/routers/api/v1/repo/transfer.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs" repo_service "code.gitea.io/gitea/services/repository" ) @@ -53,13 +54,21 @@ func Transfer(ctx *context.APIContext, opts api.TransferRepoOption) { newOwner, err := models.GetUserByName(opts.NewOwner) if err != nil { if models.IsErrUserNotExist(err) { - ctx.Error(http.StatusNotFound, "GetUserByName", err) + ctx.Error(http.StatusNotFound, "", "The new owner does not exist or cannot be found") return } ctx.InternalServerError(err) return } + if newOwner.Type == models.UserTypeOrganization { + if !ctx.User.IsAdmin && newOwner.Visibility == structs.VisibleTypePrivate && !newOwner.HasMemberWithUserID(ctx.User.ID) { + // The user shouldn't know about this organization + ctx.Error(http.StatusNotFound, "", "The new owner does not exist or cannot be found") + return + } + } + var teams []*models.Team if opts.TeamIDs != nil { if !newOwner.IsOrganization() { diff --git a/routers/api/v1/user/gpg_key.go b/routers/api/v1/user/gpg_key.go index a4f6d0e924..d5fed96df1 100644 --- a/routers/api/v1/user/gpg_key.go +++ b/routers/api/v1/user/gpg_key.go @@ -144,6 +144,8 @@ func CreateGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption) { // responses: // "201": // "$ref": "#/responses/GPGKey" + // "404": + // "$ref": "#/responses/notFound" // "422": // "$ref": "#/responses/validationError" @@ -169,6 +171,8 @@ func DeleteGPGKey(ctx *context.APIContext) { // "$ref": "#/responses/empty" // "403": // "$ref": "#/responses/forbidden" + // "404": + // "$ref": "#/responses/notFound" if err := models.DeleteGPGKey(ctx.User, ctx.ParamsInt64(":id")); err != nil { if models.IsErrGPGKeyAccessDenied(err) { @@ -186,9 +190,13 @@ func DeleteGPGKey(ctx *context.APIContext) { func HandleAddGPGKeyError(ctx *context.APIContext, err error) { switch { case models.IsErrGPGKeyAccessDenied(err): - ctx.Error(http.StatusUnprocessableEntity, "", "You do not have access to this GPG key") + ctx.Error(http.StatusUnprocessableEntity, "GPGKeyAccessDenied", "You do not have access to this GPG key") case models.IsErrGPGKeyIDAlreadyUsed(err): - ctx.Error(http.StatusUnprocessableEntity, "", "A key with the same id already exists") + ctx.Error(http.StatusUnprocessableEntity, "GPGKeyIDAlreadyUsed", "A key with the same id already exists") + case models.IsErrGPGKeyParsing(err): + ctx.Error(http.StatusUnprocessableEntity, "GPGKeyParsing", err) + case models.IsErrGPGNoEmailFound(err): + ctx.Error(http.StatusNotFound, "GPGNoEmailFound", err) default: ctx.Error(http.StatusInternalServerError, "AddGPGKey", err) } diff --git a/routers/api/v1/user/repo.go b/routers/api/v1/user/repo.go index 4024bf96cf..7d7a4514c5 100644 --- a/routers/api/v1/user/repo.go +++ b/routers/api/v1/user/repo.go @@ -6,6 +6,7 @@ package user import ( "net/http" + "strconv" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" @@ -15,10 +16,12 @@ import ( // listUserRepos - List the repositories owned by the given user. func listUserRepos(ctx *context.APIContext, u *models.User, private bool) { - repos, err := models.GetUserRepositories(&models.SearchRepoOptions{ + opts := utils.GetListOptions(ctx) + + repos, count, err := models.GetUserRepositories(&models.SearchRepoOptions{ Actor: u, Private: private, - ListOptions: utils.GetListOptions(ctx), + ListOptions: opts, }) if err != nil { ctx.Error(http.StatusInternalServerError, "GetUserRepositories", err) @@ -36,6 +39,9 @@ func listUserRepos(ctx *context.APIContext, u *models.User, private bool) { apiRepos = append(apiRepos, repos[i].APIFormat(access)) } } + + ctx.SetLinkHeader(int(count), opts.PageSize) + ctx.Header().Set("X-Total-Count", strconv.FormatInt(count, 10)) ctx.JSON(http.StatusOK, &apiRepos) } @@ -92,31 +98,37 @@ func ListMyRepos(ctx *context.APIContext) { // "200": // "$ref": "#/responses/RepositoryList" - ownRepos, err := models.GetUserRepositories(&models.SearchRepoOptions{ - Actor: ctx.User, - Private: true, - ListOptions: utils.GetListOptions(ctx), - }) - if err != nil { - ctx.Error(http.StatusInternalServerError, "GetUserRepositories", err) - return + opts := &models.SearchRepoOptions{ + ListOptions: utils.GetListOptions(ctx), + Actor: ctx.User, + OwnerID: ctx.User.ID, + Private: ctx.IsSigned, + IncludeDescription: true, } - accessibleReposMap, err := ctx.User.GetRepositoryAccesses() + + var err error + repos, count, err := models.SearchRepository(opts) if err != nil { - ctx.Error(http.StatusInternalServerError, "GetRepositoryAccesses", err) + ctx.Error(http.StatusInternalServerError, "SearchRepository", err) return } - apiRepos := make([]*api.Repository, len(ownRepos)+len(accessibleReposMap)) - for i := range ownRepos { - apiRepos[i] = ownRepos[i].APIFormat(models.AccessModeOwner) + results := make([]*api.Repository, len(repos)) + for i, repo := range repos { + if err = repo.GetOwner(); err != nil { + ctx.Error(http.StatusInternalServerError, "GetOwner", err) + return + } + accessMode, err := models.AccessLevel(ctx.User, repo) + if err != nil { + ctx.Error(http.StatusInternalServerError, "AccessLevel", err) + } + results[i] = repo.APIFormat(accessMode) } - i := len(ownRepos) - for repo, access := range accessibleReposMap { - apiRepos[i] = repo.APIFormat(access) - i++ - } - ctx.JSON(http.StatusOK, &apiRepos) + + ctx.SetLinkHeader(int(count), opts.ListOptions.PageSize) + ctx.Header().Set("X-Total-Count", strconv.FormatInt(count, 10)) + ctx.JSON(http.StatusOK, &results) } // ListOrgRepos - list the repositories of an organization. diff --git a/routers/api/v1/utils/utils.go b/routers/api/v1/utils/utils.go index 092ea3dbb6..ad1a136db4 100644 --- a/routers/api/v1/utils/utils.go +++ b/routers/api/v1/utils/utils.go @@ -5,6 +5,7 @@ package utils import ( + "net/url" "strings" "time" @@ -15,30 +16,49 @@ import ( // GetQueryBeforeSince return parsed time (unix format) from URL query's before and since func GetQueryBeforeSince(ctx *context.APIContext) (before, since int64, err error) { - qCreatedBefore := strings.Trim(ctx.Query("before"), " ") - if qCreatedBefore != "" { - createdBefore, err := time.Parse(time.RFC3339, qCreatedBefore) - if err != nil { - return 0, 0, err - } - if !createdBefore.IsZero() { - before = createdBefore.Unix() - } + qCreatedBefore, err := prepareQueryArg(ctx, "before") + if err != nil { + return 0, 0, err } - qCreatedAfter := strings.Trim(ctx.Query("since"), " ") - if qCreatedAfter != "" { - createdAfter, err := time.Parse(time.RFC3339, qCreatedAfter) - if err != nil { - return 0, 0, err - } - if !createdAfter.IsZero() { - since = createdAfter.Unix() - } + qCreatedSince, err := prepareQueryArg(ctx, "since") + if err != nil { + return 0, 0, err + } + + before, err = parseTime(qCreatedBefore) + if err != nil { + return 0, 0, err + } + + since, err = parseTime(qCreatedSince) + if err != nil { + return 0, 0, err } return before, since, nil } +// parseTime parse time and return unix timestamp +func parseTime(value string) (int64, error) { + if len(value) != 0 { + t, err := time.Parse(time.RFC3339, value) + if err != nil { + return 0, err + } + if !t.IsZero() { + return t.Unix(), nil + } + } + return 0, nil +} + +// prepareQueryArg unescape and trim a query arg +func prepareQueryArg(ctx *context.APIContext, name string) (value string, err error) { + value, err = url.PathUnescape(ctx.Query(name)) + value = strings.Trim(value, " ") + return +} + // GetListOptions returns list options using the page and limit parameters func GetListOptions(ctx *context.APIContext) models.ListOptions { return models.ListOptions{ diff --git a/routers/home.go b/routers/home.go index 1b8c4cd17b..ae94207ade 100644 --- a/routers/home.go +++ b/routers/home.go @@ -194,7 +194,6 @@ func RenderUserSearch(ctx *context.Context, opts *models.SearchUserOptions, tplN if opts.Page <= 1 { opts.Page = 1 } - opts.Actor = ctx.User var ( users []*models.User @@ -252,6 +251,7 @@ func ExploreUsers(ctx *context.Context) { ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled RenderUserSearch(ctx, &models.SearchUserOptions{ + Actor: ctx.User, Type: models.UserTypeIndividual, ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum}, IsActive: util.OptionalBoolTrue, @@ -272,6 +272,7 @@ func ExploreOrganizations(ctx *context.Context) { } RenderUserSearch(ctx, &models.SearchUserOptions{ + Actor: ctx.User, Type: models.UserTypeOrganization, ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum}, Visible: visibleTypes, diff --git a/routers/init.go b/routers/init.go index c891ec3149..964da6ced6 100644 --- a/routers/init.go +++ b/routers/init.go @@ -36,7 +36,6 @@ import ( "gitea.com/macaron/i18n" "gitea.com/macaron/macaron" - unknwoni18n "github.com/unknwon/i18n" ) func checkRunMode() { @@ -124,8 +123,6 @@ func GlobalInit(ctx context.Context) { // Setup i18n InitLocales() - log.Info("%s", unknwoni18n.Tr("en-US", "admin.dashboard.delete_repo_archives")) - NewServices() if setting.InstallLock { diff --git a/routers/private/hook.go b/routers/private/hook.go index 4b57aff588..215793c970 100644 --- a/routers/private/hook.go +++ b/routers/private/hook.go @@ -39,6 +39,7 @@ func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env [] _ = stdoutWriter.Close() }() + // This is safe as force pushes are already forbidden err = git.NewCommand("rev-list", oldCommitID+"..."+newCommitID). RunInDirTimeoutEnvFullPipelineFunc(env, -1, repo.Path, stdoutWriter, nil, nil, @@ -70,6 +71,7 @@ func checkFileProtection(oldCommitID, newCommitID string, patterns []glob.Glob, _ = stdoutWriter.Close() }() + // This use of ... is safe as force-pushes have already been ruled out. err = git.NewCommand("diff", "--name-only", oldCommitID+"..."+newCommitID). RunInDirTimeoutEnvFullPipelineFunc(env, -1, repo.Path, stdoutWriter, nil, nil, diff --git a/routers/private/serv.go b/routers/private/serv.go index d5b5fcc8f7..b6dd2c361e 100644 --- a/routers/private/serv.go +++ b/routers/private/serv.go @@ -61,6 +61,12 @@ func ServNoCommand(ctx *macaron.Context) { }) return } + if !user.IsActive || user.ProhibitLogin { + ctx.JSON(http.StatusForbidden, map[string]interface{}{ + "err": "Your account is disabled.", + }) + return + } results.Owner = user } ctx.JSON(http.StatusOK, &results) @@ -98,9 +104,28 @@ func ServCommand(ctx *macaron.Context) { results.RepoName = repoName[:len(repoName)-5] } + owner, err := models.GetUserByName(results.OwnerName) + if err != nil { + log.Error("Unable to get repository owner: %s/%s Error: %v", results.OwnerName, results.RepoName, err) + ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ + "results": results, + "type": "InternalServerError", + "err": fmt.Sprintf("Unable to get repository owner: %s/%s %v", results.OwnerName, results.RepoName, err), + }) + return + } + if !owner.IsOrganization() && !owner.IsActive { + ctx.JSON(http.StatusForbidden, map[string]interface{}{ + "results": results, + "type": "ForbiddenError", + "err": "Repository cannot be accessed, you could retry it later", + }) + return + } + // Now get the Repository and set the results section repoExist := true - repo, err := models.GetRepositoryByOwnerAndName(results.OwnerName, results.RepoName) + repo, err := models.GetRepositoryByName(owner.ID, results.RepoName) if err != nil { if models.IsErrRepoNotExist(err) { repoExist = false @@ -127,6 +152,7 @@ func ServCommand(ctx *macaron.Context) { } if repoExist { + repo.Owner = owner repo.OwnerName = ownerName results.RepoID = repo.ID @@ -238,6 +264,14 @@ func ServCommand(ctx *macaron.Context) { }) return } + + if !user.IsActive || user.ProhibitLogin { + ctx.JSON(http.StatusForbidden, map[string]interface{}{ + "err": "Your account is disabled.", + }) + return + } + results.UserName = user.Name } diff --git a/routers/repo/blame.go b/routers/repo/blame.go index 00ef9a99ea..602924ecd6 100644 --- a/routers/repo/blame.go +++ b/routers/repo/blame.go @@ -141,7 +141,13 @@ func RefBlame(ctx *context.Context) { ctx.Data["FileSize"] = blob.Size() ctx.Data["FileName"] = blob.Name() - blameReader, err := git.CreateBlameReader(models.RepoPath(userName, repoName), commitID, fileName) + ctx.Data["NumLines"], err = blob.GetBlobLineCount() + if err != nil { + ctx.NotFound("GetBlobLineCount", err) + return + } + + blameReader, err := git.CreateBlameReader(ctx.Req.Context(), models.RepoPath(userName, repoName), commitID, fileName) if err != nil { ctx.NotFound("CreateBlameReader", err) return diff --git a/routers/repo/branch.go b/routers/repo/branch.go index e7eac04bce..4d8b9158fe 100644 --- a/routers/repo/branch.go +++ b/routers/repo/branch.go @@ -6,6 +6,7 @@ package repo import ( + "fmt" "strings" "code.gitea.io/gitea/models" @@ -102,7 +103,11 @@ func RestoreBranchPost(ctx *context.Context) { return } - if err := ctx.Repo.GitRepo.CreateBranch(deletedBranch.Name, deletedBranch.Commit); err != nil { + if err := git.Push(ctx.Repo.Repository.RepoPath(), git.PushOptions{ + Remote: ctx.Repo.Repository.RepoPath(), + Branch: fmt.Sprintf("%s:%s%s", deletedBranch.Commit, git.BranchPrefix, deletedBranch.Name), + Env: models.PushingEnvironment(ctx.User, ctx.Repo.Repository), + }); err != nil { if strings.Contains(err.Error(), "already exists") { ctx.Flash.Error(ctx.Tr("repo.branch.already_exists", deletedBranch.Name)) return @@ -112,12 +117,6 @@ func RestoreBranchPost(ctx *context.Context) { return } - if err := ctx.Repo.Repository.RemoveDeletedBranch(deletedBranch.ID); err != nil { - log.Error("RemoveDeletedBranch: %v", err) - ctx.Flash.Error(ctx.Tr("repo.branch.restore_failed", deletedBranch.Name)) - return - } - // Don't return error below this if err := repofiles.PushUpdate( ctx.Repo.Repository, @@ -216,7 +215,7 @@ func loadBranches(ctx *context.Context) []*Branch { } } - divergence, divergenceError := repofiles.CountDivergingCommits(ctx.Repo.Repository, branchName) + divergence, divergenceError := repofiles.CountDivergingCommits(ctx.Repo.Repository, git.BranchPrefix+branchName) if divergenceError != nil { ctx.ServerError("CountDivergingCommits", divergenceError) return nil @@ -331,6 +330,8 @@ func CreateBranch(ctx *context.Context, form auth.NewBranchForm) { var err error if ctx.Repo.IsViewBranch { err = repo_module.CreateNewBranch(ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName) + } else if ctx.Repo.IsViewTag { + err = repo_module.CreateNewBranchFromCommit(ctx.User, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName) } else { err = repo_module.CreateNewBranchFromCommit(ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName) } diff --git a/routers/repo/compare.go b/routers/repo/compare.go index 97bb5e6b18..3ffabc14a1 100644 --- a/routers/repo/compare.go +++ b/routers/repo/compare.go @@ -381,7 +381,20 @@ func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, * return nil, nil, nil, nil, "", "" } - compareInfo, err := headGitRepo.GetCompareInfo(baseRepo.RepoPath(), baseBranch, headBranch) + baseBranchRef := baseBranch + if baseIsBranch { + baseBranchRef = git.BranchPrefix + baseBranch + } else if baseIsTag { + baseBranchRef = git.TagPrefix + baseBranch + } + headBranchRef := headBranch + if headIsBranch { + headBranchRef = git.BranchPrefix + headBranch + } else if headIsTag { + headBranchRef = git.TagPrefix + headBranch + } + + compareInfo, err := headGitRepo.GetCompareInfo(baseRepo.RepoPath(), baseBranchRef, headBranchRef) if err != nil { ctx.ServerError("GetCompareInfo", err) return nil, nil, nil, nil, "", "" diff --git a/routers/repo/http.go b/routers/repo/http.go index 650642a581..a1dcd65e1f 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -29,6 +29,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" repo_service "code.gitea.io/gitea/services/repository" ) @@ -103,6 +104,10 @@ func HTTP(ctx *context.Context) { ctx.NotFoundOrServerError("GetUserByName", models.IsErrUserNotExist, err) return } + if !owner.IsOrganization() && !owner.IsActive { + ctx.HandleText(http.StatusForbidden, "Repository cannot be accessed. You cannot push or open issues/pull-requests.") + return + } repoExist := true repo, err := models.GetRepositoryByName(owner.ID, reponame) @@ -135,6 +140,16 @@ func HTTP(ctx *context.Context) { environ []string ) + // don't allow anonymous pulls if organization is not public + if isPublicPull { + if err := repo.GetOwner(); err != nil { + ctx.ServerError("GetOwner", err) + return + } + + askAuth = askAuth || (repo.Owner.Visibility != structs.VisibleTypePublic) + } + // check access if askAuth { authUsername = ctx.Req.Header.Get(setting.ReverseProxyAuthUser) @@ -232,6 +247,11 @@ func HTTP(ctx *context.Context) { } } + if !authUser.IsActive || authUser.ProhibitLogin { + ctx.HandleText(http.StatusForbidden, "Your account is disabled.") + return + } + if repoExist { perm, err := models.GetUserRepoPermission(repo, authUser) if err != nil { diff --git a/routers/repo/issue.go b/routers/repo/issue.go index afe64c731f..8c773576b6 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -969,8 +969,10 @@ func ViewIssue(ctx *context.Context) { } } else if comment.Type == models.CommentTypeRemoveDependency || comment.Type == models.CommentTypeAddDependency { if err = comment.LoadDepIssueDetails(); err != nil { - ctx.ServerError("LoadDepIssueDetails", err) - return + if !models.IsErrIssueNotExist(err) { + ctx.ServerError("LoadDepIssueDetails", err) + return + } } } else if comment.Type == models.CommentTypeCode || comment.Type == models.CommentTypeReview { comment.RenderedContent = string(markdown.Render([]byte(comment.Content), ctx.Repo.RepoLink, @@ -1954,7 +1956,7 @@ func updateAttachments(item interface{}, files []string) error { case *models.Comment: attachments = content.Attachments default: - return fmt.Errorf("Unknow Type") + return fmt.Errorf("Unknown Type: %T", content) } for i := 0; i < len(attachments); i++ { if util.IsStringInSlice(attachments[i].UUID, files) { @@ -1972,7 +1974,7 @@ func updateAttachments(item interface{}, files []string) error { case *models.Comment: err = content.UpdateAttachments(files) default: - return fmt.Errorf("Unknow Type") + return fmt.Errorf("Unknown Type: %T", content) } if err != nil { return err @@ -1984,7 +1986,7 @@ func updateAttachments(item interface{}, files []string) error { case *models.Comment: content.Attachments, err = models.GetAttachmentsByCommentID(content.ID) default: - return fmt.Errorf("Unknow Type") + return fmt.Errorf("Unknown Type: %T", content) } return err } diff --git a/routers/repo/pull.go b/routers/repo/pull.go index d23c93d0b6..da826026b3 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -428,6 +428,20 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare sha, err := baseGitRepo.GetRefCommitID(pull.GetGitRefName()) if err != nil { + if git.IsErrNotExist(err) { + ctx.Data["IsPullRequestBroken"] = true + if pull.IsSameRepo() { + ctx.Data["HeadTarget"] = pull.HeadBranch + } else if pull.HeadRepo == nil { + ctx.Data["HeadTarget"] = ":" + pull.HeadBranch + } else { + ctx.Data["HeadTarget"] = pull.HeadRepo.OwnerName + ":" + pull.HeadBranch + } + ctx.Data["BaseTarget"] = pull.BaseBranch + ctx.Data["NumCommits"] = 0 + ctx.Data["NumFiles"] = 0 + return nil + } ctx.ServerError(fmt.Sprintf("GetRefCommitID(%s)", pull.GetGitRefName()), err) return nil } @@ -462,17 +476,15 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare ctx.Data["IsPullRequestBroken"] = true if pull.IsSameRepo() { ctx.Data["HeadTarget"] = pull.HeadBranch + } else if pull.HeadRepo == nil { + ctx.Data["HeadTarget"] = ":" + pull.HeadBranch } else { - if pull.HeadRepo == nil { - ctx.Data["HeadTarget"] = ":" + pull.HeadBranch - } else { - ctx.Data["HeadTarget"] = pull.HeadRepo.OwnerName + ":" + pull.HeadBranch - } + ctx.Data["HeadTarget"] = pull.HeadRepo.OwnerName + ":" + pull.HeadBranch } } compareInfo, err := baseGitRepo.GetCompareInfo(pull.BaseRepo.RepoPath(), - pull.BaseBranch, pull.GetGitRefName()) + git.BranchPrefix+pull.BaseBranch, pull.GetGitRefName()) if err != nil { if strings.Contains(err.Error(), "fatal: Not a valid object name") { ctx.Data["IsPullRequestBroken"] = true @@ -950,6 +962,16 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) if models.IsErrUserDoesNotHaveAccessToRepo(err) { ctx.Error(400, "UserDoesNotHaveAccessToRepo", err.Error()) return + } else if git.IsErrPushRejected(err) { + pushrejErr := err.(*git.ErrPushRejected) + message := pushrejErr.Message + if len(message) == 0 { + ctx.Flash.Error(ctx.Tr("repo.pulls.push_rejected_no_message")) + } else { + ctx.Flash.Error(ctx.Tr("repo.pulls.push_rejected", utils.SanitizeFlashErrorString(pushrejErr.Message))) + } + ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pullIssue.Index)) + return } ctx.ServerError("NewPullRequest", err) return diff --git a/routers/repo/release.go b/routers/repo/release.go index 1eac3dce97..bb755dd8ec 100644 --- a/routers/repo/release.go +++ b/routers/repo/release.go @@ -69,13 +69,6 @@ func Releases(ctx *context.Context) { IncludeTags: true, } - if opts.ListOptions.Page <= 1 { - opts.ListOptions.Page = 1 - } - if opts.ListOptions.PageSize <= 0 { - opts.ListOptions.Page = 10 - } - releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts) if err != nil { ctx.ServerError("GetReleasesByRepoID", err) @@ -139,8 +132,12 @@ func SingleRelease(ctx *context.Context) { writeAccess := ctx.Repo.CanWrite(models.UnitTypeReleases) ctx.Data["CanCreateRelease"] = writeAccess && !ctx.Repo.Repository.IsArchived - release, err := models.GetRelease(ctx.Repo.Repository.ID, ctx.Params("tag")) + release, err := models.GetRelease(ctx.Repo.Repository.ID, ctx.Params("*")) if err != nil { + if models.IsErrReleaseNotExist(err) { + ctx.NotFound("GetRelease", err) + return + } ctx.ServerError("GetReleasesByRepoID", err) return } diff --git a/routers/repo/repo.go b/routers/repo/repo.go index b0bb608d09..4d363820e6 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -134,6 +134,7 @@ func Create(ctx *context.Context) { ctx.Data["readme"] = "Default" ctx.Data["private"] = getRepoPrivate(ctx) ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate + ctx.Data["default_branch"] = setting.Repository.DefaultBranch ctxUser := checkContextUser(ctx, ctx.QueryInt64("org")) if ctx.Written() { diff --git a/routers/repo/setting.go b/routers/repo/setting.go index 7a2db88c1f..b1af3076f1 100644 --- a/routers/repo/setting.go +++ b/routers/repo/setting.go @@ -22,6 +22,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/validation" "code.gitea.io/gitea/routers/utils" @@ -75,7 +76,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { ctx.Repo.GitRepo.Close() ctx.Repo.GitRepo = nil } - if err := repo_service.ChangeRepositoryName(ctx.Repo.Owner, repo, newRepoName); err != nil { + if err := repo_service.ChangeRepositoryName(ctx.User, repo, newRepoName); err != nil { ctx.Data["Err_RepoName"] = true switch { case models.IsErrRepoAlreadyExist(err): @@ -184,8 +185,8 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { address = u.String() - if err := mirror_service.SaveAddress(ctx.Repo.Mirror, address); err != nil { - ctx.ServerError("SaveAddress", err) + if err := mirror_service.UpdateAddress(ctx.Repo.Mirror, address); err != nil { + ctx.ServerError("UpdateAddress", err) return } @@ -379,6 +380,14 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { return } + if newOwner.Type == models.UserTypeOrganization { + if !ctx.User.IsAdmin && newOwner.Visibility == structs.VisibleTypePrivate && !newOwner.HasMemberWithUserID(ctx.User.ID) { + // The user shouldn't know about this organization + ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_owner_name"), tplSettingsOptions, nil) + return + } + } + // Close the GitRepo if open if ctx.Repo.GitRepo != nil { ctx.Repo.GitRepo.Close() diff --git a/routers/repo/view.go b/routers/repo/view.go index 9c9cdc06bf..0f4e2d838c 100644 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -319,7 +319,7 @@ func renderDirectory(ctx *context.Context, treeLink string) { if markupType := markup.Type(readmeFile.name); markupType != "" { ctx.Data["IsMarkup"] = true ctx.Data["MarkupType"] = string(markupType) - ctx.Data["FileContent"] = string(markup.Render(readmeFile.name, buf, readmeTreelink, ctx.Repo.Repository.ComposeMetas())) + ctx.Data["FileContent"] = string(markup.Render(readmeFile.name, buf, readmeTreelink, ctx.Repo.Repository.ComposeDocumentMetas())) } else { ctx.Data["IsRenderedHTML"] = true ctx.Data["FileContent"] = strings.Replace( @@ -459,7 +459,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st if markupType := markup.Type(blob.Name()); markupType != "" { ctx.Data["IsMarkup"] = true ctx.Data["MarkupType"] = markupType - ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas())) + ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeDocumentMetas())) } else if readmeExist { ctx.Data["IsRenderedHTML"] = true ctx.Data["FileContent"] = strings.Replace( @@ -538,7 +538,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st buf = append(buf, d...) ctx.Data["IsMarkup"] = true ctx.Data["MarkupType"] = markupType - ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas())) + ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeDocumentMetas())) } } diff --git a/routers/repo/wiki.go b/routers/repo/wiki.go index 5da01f21ac..29b0fb2ea6 100644 --- a/routers/repo/wiki.go +++ b/routers/repo/wiki.go @@ -209,7 +209,7 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) { return nil, nil } - metas := ctx.Repo.Repository.ComposeMetas() + metas := ctx.Repo.Repository.ComposeDocumentMetas() ctx.Data["content"] = markdown.RenderWiki(data, ctx.Repo.RepoLink, metas) ctx.Data["sidebarPresent"] = sidebarContent != nil ctx.Data["sidebarContent"] = markdown.RenderWiki(sidebarContent, ctx.Repo.RepoLink, metas) diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 7f409eb576..19352d96af 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -713,7 +713,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/:id", repo.MilestoneIssuesAndPulls) }, reqRepoIssuesOrPullsReader, context.RepoRef()) m.Combo("/compare/*", repo.MustBeNotEmpty, reqRepoCodeReader, repo.SetEditorconfigIfExists). - Get(repo.SetDiffViewStyle, repo.CompareDiff). + Get(ignSignIn, repo.SetDiffViewStyle, repo.CompareDiff). Post(reqSignIn, context.RepoMustNotBeArchived(), reqRepoPullsReader, repo.MustAllowPulls, bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost) }, context.RepoAssignment(), context.UnitTypes()) @@ -814,9 +814,9 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/:username/:reponame", func() { m.Group("/releases", func() { m.Get("/", repo.Releases) - m.Get("/tag/:tag", repo.SingleRelease) + m.Get("/tag/*", repo.SingleRelease) m.Get("/latest", repo.LatestRelease) - }, repo.MustBeNotEmpty, context.RepoRef()) + }, repo.MustBeNotEmpty, context.RepoRefByType(context.RepoRefTag)) m.Group("/releases", func() { m.Get("/new", repo.NewRelease) m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost) @@ -1048,10 +1048,6 @@ func RegisterRoutes(m *macaron.Macaron) { ctx.HTML(200, "pwa/manifest_json") }) - m.Get("/serviceworker.js", templates.JSRenderer(), func(ctx *context.Context) { - ctx.HTML(200, "pwa/serviceworker_js") - }) - // prometheus metrics endpoint if setting.Metrics.Enabled { c := metrics.NewCollector() diff --git a/routers/user/auth.go b/routers/user/auth.go index e1a8854804..a253e6cdbb 100644 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -1489,6 +1489,7 @@ func ResetPasswdPost(ctx *context.Context) { func MustChangePassword(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("auth.must_change_password") ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/settings/change_password" + ctx.Data["MustChangePassword"] = true ctx.HTML(200, tplMustChangePassword) } diff --git a/routers/user/notification.go b/routers/user/notification.go index 9724c81088..34939d1455 100644 --- a/routers/user/notification.go +++ b/routers/user/notification.go @@ -174,6 +174,7 @@ func NotificationStatusPost(c *context.Context) { if c.Written() { return } + c.Data["Link"] = fmt.Sprintf("%snotifications", setting.AppURL) c.HTML(http.StatusOK, tplNotificationDiv) } diff --git a/routers/user/oauth.go b/routers/user/oauth.go index a9e089b39f..12665e94db 100644 --- a/routers/user/oauth.go +++ b/routers/user/oauth.go @@ -7,6 +7,7 @@ package user import ( "encoding/base64" "fmt" + "html" "net/url" "strings" @@ -271,8 +272,8 @@ func AuthorizeOAuth(ctx *context.Context, form auth.AuthorizationForm) { ctx.Data["Application"] = app ctx.Data["RedirectURI"] = form.RedirectURI ctx.Data["State"] = form.State - ctx.Data["ApplicationUserLink"] = "@" + app.User.Name + "" - ctx.Data["ApplicationRedirectDomainHTML"] = "" + form.RedirectURI + "" + ctx.Data["ApplicationUserLink"] = "@" + html.EscapeString(app.User.Name) + "" + ctx.Data["ApplicationRedirectDomainHTML"] = "" + html.EscapeString(form.RedirectURI) + "" // TODO document SESSION <=> FORM err = ctx.Session.Set("client_id", app.ClientID) if err != nil { diff --git a/routers/user/setting/profile.go b/routers/user/setting/profile.go index d6f25f9135..6ed0fe2eeb 100644 --- a/routers/user/setting/profile.go +++ b/routers/user/setting/profile.go @@ -90,7 +90,6 @@ func ProfilePost(ctx *context.Context, form auth.UpdateProfileForm) { } ctx.User.FullName = form.FullName - ctx.User.Email = form.Email ctx.User.KeepEmailPrivate = form.KeepEmailPrivate ctx.User.Website = form.Website ctx.User.Location = form.Location diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 6867f8e0a4..90c5795ba5 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -18,7 +18,6 @@ import ( "os" "os/exec" "sort" - "strconv" "strings" "code.gitea.io/gitea/models" @@ -54,6 +53,7 @@ const ( DiffFileChange DiffFileDel DiffFileRename + DiffFileCopy ) // DiffLineExpandDirection represents the DiffLineSection expand direction @@ -405,91 +405,262 @@ func (diff *Diff) NumFiles() int { const cmdDiffHead = "diff --git " -// ParsePatch builds a Diff object from a io.Reader and some -// parameters. -// TODO: move this function to gogits/git-module +// ParsePatch builds a Diff object from a io.Reader and some parameters. func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*Diff, error) { - var ( - diff = &Diff{Files: make([]*DiffFile, 0)} + var curFile *DiffFile - curFile = &DiffFile{} - curSection = &DiffSection{ - Lines: make([]*DiffLine, 0, 10), + diff := &Diff{Files: make([]*DiffFile, 0)} + + sb := strings.Builder{} + + // OK let's set a reasonable buffer size. + // This should be let's say at least the size of maxLineCharacters or 4096 whichever is larger. + readerSize := maxLineCharacters + if readerSize < 4096 { + readerSize = 4096 + } + + input := bufio.NewReaderSize(reader, readerSize) + line, err := input.ReadString('\n') + if err != nil { + if err == io.EOF { + return diff, nil + } + return diff, err + } +parsingLoop: + for { + // 1. A patch file always begins with `diff --git ` + `a/path b/path` (possibly quoted) + // if it does not we have bad input! + if !strings.HasPrefix(line, cmdDiffHead) { + return diff, fmt.Errorf("Invalid first file line: %s", line) } - leftLine, rightLine int - lineCount int - curFileLinesCount int - curFileLFSPrefix bool + // TODO: Handle skipping first n files + if len(diff.Files) >= maxFiles { + diff.IsIncomplete = true + _, err := io.Copy(ioutil.Discard, reader) + if err != nil { + // By the definition of io.Copy this never returns io.EOF + return diff, fmt.Errorf("Copy: %v", err) + } + break parsingLoop + } + + curFile = createDiffFile(diff, line) + diff.Files = append(diff.Files, curFile) + + // 2. It is followed by one or more extended header lines: + // + // old mode + // new mode + // deleted file mode + // new file mode + // copy from + // copy to + // rename from + // rename to + // similarity index + // dissimilarity index + // index .. + // + // * 6-digit octal numbers including the file type and file permission bits. + // * does not include the a/ and b/ prefixes + // * percentage of unchanged lines for similarity, percentage of changed + // lines dissimilarity as integer rounded down with terminal %. 100% => equal files. + // * The index line includes the blob object names before and after the change. + // The is included if the file mode does not change; otherwise, separate + // lines indicate the old and the new mode. + // 3. Following this header the "standard unified" diff format header may be encountered: (but not for every case...) + // + // --- a/ + // +++ b/ + // + // With multiple hunks + // + // @@ @@ + // +added line + // -removed line + // unchanged line + // + // 4. Binary files get: + // + // Binary files a/ and b/ differ + // + // but one of a/ and b/ could be /dev/null. + curFileLoop: + for { + line, err = input.ReadString('\n') + if err != nil { + if err != io.EOF { + return diff, err + } + break parsingLoop + } + switch { + case strings.HasPrefix(line, cmdDiffHead): + break curFileLoop + case strings.HasPrefix(line, "old mode ") || + strings.HasPrefix(line, "new mode "): + if strings.HasSuffix(line, " 160000\n") { + curFile.IsSubmodule = true + } + case strings.HasPrefix(line, "copy from "): + curFile.IsRenamed = true + curFile.Type = DiffFileCopy + case strings.HasPrefix(line, "copy to "): + curFile.IsRenamed = true + curFile.Type = DiffFileCopy + case strings.HasPrefix(line, "new file"): + curFile.Type = DiffFileAdd + curFile.IsCreated = true + if strings.HasSuffix(line, " 160000\n") { + curFile.IsSubmodule = true + } + case strings.HasPrefix(line, "deleted"): + curFile.Type = DiffFileDel + curFile.IsDeleted = true + if strings.HasSuffix(line, " 160000\n") { + curFile.IsSubmodule = true + } + case strings.HasPrefix(line, "index"): + if strings.HasSuffix(line, " 160000\n") { + curFile.IsSubmodule = true + } + case strings.HasPrefix(line, "similarity index 100%"): + curFile.Type = DiffFileRename + case strings.HasPrefix(line, "Binary"): + curFile.IsBin = true + case strings.HasPrefix(line, "--- "): + // Do nothing with this line + case strings.HasPrefix(line, "+++ "): + // Do nothing with this line + lineBytes, isFragment, err := parseHunks(curFile, maxLines, maxLineCharacters, input) + diff.TotalAddition += curFile.Addition + diff.TotalDeletion += curFile.Deletion + if err != nil { + if err != io.EOF { + return diff, err + } + break parsingLoop + } + sb.Reset() + _, _ = sb.Write(lineBytes) + for isFragment { + lineBytes, isFragment, err = input.ReadLine() + if err != nil { + // Now by the definition of ReadLine this cannot be io.EOF + return diff, fmt.Errorf("Unable to ReadLine: %v", err) + } + _, _ = sb.Write(lineBytes) + } + line = sb.String() + sb.Reset() + + break curFileLoop + } + } + + } + + // FIXME: There are numerous issues with this: + // - we might want to consider detecting encoding while parsing but... + // - we're likely to fail to get the correct encoding here anyway as we won't have enough information + // - and this doesn't really account for changes in encoding + var buf bytes.Buffer + for _, f := range diff.Files { + buf.Reset() + for _, sec := range f.Sections { + for _, l := range sec.Lines { + if l.Type == DiffLineSection { + continue + } + buf.WriteString(l.Content[1:]) + buf.WriteString("\n") + } + } + charsetLabel, err := charset.DetectEncoding(buf.Bytes()) + if charsetLabel != "UTF-8" && err == nil { + encoding, _ := stdcharset.Lookup(charsetLabel) + if encoding != nil { + d := encoding.NewDecoder() + for _, sec := range f.Sections { + for _, l := range sec.Lines { + if l.Type == DiffLineSection { + continue + } + if c, _, err := transform.String(d, l.Content[1:]); err == nil { + l.Content = l.Content[0:1] + c + } + } + } + } + } + } + + return diff, nil +} + +func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio.Reader) (lineBytes []byte, isFragment bool, err error) { + sb := strings.Builder{} + + var ( + curSection *DiffSection + curFileLinesCount int + curFileLFSPrefix bool ) - input := bufio.NewReader(reader) - isEOF := false - for !isEOF { - var linebuf bytes.Buffer - for { - b, err := input.ReadByte() - if err != nil { - if err == io.EOF { - isEOF = true - break - } else { - return nil, fmt.Errorf("ReadByte: %v", err) - } - } - if b == '\n' { - break - } - if linebuf.Len() < maxLineCharacters { - linebuf.WriteByte(b) - } else if linebuf.Len() == maxLineCharacters { - curFile.IsIncomplete = true - } - } - line := linebuf.String() + leftLine, rightLine := 1, 1 - if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") || len(line) == 0 { - continue - } - - trimLine := strings.Trim(line, "+- ") - - if trimLine == models.LFSMetaFileIdentifier { - curFileLFSPrefix = true - } - - if curFileLFSPrefix && strings.HasPrefix(trimLine, models.LFSMetaFileOidPrefix) { - oid := strings.TrimPrefix(trimLine, models.LFSMetaFileOidPrefix) - - if len(oid) == 64 { - m := &models.LFSMetaObject{Oid: oid} - count, err := models.Count(m) - - if err == nil && count > 0 { - curFile.IsBin = true - curFile.IsLFSFile = true - curSection.Lines = nil - } - } - } - - curFileLinesCount++ - lineCount++ - - // Diff data too large, we only show the first about maxLines lines - if curFileLinesCount >= maxLines { + for { + for isFragment { curFile.IsIncomplete = true + _, isFragment, err = input.ReadLine() + if err != nil { + // Now by the definition of ReadLine this cannot be io.EOF + err = fmt.Errorf("Unable to ReadLine: %v", err) + return + } } - switch { - case line[0] == ' ': - diffLine := &DiffLine{Type: DiffLinePlain, Content: line, LeftIdx: leftLine, RightIdx: rightLine} - leftLine++ - rightLine++ - curSection.Lines = append(curSection.Lines, diffLine) - continue - case line[0] == '@': + sb.Reset() + lineBytes, isFragment, err = input.ReadLine() + if err != nil { + if err == io.EOF { + return + } + err = fmt.Errorf("Unable to ReadLine: %v", err) + return + } + if lineBytes[0] == 'd' { + // End of hunks + return + } + + switch lineBytes[0] { + case '@': + if curFileLinesCount >= maxLines { + curFile.IsIncomplete = true + continue + } + + _, _ = sb.Write(lineBytes) + for isFragment { + // This is very odd indeed - we're in a section header and the line is too long + // This really shouldn't happen... + lineBytes, isFragment, err = input.ReadLine() + if err != nil { + // Now by the definition of ReadLine this cannot be io.EOF + err = fmt.Errorf("Unable to ReadLine: %v", err) + return + } + _, _ = sb.Write(lineBytes) + } + line := sb.String() + + // Create a new section to represent this hunk curSection = &DiffSection{} curFile.Sections = append(curFile.Sections, curSection) + lineSectionInfo := getDiffLineSectionInfo(curFile.Name, line, leftLine-1, rightLine-1) diffLine := &DiffLine{ Type: DiffLineSection, @@ -501,146 +672,136 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D leftLine = lineSectionInfo.LeftIdx rightLine = lineSectionInfo.RightIdx continue - case line[0] == '+': + case '\\': + if curFileLinesCount >= maxLines { + curFile.IsIncomplete = true + continue + } + // This is used only to indicate that the current file does not have a terminal newline + if !bytes.Equal(lineBytes, []byte("\\ No newline at end of file")) { + err = fmt.Errorf("Unexpected line in hunk: %s", string(lineBytes)) + return + } + // Technically this should be the end the file! + // FIXME: we should be putting a marker at the end of the file if there is no terminal new line + continue + case '+': + curFileLinesCount++ curFile.Addition++ - diff.TotalAddition++ - diffLine := &DiffLine{Type: DiffLineAdd, Content: line, RightIdx: rightLine} + if curFileLinesCount >= maxLines { + curFile.IsIncomplete = true + continue + } + diffLine := &DiffLine{Type: DiffLineAdd, RightIdx: rightLine} rightLine++ curSection.Lines = append(curSection.Lines, diffLine) - continue - case line[0] == '-': + case '-': + curFileLinesCount++ curFile.Deletion++ - diff.TotalDeletion++ - diffLine := &DiffLine{Type: DiffLineDel, Content: line, LeftIdx: leftLine} + if curFileLinesCount >= maxLines { + curFile.IsIncomplete = true + continue + } + diffLine := &DiffLine{Type: DiffLineDel, LeftIdx: leftLine} if leftLine > 0 { leftLine++ } curSection.Lines = append(curSection.Lines, diffLine) - case strings.HasPrefix(line, "Binary"): - curFile.IsBin = true - continue + case ' ': + curFileLinesCount++ + if curFileLinesCount >= maxLines { + curFile.IsIncomplete = true + continue + } + diffLine := &DiffLine{Type: DiffLinePlain, LeftIdx: leftLine, RightIdx: rightLine} + leftLine++ + rightLine++ + curSection.Lines = append(curSection.Lines, diffLine) + default: + // This is unexpected + err = fmt.Errorf("Unexpected line in hunk: %s", string(lineBytes)) + return } - // Get new file. - if strings.HasPrefix(line, cmdDiffHead) { - if len(diff.Files) >= maxFiles { - diff.IsIncomplete = true - _, err := io.Copy(ioutil.Discard, reader) + line := string(lineBytes) + if isFragment { + curFile.IsIncomplete = true + for isFragment { + lineBytes, isFragment, err = input.ReadLine() if err != nil { - return nil, fmt.Errorf("Copy: %v", err) + // Now by the definition of ReadLine this cannot be io.EOF + err = fmt.Errorf("Unable to ReadLine: %v", err) + return } - break } + } + if len(line) > maxLineCharacters { + curFile.IsIncomplete = true + line = line[:maxLineCharacters] + } + curSection.Lines[len(curSection.Lines)-1].Content = line - var middle int + // handle LFS + if line[1:] == models.LFSMetaFileIdentifier { + curFileLFSPrefix = true + } else if curFileLFSPrefix && strings.HasPrefix(line[1:], models.LFSMetaFileOidPrefix) { + oid := strings.TrimPrefix(line[1:], models.LFSMetaFileOidPrefix) + if len(oid) == 64 { + m := &models.LFSMetaObject{Oid: oid} + count, err := models.Count(m) - // Note: In case file name is surrounded by double quotes (it happens only in git-shell). - // e.g. diff --git "a/xxx" "b/xxx" - hasQuote := line[len(cmdDiffHead)] == '"' - if hasQuote { - middle = strings.Index(line, ` "b/`) - } else { - middle = strings.Index(line, " b/") - } - - beg := len(cmdDiffHead) - a := line[beg+2 : middle] - b := line[middle+3:] - - if hasQuote { - // Keep the entire string in double quotes for now - a = line[beg:middle] - b = line[middle+1:] - - var err error - a, err = strconv.Unquote(a) - if err != nil { - return nil, fmt.Errorf("Unquote: %v", err) - } - b, err = strconv.Unquote(b) - if err != nil { - return nil, fmt.Errorf("Unquote: %v", err) - } - // Now remove the /a /b - a = a[2:] - b = b[2:] - - } - - curFile = &DiffFile{ - Name: b, - OldName: a, - Index: len(diff.Files) + 1, - Type: DiffFileChange, - Sections: make([]*DiffSection, 0, 10), - IsRenamed: a != b, - } - diff.Files = append(diff.Files, curFile) - curFileLinesCount = 0 - leftLine = 1 - rightLine = 1 - curFileLFSPrefix = false - - // Check file diff type and is submodule. - for { - line, err := input.ReadString('\n') - if err != nil { - if err == io.EOF { - isEOF = true - } else { - return nil, fmt.Errorf("ReadString: %v", err) - } - } - - switch { - case strings.HasPrefix(line, "new file"): - curFile.Type = DiffFileAdd - curFile.IsCreated = true - case strings.HasPrefix(line, "deleted"): - curFile.Type = DiffFileDel - curFile.IsDeleted = true - case strings.HasPrefix(line, "index"): - curFile.Type = DiffFileChange - case strings.HasPrefix(line, "similarity index 100%"): - curFile.Type = DiffFileRename - } - if curFile.Type > 0 { - if strings.HasSuffix(line, " 160000\n") { - curFile.IsSubmodule = true - } - break + if err == nil && count > 0 { + curFile.IsBin = true + curFile.IsLFSFile = true + curSection.Lines = nil } } } } +} - // FIXME: detect encoding while parsing. - var buf bytes.Buffer - for _, f := range diff.Files { - buf.Reset() - for _, sec := range f.Sections { - for _, l := range sec.Lines { - buf.WriteString(l.Content) - buf.WriteString("\n") - } - } - charsetLabel, err := charset.DetectEncoding(buf.Bytes()) - if charsetLabel != "UTF-8" && err == nil { - encoding, _ := stdcharset.Lookup(charsetLabel) - if encoding != nil { - d := encoding.NewDecoder() - for _, sec := range f.Sections { - for _, l := range sec.Lines { - if c, _, err := transform.String(d, l.Content); err == nil { - l.Content = c - } - } - } - } - } +func createDiffFile(diff *Diff, line string) *DiffFile { + // The a/ and b/ filenames are the same unless rename/copy is involved. + // Especially, even for a creation or a deletion, /dev/null is not used + // in place of the a/ or b/ filenames. + // + // When rename/copy is involved, file1 and file2 show the name of the + // source file of the rename/copy and the name of the file that rename/copy + // produces, respectively. + // + // Path names are quoted if necessary. + // + // This means that you should always be able to determine the file name even when there + // there is potential ambiguity... + // + // but we can be simpler with our heuristics by just forcing git to prefix things nicely + curFile := &DiffFile{ + Index: len(diff.Files) + 1, + Type: DiffFileChange, + Sections: make([]*DiffSection, 0, 10), } - return diff, nil + rd := strings.NewReader(line[len(cmdDiffHead):] + " ") + curFile.Type = DiffFileChange + curFile.OldName = readFileName(rd) + curFile.Name = readFileName(rd) + curFile.IsRenamed = curFile.Name != curFile.OldName + return curFile +} + +func readFileName(rd *strings.Reader) string { + var name string + char, _ := rd.ReadByte() + _ = rd.UnreadByte() + if char == '"' { + fmt.Fscanf(rd, "%q ", &name) + if name[0] == '\\' { + name = name[1:] + } + } else { + fmt.Fscanf(rd, "%s ", &name) + } + return name[2:] } // GetDiffRange builds a Diff between two commits of a repository. @@ -669,15 +830,22 @@ func GetDiffRangeWithWhitespaceBehavior(repoPath, beforeCommitID, afterCommitID ctx, cancel := context.WithCancel(git.DefaultContext) defer cancel() var cmd *exec.Cmd - if len(beforeCommitID) == 0 && commit.ParentCount() == 0 { - cmd = exec.CommandContext(ctx, git.GitExecutable, "show", afterCommitID) + if (len(beforeCommitID) == 0 || beforeCommitID == git.EmptySHA) && commit.ParentCount() == 0 { + diffArgs := []string{"diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M"} + if len(whitespaceBehavior) != 0 { + diffArgs = append(diffArgs, whitespaceBehavior) + } + // append empty tree ref + diffArgs = append(diffArgs, "4b825dc642cb6eb9a060e54bf8d69288fbee4904") + diffArgs = append(diffArgs, afterCommitID) + cmd = exec.CommandContext(ctx, git.GitExecutable, diffArgs...) } else { actualBeforeCommitID := beforeCommitID if len(actualBeforeCommitID) == 0 { parentCommit, _ := commit.Parent(0) actualBeforeCommitID = parentCommit.ID.String() } - diffArgs := []string{"diff", "-M"} + diffArgs := []string{"diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M"} if len(whitespaceBehavior) != 0 { diffArgs = append(diffArgs, whitespaceBehavior) } diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index efdf439933..f2f84bc449 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -6,8 +6,10 @@ package gitdiff import ( + "encoding/json" "fmt" "html/template" + "strconv" "strings" "testing" @@ -41,8 +43,246 @@ func TestDiffToHTML(t *testing.T) { }, DiffLineDel)) } -func TestParsePatch(t *testing.T) { - var diff = `diff --git "a/README.md" "b/README.md" +func TestParsePatch_singlefile(t *testing.T) { + type testcase struct { + name string + gitdiff string + wantErr bool + addition int + deletion int + oldFilename string + filename string + } + + tests := []testcase{ + { + name: "readme.md2readme.md", + gitdiff: `diff --git "\\a/README.md" "\\b/README.md" +--- "\\a/README.md" ++++ "\\b/README.md" +@@ -1,3 +1,6 @@ + # gitea-github-migrator ++ ++ Build Status +- Latest Release + Docker Pulls ++ cut off ++ cut off +`, + addition: 4, + deletion: 1, + filename: "README.md", + oldFilename: "README.md", + }, + { + name: "A \\ B", + gitdiff: `diff --git "a/A \\ B" "b/A \\ B" +--- "a/A \\ B" ++++ "b/A \\ B" +@@ -1,3 +1,6 @@ + # gitea-github-migrator ++ ++ Build Status +- Latest Release + Docker Pulls ++ cut off ++ cut off`, + addition: 4, + deletion: 1, + filename: "A \\ B", + oldFilename: "A \\ B", + }, + { + name: "really weird filename", + gitdiff: `diff --git "\\a/a b/file b/a a/file" "\\b/a b/file b/a a/file" +index d2186f1..f5c8ed2 100644 +--- "\\a/a b/file b/a a/file" ` + ` ++++ "\\b/a b/file b/a a/file" ` + ` +@@ -1,3 +1,2 @@ + Create a weird file. + ` + ` +-and what does diff do here? +\ No newline at end of file`, + addition: 0, + deletion: 1, + filename: "a b/file b/a a/file", + oldFilename: "a b/file b/a a/file", + }, + { + name: "delete file with blanks", + gitdiff: `diff --git "\\a/file with blanks" "\\b/file with blanks" +deleted file mode 100644 +index 898651a..0000000 +--- "\\a/file with blanks" ` + ` ++++ /dev/null +@@ -1,5 +0,0 @@ +-a blank file +- +-has a couple o line +- +-the 5th line is the last +`, + addition: 0, + deletion: 5, + filename: "file with blanks", + oldFilename: "file with blanks", + }, + { + name: "rename aโ€”as", + gitdiff: `diff --git "a/\360\243\220\265b\342\200\240vs" "b/a\342\200\224as" +similarity index 100% +rename from "\360\243\220\265b\342\200\240vs" +rename to "a\342\200\224as" +`, + addition: 0, + deletion: 0, + oldFilename: "๐ฃตbโ€ vs", + filename: "aโ€”as", + }, + { + name: "rename with spaces", + gitdiff: `diff --git "\\a/a b/file b/a a/file" "\\b/a b/a a/file b/b file" +similarity index 100% +rename from a b/file b/a a/file +rename to a b/a a/file b/b file +`, + oldFilename: "a b/file b/a a/file", + filename: "a b/a a/file b/b file", + }, + { + name: "minuses-and-pluses", + gitdiff: `diff --git a/minuses-and-pluses b/minuses-and-pluses +index 6961180..9ba1a00 100644 +--- a/minuses-and-pluses ++++ b/minuses-and-pluses +@@ -1,4 +1,4 @@ +--- 1st line +-++ 2nd line +--- 3rd line +-++ 4th line ++++ 1st line ++-- 2nd line ++++ 3rd line ++-- 4th line +`, + oldFilename: "minuses-and-pluses", + filename: "minuses-and-pluses", + addition: 4, + deletion: 4, + }, + } + + for _, testcase := range tests { + t.Run(testcase.name, func(t *testing.T) { + got, err := ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff)) + if (err != nil) != testcase.wantErr { + t.Errorf("ParsePatch() error = %v, wantErr %v", err, testcase.wantErr) + return + } + gotMarshaled, _ := json.MarshalIndent(got, " ", " ") + if got.NumFiles() != 1 { + t.Errorf("ParsePath() did not receive 1 file:\n%s", string(gotMarshaled)) + return + } + if got.TotalAddition != testcase.addition { + t.Errorf("ParsePath() does not have correct totalAddition %d, wanted %d", got.TotalAddition, testcase.addition) + } + if got.TotalDeletion != testcase.deletion { + t.Errorf("ParsePath() did not have correct totalDeletion %d, wanted %d", got.TotalDeletion, testcase.deletion) + } + file := got.Files[0] + if file.Addition != testcase.addition { + t.Errorf("ParsePath() does not have correct file addition %d, wanted %d", file.Addition, testcase.addition) + } + if file.Deletion != testcase.deletion { + t.Errorf("ParsePath() did not have correct file deletion %d, wanted %d", file.Deletion, testcase.deletion) + } + if file.OldName != testcase.oldFilename { + t.Errorf("ParsePath() did not have correct OldName %s, wanted %s", file.OldName, testcase.oldFilename) + } + if file.Name != testcase.filename { + t.Errorf("ParsePath() did not have correct Name %s, wanted %s", file.Name, testcase.filename) + } + }) + } + + // Test max lines + diffBuilder := &strings.Builder{} + + var diff = `diff --git a/newfile2 b/newfile2 +new file mode 100644 +index 0000000..6bb8f39 +--- /dev/null ++++ b/newfile2 +@@ -0,0 +1,35 @@ +` + diffBuilder.WriteString(diff) + + for i := 0; i < 35; i++ { + diffBuilder.WriteString("+line" + strconv.Itoa(i) + "\n") + } + diff = diffBuilder.String() + result, err := ParsePatch(20, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff)) + if err != nil { + t.Errorf("There should not be an error: %v", err) + } + if !result.Files[0].IsIncomplete { + t.Errorf("Files should be incomplete! %v", result.Files[0]) + } + result, err = ParsePatch(40, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff)) + if err != nil { + t.Errorf("There should not be an error: %v", err) + } + if result.Files[0].IsIncomplete { + t.Errorf("Files should not be incomplete! %v", result.Files[0]) + } + result, err = ParsePatch(40, 5, setting.Git.MaxGitDiffFiles, strings.NewReader(diff)) + if err != nil { + t.Errorf("There should not be an error: %v", err) + } + if !result.Files[0].IsIncomplete { + t.Errorf("Files should be incomplete! %v", result.Files[0]) + } + + // Test max characters + diff = `diff --git a/newfile2 b/newfile2 +new file mode 100644 +index 0000000..6bb8f39 +--- /dev/null ++++ b/newfile2 +@@ -0,0 +1,35 @@ +` + diffBuilder.Reset() + diffBuilder.WriteString(diff) + + for i := 0; i < 33; i++ { + diffBuilder.WriteString("+line" + strconv.Itoa(i) + "\n") + } + diffBuilder.WriteString("+line33") + for i := 0; i < 512; i++ { + diffBuilder.WriteString("0123456789ABCDEF") + } + diffBuilder.WriteByte('\n') + diffBuilder.WriteString("+line" + strconv.Itoa(34) + "\n") + diffBuilder.WriteString("+line" + strconv.Itoa(35) + "\n") + diff = diffBuilder.String() + + result, err = ParsePatch(20, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff)) + if err != nil { + t.Errorf("There should not be an error: %v", err) + } + if !result.Files[0].IsIncomplete { + t.Errorf("Files should be incomplete! %v", result.Files[0]) + } + result, err = ParsePatch(40, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff)) + if err != nil { + t.Errorf("There should not be an error: %v", err) + } + if !result.Files[0].IsIncomplete { + t.Errorf("Files should be incomplete! %v", result.Files[0]) + } + + diff = `diff --git "a/README.md" "b/README.md" --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ @@ -53,7 +293,7 @@ func TestParsePatch(t *testing.T) { Docker Pulls + cut off + cut off` - result, err := ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff)) + result, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff)) if err != nil { t.Errorf("ParsePatch failed: %s", err) } @@ -76,6 +316,23 @@ func TestParsePatch(t *testing.T) { } println(result) + var diff2a = `diff --git "a/A \\ B" b/A/B +--- "a/A \\ B" ++++ b/A/B +@@ -1,3 +1,6 @@ + # gitea-github-migrator ++ ++ Build Status +- Latest Release + Docker Pulls ++ cut off ++ cut off` + result, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2a)) + if err != nil { + t.Errorf("ParsePatch failed: %s", err) + } + println(result) + var diff3 = `diff --git a/README.md b/README.md --- a/README.md +++ b/README.md diff --git a/services/mailer/mail_issue.go b/services/mailer/mail_issue.go index 1030a9548e..01c198984b 100644 --- a/services/mailer/mail_issue.go +++ b/services/mailer/mail_issue.go @@ -118,7 +118,7 @@ func mailIssueCommentBatch(ctx *mailCommentContext, ids []int64, visited map[int visited[id] = true } } - recipients, err := models.GetMaileableUsersByIDs(unique) + recipients, err := models.GetMaileableUsersByIDs(unique, fromMention) if err != nil { return err } diff --git a/services/mirror/mirror.go b/services/mirror/mirror.go index 165e7cd35b..1d60e97583 100644 --- a/services/mirror/mirror.go +++ b/services/mirror/mirror.go @@ -90,8 +90,8 @@ func AddressNoCredentials(m *models.Mirror) string { return u.String() } -// SaveAddress writes new address to Git repository config. -func SaveAddress(m *models.Mirror, addr string) error { +// UpdateAddress writes new address to Git repository and database +func UpdateAddress(m *models.Mirror, addr string) error { repoPath := m.Repo.RepoPath() // Remove old origin _, err := git.NewCommand("remote", "rm", "origin").RunInDir(repoPath) @@ -99,8 +99,12 @@ func SaveAddress(m *models.Mirror, addr string) error { return err } - _, err = git.NewCommand("remote", "add", "origin", "--mirror=fetch", addr).RunInDir(repoPath) - return err + if _, err = git.NewCommand("remote", "add", "origin", "--mirror=fetch", addr).RunInDir(repoPath); err != nil { + return err + } + + m.Repo.OriginalURL = addr + return models.UpdateRepositoryCols(m.Repo, "original_url") } // gitShortEmptySha Git short empty SHA diff --git a/services/pull/merge.go b/services/pull/merge.go index 47521ce147..27689384a5 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -544,7 +544,7 @@ func IsUserAllowedToMerge(pr *models.PullRequest, p models.Permission, user *mod return false, err } - if (p.CanWrite(models.UnitTypeCode) && pr.ProtectedBranch == nil) || (pr.ProtectedBranch != nil && pr.ProtectedBranch.IsUserMergeWhitelisted(user.ID)) { + if (p.CanWrite(models.UnitTypeCode) && pr.ProtectedBranch == nil) || (pr.ProtectedBranch != nil && pr.ProtectedBranch.IsUserMergeWhitelisted(user.ID, p)) { return true, nil } diff --git a/services/pull/pull.go b/services/pull/pull.go index fb4af06372..32c2775bc8 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -9,8 +9,6 @@ import ( "bytes" "context" "fmt" - "os" - "path" "strings" "time" @@ -128,7 +126,16 @@ func ChangeTargetBranch(pr *models.PullRequest, doer *models.User, targetBranch if pr.Status == models.PullRequestStatusChecking { pr.Status = models.PullRequestStatusMergeable } - if err := pr.UpdateColsIfNotMerged("merge_base", "status", "conflicted_files", "base_branch"); err != nil { + + // Update Commit Divergence + divergence, err := GetDiverging(pr) + if err != nil { + return err + } + pr.CommitsAhead = divergence.Ahead + pr.CommitsBehind = divergence.Behind + + if err := pr.UpdateColsIfNotMerged("merge_base", "status", "conflicted_files", "base_branch", "commits_ahead", "commits_behind"); err != nil { return err } @@ -168,18 +175,6 @@ func checkForInvalidation(requests models.PullRequestList, repoID int64, doer *m return nil } -func addHeadRepoTasks(prs []*models.PullRequest) { - for _, pr := range prs { - log.Trace("addHeadRepoTasks[%d]: composing new test task", pr.ID) - if err := PushToBaseRepo(pr); err != nil { - log.Error("PushToBaseRepo: %v", err) - continue - } - - AddToTaskQueue(pr) - } -} - // AddTestPullRequestTask adds new test tasks by given head/base repository and head/base branch, // and generate new patch for testing as needed. func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSync bool, oldCommitID, newCommitID string) { @@ -236,7 +231,15 @@ func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSy } } - addHeadRepoTasks(prs) + for _, pr := range prs { + log.Trace("Updating PR[%d]: composing new test task", pr.ID) + if err := PushToBaseRepo(pr); err != nil { + log.Error("PushToBaseRepo: %v", err) + continue + } + + AddToTaskQueue(pr) + } log.Trace("AddTestPullRequestTask [base_repo_id: %d, base_branch: %s]: finding pull requests", repoID, branch) prs, err = models.GetUnmergedPullRequestsByBaseInfo(repoID, branch) @@ -336,54 +339,17 @@ func checkIfPRContentChanged(pr *models.PullRequest, oldCommitID, newCommitID st func PushToBaseRepo(pr *models.PullRequest) (err error) { log.Trace("PushToBaseRepo[%d]: pushing commits to base repo '%s'", pr.BaseRepoID, pr.GetGitRefName()) - // Clone base repo. - tmpBasePath, err := models.CreateTemporaryPath("pull") - if err != nil { - log.Error("CreateTemporaryPath: %v", err) - return err - } - defer func() { - err := models.RemoveTemporaryPath(tmpBasePath) - if err != nil { - log.Error("Error whilst removing temporary path: %s Error: %v", tmpBasePath, err) - } - }() - if err := pr.LoadHeadRepo(); err != nil { log.Error("Unable to load head repository for PR[%d] Error: %v", pr.ID, err) return err } headRepoPath := pr.HeadRepo.RepoPath() - if err := git.Clone(headRepoPath, tmpBasePath, git.CloneRepoOptions{ - Bare: true, - Shared: true, - Branch: pr.HeadBranch, - Quiet: true, - }); err != nil { - log.Error("git clone tmpBasePath: %v", err) - return err - } - gitRepo, err := git.OpenRepository(tmpBasePath) - if err != nil { - return fmt.Errorf("OpenRepository: %v", err) - } - if err := pr.LoadBaseRepo(); err != nil { log.Error("Unable to load base repository for PR[%d] Error: %v", pr.ID, err) return err } - if err := gitRepo.AddRemote("base", pr.BaseRepo.RepoPath(), false); err != nil { - return fmt.Errorf("tmpGitRepo.AddRemote: %v", err) - } - defer gitRepo.Close() - - headFile := pr.GetGitRefName() - - // Remove head in case there is a conflict. - file := path.Join(pr.BaseRepo.RepoPath(), headFile) - - _ = os.Remove(file) + baseRepoPath := pr.BaseRepo.RepoPath() if err = pr.LoadIssue(); err != nil { return fmt.Errorf("unable to load issue %d for pr %d: %v", pr.IssueID, pr.ID, err) @@ -392,14 +358,26 @@ func PushToBaseRepo(pr *models.PullRequest) (err error) { return fmt.Errorf("unable to load poster %d for pr %d: %v", pr.Issue.PosterID, pr.ID, err) } - if err = git.Push(tmpBasePath, git.PushOptions{ - Remote: "base", - Branch: fmt.Sprintf("%s:%s", pr.HeadBranch, headFile), + gitRefName := pr.GetGitRefName() + + if err := git.Push(headRepoPath, git.PushOptions{ + Remote: baseRepoPath, + Branch: pr.HeadBranch + ":" + gitRefName, Force: true, // Use InternalPushingEnvironment here because we know that pre-receive and post-receive do not run on a refs/pulls/... Env: models.InternalPushingEnvironment(pr.Issue.Poster, pr.BaseRepo), }); err != nil { - return fmt.Errorf("Push: %s:%s %s:%s %v", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), headFile, err) + if git.IsErrPushOutOfDate(err) { + // This should not happen as we're using force! + log.Error("Unable to push PR head for %s#%d (%-v:%s) due to ErrPushOfDate: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, err) + return err + } else if git.IsErrPushRejected(err) { + rejectErr := err.(*git.ErrPushRejected) + log.Info("Unable to push PR head for %s#%d (%-v:%s) due to rejection:\nStdout: %s\nStderr: %s\nError: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, rejectErr.StdOut, rejectErr.StdErr, rejectErr.Err) + return err + } + log.Error("Unable to push PR head for %s#%d (%-v:%s) due to Error: %v", pr.BaseRepo.FullName(), pr.Index, pr.BaseRepo, gitRefName, err) + return fmt.Errorf("Push: %s:%s %s:%s %v", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), gitRefName, err) } return nil @@ -589,7 +567,7 @@ func GetCommitMessages(pr *models.PullRequest) string { } element = element.Next() } - + skip += limit } } diff --git a/services/pull/review.go b/services/pull/review.go index 25e0ca858a..09ab3ff567 100644 --- a/services/pull/review.go +++ b/services/pull/review.go @@ -8,6 +8,7 @@ package pull import ( "bytes" "fmt" + "regexp" "strings" "code.gitea.io/gitea/models" @@ -29,7 +30,7 @@ func CreateCodeComment(doer *models.User, gitRepo *git.Repository, issue *models // - Comments that are part of a review // - Comments that reply to an existing review - if !isReview { + if !isReview && replyReviewID != 0 { // It's not part of a review; maybe a reply to a review comment or a single comment. // Check if there are reviews for that line already; if there are, this is a reply if existsReview, err = models.ReviewExists(issue, treePath, line); err != nil { @@ -104,6 +105,8 @@ func CreateCodeComment(doer *models.User, gitRepo *git.Repository, issue *models return comment, nil } +var notEnoughLines = regexp.MustCompile(`exit status 128 - fatal: file .* has only \d+ lines?`) + // createCodeComment creates a plain code comment at the specified line / path func createCodeComment(doer *models.User, repo *models.Repository, issue *models.Issue, content, treePath string, line, reviewID int64) (*models.Comment, error) { var commitID, patch string @@ -127,7 +130,7 @@ func createCodeComment(doer *models.User, repo *models.Repository, issue *models commit, err := gitRepo.LineBlame(pr.GetGitRefName(), gitRepo.Path, treePath, uint(line)) if err == nil { commitID = commit.ID.String() - } else if !strings.Contains(err.Error(), "exit status 128 - fatal: no such path") { + } else if !(strings.Contains(err.Error(), "exit status 128 - fatal: no such path") || notEnoughLines.MatchString(err.Error())) { return nil, fmt.Errorf("LineBlame[%s, %s, %s, %d]: %v", pr.GetGitRefName(), gitRepo.Path, treePath, line, err) } } diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index 91f48d0626..45cd10b65b 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -100,7 +100,7 @@ func createTemporaryRepo(pr *models.PullRequest) (string, error) { outbuf.Reset() errbuf.Reset() - if err := git.NewCommand("fetch", "origin", "--no-tags", pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil { + if err := git.NewCommand("fetch", "origin", "--no-tags", "--", pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil { log.Error("Unable to fetch origin base branch [%s:%s -> base, original_base in %s]: %v:\n%s\n%s", pr.BaseRepo.FullName(), pr.BaseBranch, tmpBasePath, err, outbuf.String(), errbuf.String()) if err := models.RemoveTemporaryPath(tmpBasePath); err != nil { log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err) @@ -140,7 +140,7 @@ func createTemporaryRepo(pr *models.PullRequest) (string, error) { trackingBranch := "tracking" // Fetch head branch - if err := git.NewCommand("fetch", "--no-tags", remoteRepoName, pr.HeadBranch+":"+trackingBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil { + if err := git.NewCommand("fetch", "--no-tags", remoteRepoName, git.BranchPrefix+pr.HeadBranch+":"+trackingBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil { log.Error("Unable to fetch head_repo head branch [%s:%s -> tracking in %s]: %v:\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, tmpBasePath, err, outbuf.String(), errbuf.String()) if err := models.RemoveTemporaryPath(tmpBasePath); err != nil { log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err) diff --git a/services/release/release.go b/services/release/release.go index 3105ce24ae..64d132cd73 100644 --- a/services/release/release.go +++ b/services/release/release.go @@ -46,6 +46,7 @@ func createTag(gitRepo *git.Repository, rel *models.Release) error { rel.Publisher, rel.Repo, git.TagPrefix+rel.TagName, git.EmptySHA, commit.ID.String(), repository.NewPushCommits()) notification.NotifyCreateRef(rel.Publisher, rel.Repo, "tag", git.TagPrefix+rel.TagName) + rel.CreatedUnix = timeutil.TimeStampNow() } commit, err := gitRepo.GetTagCommit(rel.TagName) if err != nil { @@ -53,7 +54,6 @@ func createTag(gitRepo *git.Repository, rel *models.Release) error { } rel.Sha1 = commit.ID.String() - rel.CreatedUnix = timeutil.TimeStampNow() rel.NumCommits, err = commit.CommitsCount() if err != nil { return fmt.Errorf("CommitsCount: %v", err) diff --git a/services/release/release_test.go b/services/release/release_test.go index effab21251..d5673b73b8 100644 --- a/services/release/release_test.go +++ b/services/release/release_test.go @@ -7,6 +7,7 @@ package release import ( "path/filepath" "testing" + "time" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" @@ -101,3 +102,153 @@ func TestRelease_Create(t *testing.T) { IsTag: true, }, nil)) } + +func TestRelease_Update(t *testing.T) { + assert.NoError(t, models.PrepareTestDatabase()) + + user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) + repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) + repoPath := models.RepoPath(user.Name, repo.Name) + + gitRepo, err := git.OpenRepository(repoPath) + assert.NoError(t, err) + defer gitRepo.Close() + + // Test a changed release + assert.NoError(t, CreateRelease(gitRepo, &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v1.1.1", + Target: "master", + Title: "v1.1.1 is released", + Note: "v1.1.1 is released", + IsDraft: false, + IsPrerelease: false, + IsTag: false, + }, nil)) + release, err := models.GetRelease(repo.ID, "v1.1.1") + assert.NoError(t, err) + releaseCreatedUnix := release.CreatedUnix + time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp + release.Note = "Changed note" + assert.NoError(t, UpdateRelease(user, gitRepo, release, nil)) + release, err = models.GetReleaseByID(release.ID) + assert.NoError(t, err) + assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) + + // Test a changed draft + assert.NoError(t, CreateRelease(gitRepo, &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v1.2.1", + Target: "65f1bf2", + Title: "v1.2.1 is draft", + Note: "v1.2.1 is draft", + IsDraft: true, + IsPrerelease: false, + IsTag: false, + }, nil)) + release, err = models.GetRelease(repo.ID, "v1.2.1") + assert.NoError(t, err) + releaseCreatedUnix = release.CreatedUnix + time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp + release.Title = "Changed title" + assert.NoError(t, UpdateRelease(user, gitRepo, release, nil)) + release, err = models.GetReleaseByID(release.ID) + assert.NoError(t, err) + assert.Less(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) + + // Test a changed pre-release + assert.NoError(t, CreateRelease(gitRepo, &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v1.3.1", + Target: "65f1bf2", + Title: "v1.3.1 is pre-released", + Note: "v1.3.1 is pre-released", + IsDraft: false, + IsPrerelease: true, + IsTag: false, + }, nil)) + release, err = models.GetRelease(repo.ID, "v1.3.1") + assert.NoError(t, err) + releaseCreatedUnix = release.CreatedUnix + time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp + release.Title = "Changed title" + release.Note = "Changed note" + assert.NoError(t, UpdateRelease(user, gitRepo, release, nil)) + release, err = models.GetReleaseByID(release.ID) + assert.NoError(t, err) + assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) +} + +func TestRelease_createTag(t *testing.T) { + assert.NoError(t, models.PrepareTestDatabase()) + + user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) + repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) + repoPath := models.RepoPath(user.Name, repo.Name) + + gitRepo, err := git.OpenRepository(repoPath) + assert.NoError(t, err) + defer gitRepo.Close() + + // Test a changed release + release := &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v2.1.1", + Target: "master", + Title: "v2.1.1 is released", + Note: "v2.1.1 is released", + IsDraft: false, + IsPrerelease: false, + IsTag: false, + } + assert.NoError(t, createTag(gitRepo, release)) + assert.NotEmpty(t, release.CreatedUnix) + releaseCreatedUnix := release.CreatedUnix + time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp + release.Note = "Changed note" + assert.NoError(t, createTag(gitRepo, release)) + assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) + + // Test a changed draft + release = &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v2.2.1", + Target: "65f1bf2", + Title: "v2.2.1 is draft", + Note: "v2.2.1 is draft", + IsDraft: true, + IsPrerelease: false, + IsTag: false, + } + assert.NoError(t, createTag(gitRepo, release)) + releaseCreatedUnix = release.CreatedUnix + time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp + release.Title = "Changed title" + assert.NoError(t, createTag(gitRepo, release)) + assert.Less(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) + + // Test a changed pre-release + release = &models.Release{ + RepoID: repo.ID, + PublisherID: user.ID, + TagName: "v2.3.1", + Target: "65f1bf2", + Title: "v2.3.1 is pre-released", + Note: "v2.3.1 is pre-released", + IsDraft: false, + IsPrerelease: true, + IsTag: false, + } + assert.NoError(t, createTag(gitRepo, release)) + releaseCreatedUnix = release.CreatedUnix + time.Sleep(2 * time.Second) // sleep 2 seconds to ensure a different timestamp + release.Title = "Changed title" + release.Note = "Changed note" + assert.NoError(t, createTag(gitRepo, release)) + assert.Equal(t, int64(releaseCreatedUnix), int64(release.CreatedUnix)) +} diff --git a/services/repository/repository.go b/services/repository/repository.go index f50b98b640..4ebfae6200 100644 --- a/services/repository/repository.go +++ b/services/repository/repository.go @@ -54,13 +54,11 @@ func DeleteRepository(doer *models.User, repo *models.Repository) error { log.Error("CloseRepoBranchesPulls failed: %v", err) } - if err := models.DeleteRepository(doer, repo.OwnerID, repo.ID); err != nil { - return err - } - + // If the repo itself has webhooks, we need to trigger them before deleting it... notification.NotifyDeleteRepository(doer, repo) - return nil + err := models.DeleteRepository(doer, repo.OwnerID, repo.ID) + return err } // PushCreateRepo creates a repository when a new repository is pushed to an appropriate namespace diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl index affed1634f..c1ac8fb489 100644 --- a/templates/admin/dashboard.tmpl +++ b/templates/admin/dashboard.tmpl @@ -15,7 +15,7 @@ {{.i18n.Tr "admin.dashboard.operations"}}
-
+ {{.CsrfTokenHtml}} @@ -53,8 +53,8 @@ - - + + diff --git a/templates/admin/hook_new.tmpl b/templates/admin/hook_new.tmpl index 65f567b5dc..26169acaa0 100644 --- a/templates/admin/hook_new.tmpl +++ b/templates/admin/hook_new.tmpl @@ -26,6 +26,8 @@ {{else if eq .HookType "feishu"}} + {{else if eq .HookType "matrix"}} + {{end}} @@ -38,6 +40,7 @@ {{template "repo/settings/webhook/telegram" .}} {{template "repo/settings/webhook/msteams" .}} {{template "repo/settings/webhook/feishu" .}} + {{template "repo/settings/webhook/matrix" .}} {{template "repo/settings/webhook/history" .}} diff --git a/templates/admin/monitor.tmpl b/templates/admin/monitor.tmpl index 26fbcb60ac..8dd0d939d7 100644 --- a/templates/admin/monitor.tmpl +++ b/templates/admin/monitor.tmpl @@ -7,7 +7,8 @@ {{.i18n.Tr "admin.monitor.cron"}}
- + + {{.CsrfTokenHtml}}
{{.i18n.Tr "admin.dashboard.git_fsck"}}{{.i18n.Tr "admin.dashboard.repo_health_check"}}
{{.i18n.Tr "admin.dashboard.delete_generated_repository_avatars"}}
diff --git a/templates/admin/notice.tmpl b/templates/admin/notice.tmpl index 7d1720becd..5311ad8f79 100644 --- a/templates/admin/notice.tmpl +++ b/templates/admin/notice.tmpl @@ -7,7 +7,7 @@ {{.i18n.Tr "admin.notices.system_notice_list"}} ({{.i18n.Tr "admin.total" .Total}})
-
+
@@ -28,9 +28,9 @@ - - - + + + {{end}} @@ -73,10 +73,11 @@ -
{{.ID}} {{$.i18n.Tr .TrStr}}{{SubStr .Description 0 120}}...{{.CreatedUnix.FormatShort}}{{.Description}}{{.CreatedUnix.FormatShort}}