81 Commits

Author SHA1 Message Date
6205151d53 Merge pull request 'Update dependency dotenv to v11' (#13) from renovate/dotenv-11.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #13
2022-01-12 16:29:24 +00:00
4861ca7f3e Update dependency dotenv to v11
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2022-01-11 07:02:02 +00:00
efb11f6047 Enabled dep dashboard
All checks were successful
continuous-integration/drone/push Build is passing
2021-10-15 16:23:21 +02:00
e95ca8045a Merge pull request 'Update dependency knex to ^0.95.0' (#5) from renovate/knex-0.x into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #5
2021-10-15 14:22:03 +00:00
2b93f3ea8a Update dependency knex to ^0.95.0
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-10-15 14:18:41 +00:00
2a7a32fda6 Merge pull request 'Configure Renovate' (#4) from renovate/configure into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #4
2021-10-15 14:17:08 +00:00
d7428af1d8 Add renovate.json
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
2021-10-15 14:16:47 +00:00
3ca5f6b3b4 Preleminary emoji support
All checks were successful
continuous-integration/drone/push Build is passing
2021-09-25 19:29:23 +02:00
eb96408d33 Working clientside stuff
All checks were successful
continuous-integration/drone/push Build is passing
closes #3
2021-09-25 18:45:52 +02:00
11bd1b4f1f Added 'clientside' flag to getters and setters 2021-09-25 18:28:49 +02:00
e3214084f6 Added migration for clientside redirects
ref #3
2021-09-25 18:25:53 +02:00
3803ac9197 🚀RELEASE 0.6.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-09-25 18:03:09 +02:00
e1621b72ad Added rudementary page content
All checks were successful
continuous-integration/drone/push Build is passing
2021-09-25 17:44:34 +02:00
b64a8436e7 Updated opengraph type
ref #2
2021-09-25 17:42:44 +02:00
d8ed9a149f Switched docker base images to odit mirror 2021-09-25 17:38:11 +02:00
9d7125a311 Now with custom opengraph (tm)
All checks were successful
continuous-integration/drone/push Build is passing
ref #2
2021-09-25 17:35:52 +02:00
6d71a3ebf4 Removed unused log
All checks were successful
continuous-integration/drone/push Build is passing
2021-09-25 17:27:59 +02:00
75adbf73cf Now with working bad bot detection
ref #2
2021-09-25 17:27:41 +02:00
e5b8557e4c Getters now return the no_preview status 2021-09-25 17:21:30 +02:00
33d7c94648 New urls can now be created with disabled preview
ref #2
2021-09-25 17:19:36 +02:00
f6b2ae523d Added bot check for native short urls
ref #2
2021-09-25 17:17:42 +02:00
0a500f16cd Added migration for disallowing bot previews 2021-09-25 17:16:38 +02:00
61da5d8110 Added basic bot checking 2021-09-25 17:14:34 +02:00
773b286216 Added package for bot recognition 2021-09-25 17:12:52 +02:00
d097eccbd9 removed logging 2021-09-25 17:12:22 +02:00
f15282a3f9 Log user agents
All checks were successful
continuous-integration/drone/push Build is passing
2021-09-25 17:09:19 +02:00
0a8945a294 Added noindex header to all shorturl routes
All checks were successful
continuous-integration/drone/push Build is passing
ref #2
2021-09-25 16:59:28 +02:00
b871e4295d 🚀RELEASE 0.5.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-21 10:03:16 +02:00
0945060a49 Added optional filtering by provider 2021-08-21 10:02:52 +02:00
f7eae96b8c Shortened return to avoid variable memory asignment 2021-08-21 10:01:24 +02:00
c2a50a1480 Changed object property order (just for us pesky humans to improve readability) 2021-08-21 09:59:57 +02:00
bb99c2dcd1 Added endpoint to query over all visited urls 2021-08-21 09:59:14 +02:00
e8382fb579 🚀RELEASE 0.5.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-21 09:56:21 +02:00
b5321377bd Reverted last change since we can defer it from the provider 2021-08-21 09:54:55 +02:00
6e26bbbf5f Changed the way visits entrys get compiled to enable provider visits count searches over the default api 2021-08-21 09:53:17 +02:00
59e178476e Removed visits 404 resolution 2021-08-21 09:51:25 +02:00
824c109a42 Server now inserts provider on visit 2021-08-21 09:49:45 +02:00
f48159b31b Added migration for visits provider 2021-08-21 09:46:28 +02:00
6195001d4b Added package script for migration creation 2021-08-21 09:45:57 +02:00
0afa80345d 🚀RELEASE 0.4.3
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-21 07:35:41 +02:00
dbb0d177b8 Fixed auth error crashing the entire server thanks to fastify handling stuff not the same way that they do in the docs.....
closes #1
2021-08-21 07:35:13 +02:00
4ffc06db7b 🚀RELEASE 0.4.2
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-18 17:47:16 +02:00
588f3bae89 Changed register api route and added user deletion route 2021-08-18 17:46:49 +02:00
d889432ce8 🚀RELEASE 0.4.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-18 17:39:01 +02:00
44830f08bc Fixed jwtcount not being recognized 2021-08-18 17:38:47 +02:00
1cd3ebf8c5 🚀RELEASE 0.4.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-18 16:23:39 +02:00
558b69eeaa Implemented jwt count validation and update on logout 2021-08-18 16:22:50 +02:00
2b22063a81 All authenticated entpoints now accept jwtauth 2021-08-18 16:10:59 +02:00
48cc380504 Implemented jwtcount basics 2021-08-18 16:09:34 +02:00
75473cabe7 Basic jwt implementation :party: 2021-08-18 15:57:23 +02:00
6420ffb055 Switched to fastify-auth to support multiple auth providers 2021-08-18 15:36:16 +02:00
a62ee63c83 🚀RELEASE 0.3.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-18 15:22:49 +02:00
c89f2a2939 Added stats api route 2021-08-18 15:21:36 +02:00
d51c58867d Added comments 2021-08-16 15:19:04 +02:00
2fa520fdde Added author info
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-14 16:02:40 +02:00
5bb7212420 Added license 2021-08-14 16:00:45 +02:00
2226705e3f Updated readme 2021-08-14 15:52:56 +02:00
72932955d1 🚀RELEASE 0.2.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-14 15:48:18 +02:00
339e2f39d8 Ebay provider resolution 2021-08-14 15:47:58 +02:00
12c6d7e3da Added ebay provider recognition 2021-08-14 15:47:03 +02:00
1624e666e8 Now recognizing with and without protocol 2021-08-14 15:46:14 +02:00
86f4cd00ea 🚀RELEASE 0.1.4
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-14 14:19:30 +02:00
518aa3eb08 Added cors 2021-08-14 14:19:08 +02:00
86985ef735 🚀RELEASE 0.1.3
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-14 13:23:38 +02:00
fef7daaf96 Weired knex env fix 2021-08-14 13:23:11 +02:00
b14fa05adc 🚀RELEASE 0.1.2
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-14 13:10:00 +02:00
7c71e94304 Added optional db volume to docker-compose 2021-08-14 13:09:40 +02:00
8fa489f2bc Changed the way that the migration get's triggered 2021-08-14 13:09:25 +02:00
512acc0b8c Prod db now resides in db folder
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-14 12:56:02 +02:00
567ac07612 Merge branch 'main' of git.odit.services:kauft.es/linkylinky into main
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-14 11:50:35 +02:00
fa01864d0d API Endpoint to get all short urls 2021-08-14 11:50:29 +02:00
91b25c22ca Get all api endpoints 2021-08-14 11:50:03 +02:00
55d6b91cc2 🚀RELEASE 0.1.1
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-14 11:06:45 +02:00
807eb9c267 fix: Dockerfile
Some checks reported errors
continuous-integration/drone/push Build was killed
2021-08-14 11:06:16 +02:00
e02d91e662 🚀RELEASE 0.1.0
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-14 10:46:36 +02:00
8d9cf8d1b3 Merge branch 'main' of https://git.odit.services/kauft.es/linkylinky
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-14 10:44:46 +02:00
d97450cf53 add lockfile [skip-ci] 2021-08-14 10:44:41 +02:00
fd0a586ed6 Added tag commit args
Some checks failed
continuous-integration/drone/push Build is failing
2021-08-14 10:44:31 +02:00
af6500ccb4 Now signing release commits 2021-08-14 10:43:29 +02:00
9a3c55d235 Merge branch 'main' of https://git.odit.services/kauft.es/linkylinky
Some checks failed
continuous-integration/drone/push Build is failing
2021-08-14 10:42:51 +02:00
86ef277c90 smaller Dockerfile [skip-ci] 2021-08-14 10:42:42 +02:00
17 changed files with 5068 additions and 56 deletions

3
.env
View File

@@ -1,3 +1,4 @@
SSL=false
SSL=true
DOMAIN=kauft.es
DISABLE_PROVIDERS=false
ENABLE_REGISTER=true

1
.gitignore vendored
View File

@@ -58,7 +58,6 @@ jspm_packages/
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
yarn.lock
package-lock.json
*.sqlite*

View File

@@ -2,11 +2,148 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [0.6.0](https://git.odit.services/kauft.es/linkylinky/compare/0.5.1...0.6.0)
- Now with custom opengraph (tm) [`9d7125a`](https://git.odit.services/kauft.es/linkylinky/commit/9d7125a31186f3b7f33df4875db12c67cf91f536)
- Added rudementary page content [`e1621b7`](https://git.odit.services/kauft.es/linkylinky/commit/e1621b72ade1fce381f30bcf310a6dcf8d1c65ea)
- Added migration for disallowing bot previews [`0a500f1`](https://git.odit.services/kauft.es/linkylinky/commit/0a500f16cde0b0e38a115dd4e76185a2a45dda49)
- Added basic bot checking [`61da5d8`](https://git.odit.services/kauft.es/linkylinky/commit/61da5d81108a4b86f92e1c05ca99372c6b188347)
- Now with working bad bot detection [`75adbf7`](https://git.odit.services/kauft.es/linkylinky/commit/75adbf73cfbf4fadf2cd632ecb687eff95749f52)
- New urls can now be created with disabled preview [`33d7c94`](https://git.odit.services/kauft.es/linkylinky/commit/33d7c94648d062ece3fa437e71ce1ded70324cd8)
- Added bot check for native short urls [`f6b2ae5`](https://git.odit.services/kauft.es/linkylinky/commit/f6b2ae523da149b72f2be6d9171584cdc0be6e99)
- Added package for bot recognition [`773b286`](https://git.odit.services/kauft.es/linkylinky/commit/773b286216c9e530ccdf3fbfcfe95fa938097be5)
- Getters now return the no_preview status [`e5b8557`](https://git.odit.services/kauft.es/linkylinky/commit/e5b8557e4ccae90981e675c2adae81236aa9144e)
- Added noindex header to all shorturl routes [`0a8945a`](https://git.odit.services/kauft.es/linkylinky/commit/0a8945a294de2bc5bce9410f3ebf20b8f5abd0a5)
- Switched docker base images to odit mirror [`d8ed9a1`](https://git.odit.services/kauft.es/linkylinky/commit/d8ed9a149fddae8e8cc61b78cbc940a9d7ade8f2)
- Updated opengraph type [`b64a843`](https://git.odit.services/kauft.es/linkylinky/commit/b64a8436e745d176cc49ef72434dce0f8f1bcc12)
- Log user agents [`f15282a`](https://git.odit.services/kauft.es/linkylinky/commit/f15282a3f9bdaaf09a36d8662b64a5bc2740633f)
- Removed unused log [`6d71a3e`](https://git.odit.services/kauft.es/linkylinky/commit/6d71a3ebf4d880b8291cacd620f86416cff0d744)
- removed logging [`d097ecc`](https://git.odit.services/kauft.es/linkylinky/commit/d097eccbd925e3627fa710d7891d269b372d174c)
#### [0.5.1](https://git.odit.services/kauft.es/linkylinky/compare/0.5.0...0.5.1)
> 21 August 2021
- 🚀RELEASE 0.5.1 [`b871e42`](https://git.odit.services/kauft.es/linkylinky/commit/b871e4295dc4b067f4f4dd28c3f940c8aa9624e0)
- Added endpoint to query over all visited urls [`bb99c2d`](https://git.odit.services/kauft.es/linkylinky/commit/bb99c2dcd1ce89af1bc27a035be5265345d2a05f)
- Added optional filtering by provider [`0945060`](https://git.odit.services/kauft.es/linkylinky/commit/0945060a49ed35c038df2c04bbd07174bc5654ca)
- Shortened return to avoid variable memory asignment [`f7eae96`](https://git.odit.services/kauft.es/linkylinky/commit/f7eae96b8c3479d333fc00bc36bce451733700db)
- Changed object property order (just for us pesky humans to improve readability) [`c2a50a1`](https://git.odit.services/kauft.es/linkylinky/commit/c2a50a14807e223987464c63fac6d67ed98b1a93)
#### [0.5.0](https://git.odit.services/kauft.es/linkylinky/compare/0.4.3...0.5.0)
> 21 August 2021
- 🚀RELEASE 0.5.0 [`e8382fb`](https://git.odit.services/kauft.es/linkylinky/commit/e8382fb579f769364693974cbe74ce06e9810a9a)
- Removed visits 404 resolution [`59e1784`](https://git.odit.services/kauft.es/linkylinky/commit/59e178476e8f7e64de92ae23e859b87680e7af64)
- Added migration for visits provider [`f48159b`](https://git.odit.services/kauft.es/linkylinky/commit/f48159b31bcaf7c7449c89fb1e3851bcb04f5e3c)
- Reverted last change since we can defer it from the provider [`b532137`](https://git.odit.services/kauft.es/linkylinky/commit/b5321377bde9bd7de13e2eee4dd38a072cf0d4a3)
- Changed the way visits entrys get compiled to enable provider visits count searches over the default api [`6e26bbb`](https://git.odit.services/kauft.es/linkylinky/commit/6e26bbbf5f29e4c1eaa56c5dc41ab77c192d0cfb)
- Server now inserts provider on visit [`824c109`](https://git.odit.services/kauft.es/linkylinky/commit/824c109a420efd0e1e6de01d93827020f3fe5a5f)
- Added package script for migration creation [`6195001`](https://git.odit.services/kauft.es/linkylinky/commit/6195001d4b701d39470ff4be0e265f9afb288e78)
#### [0.4.3](https://git.odit.services/kauft.es/linkylinky/compare/0.4.2...0.4.3)
> 21 August 2021
- Fixed auth error crashing the entire server thanks to fastify handling stuff not the same way that they do in the docs..... [`#1`](https://git.odit.services/kauft.es/linkylinky/issues/1)
- 🚀RELEASE 0.4.3 [`0afa803`](https://git.odit.services/kauft.es/linkylinky/commit/0afa80345d47e09e20d4365634f8532248b2044c)
#### [0.4.2](https://git.odit.services/kauft.es/linkylinky/compare/0.4.1...0.4.2)
> 18 August 2021
- Changed register api route and added user deletion route [`588f3ba`](https://git.odit.services/kauft.es/linkylinky/commit/588f3bae8980f76461d20e15475ec797078b0b54)
- 🚀RELEASE 0.4.2 [`4ffc06d`](https://git.odit.services/kauft.es/linkylinky/commit/4ffc06db7bb84bc7bfc9c57a80927f7201185274)
#### [0.4.1](https://git.odit.services/kauft.es/linkylinky/compare/0.4.0...0.4.1)
> 18 August 2021
- 🚀RELEASE 0.4.1 [`d889432`](https://git.odit.services/kauft.es/linkylinky/commit/d889432ce8a403f6a609423eaf458a5904dc5b98)
- Fixed jwtcount not being recognized [`44830f0`](https://git.odit.services/kauft.es/linkylinky/commit/44830f08bc212f8079b5ac2da3d51eedbe6d5c41)
#### [0.4.0](https://git.odit.services/kauft.es/linkylinky/compare/0.3.0...0.4.0)
> 18 August 2021
- Basic jwt implementation :party: [`75473ca`](https://git.odit.services/kauft.es/linkylinky/commit/75473cabe79975296e473002e16d3abafbd2635e)
- Implemented jwtcount basics [`48cc380`](https://git.odit.services/kauft.es/linkylinky/commit/48cc380504206ea08b3a5082f19ad10bdd7cf773)
- Implemented jwt count validation and update on logout [`558b69e`](https://git.odit.services/kauft.es/linkylinky/commit/558b69eeaa78ea015473c674d5f919d64128a930)
- Switched to fastify-auth to support multiple auth providers [`6420ffb`](https://git.odit.services/kauft.es/linkylinky/commit/6420ffb055f08348c54cd08a193aba5fe5ebc13a)
- 🚀RELEASE 0.4.0 [`1cd3ebf`](https://git.odit.services/kauft.es/linkylinky/commit/1cd3ebf8c5a9413b93ab49c8813dad5c5c547cb2)
- All authenticated entpoints now accept jwtauth [`2b22063`](https://git.odit.services/kauft.es/linkylinky/commit/2b22063a81193c3d698525a050ef300e542c1f05)
#### [0.3.0](https://git.odit.services/kauft.es/linkylinky/compare/0.2.0...0.3.0)
> 18 August 2021
- Added license [`5bb7212`](https://git.odit.services/kauft.es/linkylinky/commit/5bb7212420ba102e743d62a47074191cdb264d2a)
- 🚀RELEASE 0.3.0 [`a62ee63`](https://git.odit.services/kauft.es/linkylinky/commit/a62ee63c838a64d7fd28ae110cad474e2c531995)
- Added stats api route [`c89f2a2`](https://git.odit.services/kauft.es/linkylinky/commit/c89f2a2939b658ffc688646ccce32fc0e1530583)
- Added author info [`2fa520f`](https://git.odit.services/kauft.es/linkylinky/commit/2fa520fdde1d55b2766b4b03e394e21a4f6cbae5)
- Updated readme [`2226705`](https://git.odit.services/kauft.es/linkylinky/commit/2226705e3f57d7d2f3ef5a79947c3ab44ec62c38)
- Added comments [`d51c588`](https://git.odit.services/kauft.es/linkylinky/commit/d51c58867d7508c84f26c236e38567bc6a4adbed)
#### [0.2.0](https://git.odit.services/kauft.es/linkylinky/compare/0.1.4...0.2.0)
> 14 August 2021
- 🚀RELEASE 0.2.0 [`7293295`](https://git.odit.services/kauft.es/linkylinky/commit/72932955d15976947dd553c5deba51cbf541b215)
- Added ebay provider recognition [`12c6d7e`](https://git.odit.services/kauft.es/linkylinky/commit/12c6d7e3da5cb4de6a597b4639f313b8e4319646)
- Ebay provider resolution [`339e2f3`](https://git.odit.services/kauft.es/linkylinky/commit/339e2f39d88d42a961e1e495f319dc0663cdc0a6)
- Now recognizing with and without protocol [`1624e66`](https://git.odit.services/kauft.es/linkylinky/commit/1624e666e83e0afe346bcacb105ea1a1535f0690)
#### [0.1.4](https://git.odit.services/kauft.es/linkylinky/compare/0.1.3...0.1.4)
> 14 August 2021
- Added cors [`518aa3e`](https://git.odit.services/kauft.es/linkylinky/commit/518aa3eb08cb72854812130d45b3b89afb074693)
- 🚀RELEASE 0.1.4 [`86f4cd0`](https://git.odit.services/kauft.es/linkylinky/commit/86f4cd00ea517f7e2cacbf69f2163eae597610ee)
#### [0.1.3](https://git.odit.services/kauft.es/linkylinky/compare/0.1.2...0.1.3)
> 14 August 2021
- Weired knex env fix [`fef7daa`](https://git.odit.services/kauft.es/linkylinky/commit/fef7daaf961e9112aa00f2ad22c3b0518ad258a7)
- 🚀RELEASE 0.1.3 [`86985ef`](https://git.odit.services/kauft.es/linkylinky/commit/86985ef7355c2db09dcd6c8e52ee7ebde3ed4128)
#### [0.1.2](https://git.odit.services/kauft.es/linkylinky/compare/0.1.1...0.1.2)
> 14 August 2021
- API Endpoint to get all short urls [`fa01864`](https://git.odit.services/kauft.es/linkylinky/commit/fa01864d0de7921e741d63c3f5795161279ea478)
- 🚀RELEASE 0.1.2 [`b14fa05`](https://git.odit.services/kauft.es/linkylinky/commit/b14fa05adc1ef8e34fd73bf5f495505df7d44b33)
- Changed the way that the migration get's triggered [`8fa489f`](https://git.odit.services/kauft.es/linkylinky/commit/8fa489f2bcd9d1ad63ab4581b7f3b27eee3d9038)
- Get all api endpoints [`91b25c2`](https://git.odit.services/kauft.es/linkylinky/commit/91b25c22ca035aec5cc2fdc80ca4fbb56a2f8b65)
- Added optional db volume to docker-compose [`7c71e94`](https://git.odit.services/kauft.es/linkylinky/commit/7c71e943041d8e3ac9dcf95cad27f2f0bc0b024c)
- Prod db now resides in db folder [`512acc0`](https://git.odit.services/kauft.es/linkylinky/commit/512acc0b8c15d4cfbafef21ec20707bac4629ea4)
#### [0.1.1](https://git.odit.services/kauft.es/linkylinky/compare/0.1.0...0.1.1)
> 14 August 2021
- 🚀RELEASE 0.1.1 [`55d6b91`](https://git.odit.services/kauft.es/linkylinky/commit/55d6b91cc252ee6676d13df9abd8b61283a07f0f)
- fix: Dockerfile [`807eb9c`](https://git.odit.services/kauft.es/linkylinky/commit/807eb9c267377df0b5f30f81eb380ef8a1c2add2)
#### [0.1.0](https://git.odit.services/kauft.es/linkylinky/compare/0.0.2...0.1.0)
> 14 August 2021
- add lockfile [skip-ci] [`d97450c`](https://git.odit.services/kauft.es/linkylinky/commit/d97450cf5389965d8183b5719aad7e9e6f0181ae)
- 🚀RELEASE 0.1.0 [`e02d91e`](https://git.odit.services/kauft.es/linkylinky/commit/e02d91e662e090b79b03ec77896100923464aa6b)
- smaller Dockerfile [skip-ci] [`86ef277`](https://git.odit.services/kauft.es/linkylinky/commit/86ef277c902aabb52acb5f846cb55406dc4d1095)
- Added tag commit args [`fd0a586`](https://git.odit.services/kauft.es/linkylinky/commit/fd0a586ed6e365801979c16d809a8254f64049be)
- Now signing release commits [`af6500c`](https://git.odit.services/kauft.es/linkylinky/commit/af6500ccb4792616f28bec77eda5c5e116422604)
#### 0.0.2
> 14 August 2021
- Migrated to knex [`823b211`](https://git.odit.services/kauft.es/linkylinky/commit/823b211c8c4fd4de3a6043696ca070101173aa1b)
- Added basics for auth [`6d417fa`](https://git.odit.services/kauft.es/linkylinky/commit/6d417fac1b4d77ab5552b75483cfc787d466e699)
- Initial [`ab17f91`](https://git.odit.services/kauft.es/linkylinky/commit/ab17f9148af6811a53bf323172d045cc71ecfb6d)
- 🚀RELEASE 0.0.2 [`a4bdb4d`](https://git.odit.services/kauft.es/linkylinky/commit/a4bdb4dca4aaba397688d43f1ec3a26cb2143dea)
- Added image builds by drone [`1a8410c`](https://git.odit.services/kauft.es/linkylinky/commit/1a8410c421e30001ae9623c19a8e72e0632ed920)
- Working registration/auth [`81b314a`](https://git.odit.services/kauft.es/linkylinky/commit/81b314ac55e9ab0cd603dda48473c0fe3db6c42e)
- Implemented short code generation via nanoid [`1550860`](https://git.odit.services/kauft.es/linkylinky/commit/15508606a41057857cce0d2ae16e389432c76960)

View File

@@ -1,15 +1,17 @@
FROM node:16-alpine as run
FROM registry.odit.services/hub/library/node:16.6.2-alpine3.14
WORKDIR /app
COPY package.json .
RUN yarn --prod
COPY yarn.lock .
RUN yarn --production --frozen-lockfile
COPY migrations ./migrations
COPY src ./src
COPY knexfile.js ./
RUN mkdir db
#
# FROM astefanutti/scratch-node:16.0.0
FROM registry.odit.services/hub/library/node:16.6.2-alpine3.14
WORKDIR /app
COPY --from=0 /app /app
ENV NODE_ENV production
EXPOSE 3000
WORKDIR /app
COPY migrations ./migrations
COPY src/server.js ./
COPY knexfile.js ./
CMD ["node", "./server.js"]
ENTRYPOINT ["/bin/sh", "-c", "yarn migrate && node ./src/server.js"]

24
LICENSE Normal file
View File

@@ -0,0 +1,24 @@
MIT License
-----------
Copyright (c) 2021 ODIT.Services (https://odit.services)
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,5 +1,8 @@
# LinkyLinky 🔗
> A small url shortener, originaly developed for kauft.es
<p align="center">
<img height="150" src="https://git.odit.services/user/avatar/kauft.es/140">
<h1 align="center">LinkyLinky 🔗</h1>
<h3 align="center">A small url shortener, originaly developed for kauft.es</h3>
</p>
## Dev Setup 🛠
> Runs on port 3000

View File

@@ -5,3 +5,5 @@ services:
#image: registry.odit.services/kauft.es/linkylinky:latest
ports:
- 3000:3000
#volumes:
# - ./db:/app/db

View File

@@ -12,7 +12,7 @@ module.exports = {
production: {
client: 'sqlite3',
connection: {
filename: './db.sqlite3'
filename: './db/db.sqlite3'
},
migrations: {
tableName: 'knex_migrations'

View File

@@ -0,0 +1,10 @@
exports.up = function(knex) {
return knex.schema.table('users', function (table) {
table.integer("jwtcount").defaultTo(0);
});
};
exports.down = function(knex) {
};

View File

@@ -0,0 +1,10 @@
exports.up = function(knex) {
return knex.schema.table('visits', function (table) {
table.text('provider').defaultTo("N/A");
});
};
exports.down = function(knex) {
};

View File

@@ -0,0 +1,10 @@
exports.up = function(knex) {
return knex.schema.table('urls', function (table) {
table.boolean('no_preview').defaultTo(false);
});
};
exports.down = function(knex) {
};

View File

@@ -0,0 +1,9 @@
exports.up = function(knex) {
return knex.schema.table('urls', function (table) {
table.boolean('clientside').defaultTo(false);
});
};
exports.down = function(knex) {
};

View File

@@ -1,21 +1,38 @@
{
"name": "@odit/shortener-backend",
"version": "0.0.2",
"version": "0.6.0",
"main": "index.js",
"license": "MIT",
"private": false,
"author": {
"name": "ODIT.Services",
"email": "info@odit.services",
"url": "https://odit.services"
},
"contributors": [
{
"name": "Nicolai Ort",
"email": "info@nicolai-ort.com",
"url": "https://nicolai-ort.com"
}
],
"scripts": {
"dev": "nodemon src/server.js",
"start": "node src/server.js",
"migrate": "knex migrate:latest",
"release": "release-it"
"release": "release-it",
"create:migration": "knex migrate:make"
},
"dependencies": {
"argon2": "^0.28.2",
"dotenv": "^10.0.0",
"dotenv": "^11.0.0",
"fastify": "^3.20.1",
"fastify-auth": "^1.1.0",
"fastify-basic-auth": "^2.1.0",
"knex": "^0.21.21",
"fastify-cors": "^6.0.2",
"fastify-jwt": "^3.0.1",
"isbot": "^3.3.3",
"knex": "^0.95.0",
"sqlite3": "^5.0.2",
"uniqid": "^5.3.0"
},
@@ -28,6 +45,12 @@
"commit": true,
"requireCleanWorkingDir": false,
"commitMessage": "🚀RELEASE ${version}",
"git.commitArgs": [
"-S"
],
"git.tagArgs": [
"-S"
],
"push": true,
"tag": true,
"tagName": null,

4
renovate.json Normal file
View File

@@ -0,0 +1,4 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"dependencyDashboard": true
}

View File

@@ -2,12 +2,15 @@ const fastify = require('fastify')({ logger: true })
var uniqid = require('uniqid');
require('dotenv').config();
const argon2 = require('argon2');
const isBot = require('isbot')
let config = {
domain: process.env.DOMAIN || "localhost:3000",
https: (process.env.SSL === 'true') || false,
env: process.env.NODE_ENV || 'development',
recognizeProviders: !(process.env.DISABLE_PROVIDERS === 'true'),
registrationEnabled: (process.env.ENABLE_REGISTER === 'true'),
jwt_secret: process.env.JWT_SECRET || "pleaseneverusethisdefaultsecret",
getBaseUrl() {
if (config.https) {
return `https://${config.domain}`;
@@ -15,29 +18,82 @@ let config = {
return `http://${config.domain}`;
}
}
const knex = require('knex')({
client: 'sqlite3',
connection: {
filename: "./dev.sqlite3"
}
});
const knexConfiguration = require('../knexfile')[config.env];
const knex = require('knex')(knexConfiguration);
const authenticate = { realm: 'Short' }
fastify.register(require('fastify-auth'))
fastify.register(require('fastify-basic-auth'), { validate, authenticate });
fastify.register(require('fastify-jwt'), {
secret: config.jwt_secret
});
fastify.register(require('fastify-cors'), {
origin: true,
preflight: true,
preflightContinue: true
})
fastify.decorate('verifyJWT', function async(request, reply, done) {
let token = request.headers.authorization;
if (!token || token == "" || token == "Bearer") {
done(new Error("No jwt provided"));
}
if (token.startsWith("Bearer")) {
token = token.replace("Bearer ", "");
fastify.log.info("Detected bearer and replaced it")
}
fastify.jwt.verify(token, async (err, decoded) => {
if (err) {
fastify.log.error("JWT validation failed:")
done(new Error("JWT Validation failed"));
}
else {
if (!decoded.payload) {
done(new Error("JWT is empty"));
}
fastify.log.info(`Token verified. User is ${decoded.payload.user}`);
const jwtcount = (await knex.select('jwtcount')
.from('users')
.where('username', '=', decoded.payload.user)
.limit(1))[0].jwtcount;
if (decoded.payload.jwtcount < jwtcount) {
fastify.log.error("Auth ended at jwtcount")
done(new Error("JWT in no longer valid"))
}
else {
fastify.log.info(`JWT count verified`);
request.user = decoded.payload.user;
done()
}
}
})
})
//Automagic Amazn redirects on /a/
fastify.get('/a/:id', async (req, res) => {
res.redirect(302, `https://amazon.de/dp/${req.params.id}`)
await knex('visits').insert({ shortcode: req.params.id, provider: 'a' });
})
//Automagic Youtube redirects on /yt/
fastify.get('/yt/:id', async (req, res) => {
res.redirect(302, `https://youtu.be/${req.params.id}`)
await knex('visits').insert({ shortcode: req.params.id, provider: 'yt' });
})
//Automagic Youtube Playlist redirects on /ytpl/
fastify.get('/ytpl/:id', async (req, res) => {
res.redirect(302, `https://youtube.com/playlist?list=${req.params.id}`)
await knex('visits').insert({ shortcode: req.params.id, provider: 'ytpl' });
})
//Automagic ebay item redirects on /e/
fastify.get('/e/:id', async (req, res) => {
res.redirect(302, `https://ebay.de/itm/${req.params.id}`)
await knex('visits').insert({ shortcode: req.params.id, provider: 'e' });
})
//Normal shorturls
@@ -48,15 +104,26 @@ fastify.get('/:shortcode', async (req, res) => {
if (!shortcode) {
return 404;
}
const target = await knex.select('target')
const target = await knex.select('target', 'no_preview', 'clientside')
.from('urls')
.where('shortcode', '=', shortcode)
.limit(1);
if (!target[0]) {
return 404
}
if (isBot(req.headers['user-agent']) && target[0].no_preview) {
res.type("text/html");
return bot_html;
}
if (target[0].clientside) {
res.type("text/html");
return clientside_html.replace("{{targeturl}}", target[0].target)
}
res.redirect(302, target[0].target);
await knex('visits').insert({ shortcode });
await knex('visits').insert({ shortcode, provider: 'native' });
})
//Create new url schema
@@ -66,6 +133,8 @@ const newUrlSchema = {
properties: {
target: { type: 'string' },
shortcode: { type: 'string' },
no_preview: { type: 'boolean' },
clientside: { type: 'boolean' }
}
}
};
@@ -74,6 +143,8 @@ const newUrlSchema = {
fastify.post('/api', { newUrlSchema }, async (req, res) => {
const target = req.body?.target;
let shortcode = req.body?.shortcode;
let no_preview = req.body?.no_preview || false;
let clientside = req.body?.clientside || false;
//Check if the user provided a target
if (!target) {
@@ -93,7 +164,7 @@ fastify.post('/api', { newUrlSchema }, async (req, res) => {
return response;
}
}
const exists = await knex.select('shortcode')
const exists = await knex.select('shortcode', 'no_preview', 'clientside')
.from('urls')
.where('target', '=', target)
.limit(1);
@@ -102,7 +173,9 @@ fastify.post('/api', { newUrlSchema }, async (req, res) => {
return {
url: `${config.getBaseUrl()}/${shortcode}`,
shortcode,
target
target,
no_preview: exists[0].no_preview,
clientside: exists[0].clientside
}
}
shortcode = uniqid();
@@ -124,12 +197,28 @@ fastify.post('/api', { newUrlSchema }, async (req, res) => {
}
//Create a new db entry
await knex('urls').insert({ target, shortcode });
await knex('urls').insert({ target, shortcode, no_preview, clientside });
return {
url: `${config.getBaseUrl()}/${shortcode}`,
shortcode,
target
target,
no_preview,
clientside
}
});
//Get stats api route
fastify.get('/api/stats', async (req, res) => {
const urls = await knex.select('shortcode')
.from('urls');
const visits = await knex.select('timestamp')
.from('visits');
return {
urls: urls.length,
visits: visits.length,
}
});
@@ -142,7 +231,7 @@ fastify.get('/api/:shortcode', async (req, res) => {
return 404;
}
const exists = await knex.select('shortcode', 'target')
const exists = await knex.select('shortcode', 'target', 'no_preview', 'clientside')
.from('urls')
.where('shortcode', '=', shortcode)
.limit(1);
@@ -158,12 +247,15 @@ fastify.get('/api/:shortcode', async (req, res) => {
url: `${config.getBaseUrl()}/${exists[0].shortcode}`,
shortcode: exists[0].shortcode,
target: exists[0].target,
no_preview: exists[0].no_preview,
clientside: exists[0].clientside,
visits: visits.length
}
});
//User registration
fastify.post('/api/register', async (req, res) => {
fastify.post('/api/auth/register', async (req, res) => {
if (!config.registrationEnabled) {
res.statusCode = 400;
return "Registration was disabled by your admin";
@@ -195,9 +287,10 @@ fastify.post('/api/register', async (req, res) => {
return "Done!"
});
//Anything in here has some kind of auth
fastify.after(() => {
//Get url api route
fastify.get('/api/:shortcode/visits', { onRequest: fastify.basicAuth }, async (req, res) => {
//Get url visits api route
fastify.get('/api/:shortcode/visits', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => {
const shortcode = req.params.shortcode;
//This should never happen but better safe than 500
@@ -205,23 +298,26 @@ fastify.after(() => {
return 404;
}
const exists = await knex.select('shortcode', 'target')
.from('urls')
.where('shortcode', '=', shortcode)
.limit(1);
if (exists.length == 0) {
return 404;
}
const visits = await knex.select('timestamp')
const visits = await knex.select('timestamp', 'provider')
.from('visits')
.where('shortcode', '=', shortcode);
return visits;
});
//Get all visits api route
fastify.get('/api/visits', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => {
if (req.query.provider) {
return await knex.select('shortcode', 'provider', 'timestamp')
.from('visits')
.where("provider", "=", req.query.provider);
}
return await knex.select('shortcode', 'provider', 'timestamp')
.from('visits');
});
//Get url api route
fastify.delete('/api/:shortcode', async (req, res) => {
fastify.delete('/api/:shortcode', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => {
const shortcode = req.params.shortcode;
//This should never happen but better safe than 500
@@ -237,6 +333,63 @@ fastify.after(() => {
return true;
});
//Get all urls api route
fastify.get('/api', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, res) => {
urls = await knex.select('target', 'shortcode', 'no_preview', 'clientside')
.from('urls');
for (let url of urls) {
url.url = `${config.getBaseUrl()}/${url.shortcode}`
if (req.query.showVisits) {
url.visits = (await knex.select('timestamp')
.from('visits')
.where('shortcode', '=', url.shortcode)).length;
}
}
return urls;
});
fastify.post('/api/auth/login', { onRequest: fastify.auth([fastify.basicAuth]) }, async (req, reply) => {
const jwtcount = (await knex.select('jwtcount')
.from('users')
.where('username', '=', req.user)
.limit(1))[0].jwtcount;
const payload = {
user: req.user,
jwtcount
};
const token = fastify.jwt.sign({ payload })
reply.send({ token });
});
fastify.post('/api/auth/check', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, (req, reply) => {
return "logged in";
});
fastify.post('/api/auth/logout', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, reply) => {
let jwtcount = (await knex.select('jwtcount')
.from('users')
.where('username', '=', req.user)
.limit(1))[0].jwtcount;
jwtcount += 1;
await knex('users')
.where('username', '=', req.user)
.update({
jwtcount
});
return "Done!";
});
fastify.post('/api/auth/deleteme', { onRequest: fastify.auth([fastify.basicAuth, fastify.verifyJWT]) }, async (req, reply) => {
await knex('users')
.where('username', '=', req.user)
.delete();
return "Done!";
});
});
@@ -266,7 +419,7 @@ function checkKnownProviders(target) {
target
}
}
const amazonID = target.match(/https?:\/\/(www|smile|)\.?(amazon|smile)\.(de)(?:(?:\/.*\/|\/)(?:dp|gp))(\/product\/|\/)([A-Z0-9]+)/);
const amazonID = target.match(/(?:https?:\/\/|)(www|smile|)\.?(amazon|smile)\.(de)(?:(?:\/.*\/|\/)(?:dp|gp))(\/product\/|\/)([A-Z0-9]+)/);
if (amazonID) {
const shortcode = `a/${amazonID[5]}`
return {
@@ -275,6 +428,15 @@ function checkKnownProviders(target) {
target
}
}
const ebayID = target.match(/(?:[ebay]*(?:[\/]|[itm=])|^)([0-9]{9,12})/);
if (ebayID) {
const shortcode = `e/${ebayID[1]}`
return {
url: `${config.getBaseUrl()}/${shortcode}`,
shortcode,
target
}
}
return null;
}
@@ -294,17 +456,291 @@ async function validate(username, password, req, reply) {
if (!(await argon2.verify(user[0].password, password))) {
return new Error('Wrong credentials');
}
req.user = username;
}
const bot_html = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta property="og:title" content="LinkyLinky">
<meta property="og:site_name" content="LinkyLinky by Kauft.es">
<meta property="og:url" content="https://kauft.es/">
<meta property="og:description" content="LinkyLinky by Kauft.es is a custom url shortener. You're reading this, b/c someone doesn't want their shorturl to be indexed by bots/crawlers/spiders.">
<meta property="og:type" content="article">
<meta property="og:image" content="https://kauft.es/dashboard/icon_128.png">
<title>LinkyLinky</title>
</head>
<body>
<p align="center">
<img height="150" src="https://kauft.es/dashboard/icon_128.png">
<h1 align="center">LinkyLinky 🔗</h1>
<h3 align="center">A small url shortener, originaly developed for kauft.es</h3>
<p>LinkyLinky by Kauft.es is a custom url shortener.<br>
You're reading this, b/c someone doesn't want their shorturl to be indexed by bots/crawlers/spiders.</p>
</p>
</body>
</html>
`;
const clientside_html = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="robot" content="no-index">
</head>
<body>
<style>
body {
background: black;
overflow: hidden;
}
.containCube {
position: relative;
height: 100vh;
width: 100%;
perspective: 800px;
}
.containCube .cube {
position: absolute;
height: 300px;
width: 300px;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
box-sizing: border-box;
transform-style: preserve-3d;
transform-origin: 50% 50%;
-webkit-animation: rotate 20s ease-in-out infinite alternate;
animation: rotate 20s ease-in-out infinite alternate;
}
.containCube .cubeGroup {
position: absolute;
display: grid;
box-sizing: border-box;
height: 100%;
width: 100%;
color: white;
text-shadow: 0 0 1px black;
border: 3px dashed white;
}
.containCube .cubeGroup h1 {
margin: auto;
}
.containCube .cube-front {
transform: translatez(150px);
}
.containCube .cube-rear {
transform: translatez(-150px) rotatey(180deg);
}
.containCube .cube-right {
transform-origin: 100%;
transform: rotatey(90deg) translatex(150px);
}
.containCube .cube-left {
transform-origin: 0%;
transform: rotatey(-90deg) translatex(-150px);
}
.containCube .cube-bottom {
transform-origin: 50% 100%;
transform: rotatex(-90deg) translatey(150px);
}
.containCube .cube-top {
transform-origin: 50% 0%;
transform: rotatex(90deg) translatey(-150px);
}
.containCube .cube-1 {
background: red;
}
.containCube .cube-2 {
background: red;
}
.containCube .cube-3 {
background: red;
}
.containCube .cube-4 {
background: red;
}
.containCube .cube-5 {
background: red;
}
.containCube .cube-6 {
background: red;
}
@-webkit-keyframes rotate {
10% {
transform: rotate3d(1, 1, 0, 320deg);
}
20% {
transform: rotate3d(1, 0, 0, -90deg);
}
30% {
transform: rotate3d(1, 1, 0, 440deg);
}
40% {
transform: rotate3d(1, 0, 0, -180deg);
}
50% {
transform: rotate3d(1, 1, 0, 460deg);
}
60% {
transform: rotate3d(0, 1, 0, -195deg);
}
70% {
transform: rotate3d(1, 1, 0, 172deg);
}
80% {
transform: rotate3d(0, 1, 0, -360deg);
}
90% {
transform: rotate3d(1, 1, 0, 280deg);
}
}
@keyframes rotate {
10% {
transform: rotate3d(1, 1, 0, 320deg);
}
20% {
transform: rotate3d(1, 0, 0, -90deg);
}
30% {
transform: rotate3d(1, 1, 0, 440deg);
}
40% {
transform: rotate3d(1, 0, 0, -180deg);
}
50% {
transform: rotate3d(1, 1, 0, 460deg);
}
60% {
transform: rotate3d(0, 1, 0, -195deg);
}
70% {
transform: rotate3d(1, 1, 0, 172deg);
}
80% {
transform: rotate3d(0, 1, 0, -360deg);
}
90% {
transform: rotate3d(1, 1, 0, 280deg);
}
}
@-webkit-keyframes rotateZed {
20% {
transform: translatez(100px);
}
40% {
transform: translatez(-100px);
}
60% {
transform: translatez(100px);
}
80% {
transform: translatez(-100px);
}
}
@keyframes rotateZed {
20% {
transform: translatez(100px);
}
40% {
transform: translatez(-100px);
}
60% {
transform: translatez(100px);
}
80% {
transform: translatez(-100px);
}
}
</style>
<div class="containCube">
<div class="cube">
<div class="cubeGroup cube-front cube-1">
<h1>kauft.es</h1>
</div>
<div class="cubeGroup cube-top cube-2">
<h1>kauft.es</h1>
</div>
<div class="cubeGroup cube-left cube-3">
<h1>kauft.es</h1>
</div>
<div class="cubeGroup cube-right cube-4">
<h1>kauft.es</h1>
</div>
<div class="cubeGroup cube-rear cube-5">
<h1>kauft.es</h1>
</div>
<div class="cubeGroup cube-bottom cube-6">
<h1>kauft.es</h1>
</div>
</div>
</div>
<script>
setTimeout(function () {
location.replace("{{targeturl}}");
}, 3000);//Delay 3 seconds
</script>
</body>
</html>
`;
// Run the server!
const start = async () => {
try {
await knex.migrate.latest()
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
try {
await fastify.listen(3000, '0.0.0.0')
} catch (err) {

837
src/🥵🥵🥵.js Normal file
View File

@@ -0,0 +1,837 @@
const emojis = [
"😀",
"😃",
"😄",
"😁",
"😆",
"😅",
"😂",
"🤣",
"😊",
"😇",
"🙂",
"🙃",
"😉",
"😌",
"😍",
"😘",
"😗",
"😙",
"😚",
"😋",
"😛",
"😝",
"😜",
"🤪",
"🤨",
"🧐",
"🤓",
"😎",
"🤩",
"😏",
"🤯",
"😳",
"🤗",
"🤔",
"🤭",
"🤫",
"🤥",
"😶",
"😯",
"😮",
"😲",
"😴",
"🤤",
"🤐",
"🤧",
"😷",
"🤒",
"🤑",
"🤠",
"😈",
"👿",
"👹",
"👺",
"🤡",
"💩",
"👻",
"👽",
"👾",
"🤖",
"🎃",
"😺",
"😸",
"😹",
"😻",
"😼",
"😽",
"🙀",
"😿",
"😾",
"🤲",
"👐",
"🙌",
"👏",
"🤝",
"👍",
"👊",
"✊",
"🤛",
"🤜",
"🤞",
"✌️",
"🤟",
"🤘",
"👈",
"👉",
"👆",
"👇",
"☝️",
"✋",
"🤚",
"🖐",
"🖖",
"👋",
"🤙",
"💪",
"✍️",
"💁‍",
"🙅‍",
"🙋‍",
"🤷‍",
"💃",
"🕺🏻",
"🧥",
"👚",
"👕",
"👖",
"👔",
"👗",
"👙",
"👘",
"👠",
"👡",
"👢",
"👞",
"👟",
"🧦",
"🧤",
"🧣",
"🎩",
"🧢",
"👒",
"🎓",
"⛑",
"👑",
"💍",
"👝",
"👛",
"👜",
"💼",
"🎒",
"👓",
"🕶",
"🌂",
"💢",
"♨️",
"❗️",
"❕",
"❓",
"❔",
"⁉️",
"🔅",
"🔆",
"🚸",
"🔰",
"♻️",
"✅",
"🌀",
"💤",
"🚮",
"🆗",
"🔣",
"🆒",
"🔜",
"✔️",
"🔈",
"🔉",
"🔊",
"📢",
"💬",
"💭",
"🗯",
"🀄️",
"🃏",
"🎴",
"🐶",
"🐱",
"🐭",
"🐹",
"🐰",
"🦊",
"🐻",
"🐼",
"🐨",
"🐯",
"🦁",
"🐮",
"🐷",
"🐽",
"🐸",
"🐵",
"🙈",
"🙉",
"🙊",
"🐒",
"🐔",
"🐧",
"🐦",
"🐤",
"🐣",
"🐥",
"🦆",
"🦅",
"🦉",
"🦇",
"🐺",
"🐗",
"🐴",
"🦄",
"🐝",
"🐌",
"🐞",
"🐜",
"🦗",
"🕷",
"🕸",
"🦂",
"🐢",
"🐍",
"🦎",
"🦖",
"🦕",
"🐙",
"🦑",
"🦐",
"🦀",
"🐡",
"🐠",
"🐟",
"🐬",
"🐳",
"🐋",
"🦈",
"🐊",
"🐅",
"🐆",
"🦓",
"🦍",
"🐘",
"🦏",
"🐪",
"🐫",
"🦒",
"🐃",
"🐂",
"🐄",
"🐎",
"🐖",
"🐏",
"🐑",
"🐐",
"🦌",
"🐕",
"🐩",
"🐈",
"🐓",
"🦃",
"🕊",
"🐇",
"🐁",
"🐀",
"🐿",
"🦔",
"🐾",
"🐉",
"🐲",
"🌵",
"🎄",
"🌲",
"🌳",
"🌴",
"🌱",
"🌿",
"☘️",
"🍀",
"🎍",
"🎋",
"🍃",
"🍂",
"🍁",
"🍄",
"🐚",
"🌾",
"💐",
"🌷",
"🌹",
"🥀",
"🌺",
"🌸",
"🌼",
"🌻",
"🌞",
"🌝",
"🌛",
"🌜",
"🌚",
"🌕",
"🌖",
"🌗",
"🌘",
"🌑",
"🌒",
"🌓",
"🌔",
"🌙",
"🌎",
"🌏",
"💫",
"🌟",
"⚡️",
"☄️",
"🌪",
"☀️",
"🌤",
"⛅️",
"🌥",
"☁️",
"🌦",
"🌧",
"⛈",
"🌩",
"🌨",
"❄️",
"☃️",
"⛄️",
"🌬",
"💨",
"☔️",
"☂️",
"🌊",
"🌫",
"🕐",
"🕑",
"🕒",
"🕓",
"🕔",
"🕕",
"🕖",
"🕗",
"🕘",
"🕙",
"🕚",
"🕛",
"🕜",
"🕝",
"🕞",
"🕟",
"🕠",
"🕡",
"🕢",
"🕣",
"🕤",
"🕥",
"🕦",
"🕧",
"🍏",
"🍎",
"🍐",
"🍊",
"🍋",
"🍌",
"🍉",
"🍇",
"🍓",
"🍈",
"🍒",
"🍍",
"🥥",
"🥝",
"🍅",
"🥑",
"🥦",
"🥒",
"🌶",
"🌽",
"🥕",
"🥔",
"🍠",
"🥐",
"🍞",
"🥖",
"🥨",
"🧀",
"🥚",
"🍳",
"🥞",
"🥓",
"🥩",
"🍗",
"🍖",
"🌭",
"🍔",
"🍟",
"🍕",
"🥪",
"🥙",
"🌮",
"🌯",
"🥗",
"🥘",
"🥫",
"🍝",
"🍲",
"🍛",
"🍣",
"🍱",
"🥟",
"🍤",
"🍙",
"🍚",
"🍘",
"🍥",
"🥠",
"🍢",
"🍡",
"🍧",
"🍨",
"🍦",
"🥧",
"🍰",
"🎂",
"🍮",
"🍭",
"🍬",
"🍫",
"🍿",
"🍩",
"🍪",
"🌰",
"🥜",
"🍯",
"🥛",
"🍼",
"☕️",
"🍵",
"🥤",
"🍶",
"🍺",
"🍻",
"🥂",
"🍷",
"🥃",
"🍸",
"🍹",
"🍾",
"🥄",
"🍴",
"🍽",
"🥣",
"🥡",
"🥢",
"⚽️",
"🏀",
"🏈",
"⚾",
"️🎾",
"🏐",
"🏉",
"🎱",
"🏓",
"🏸",
"🏑",
"🏒",
"🏏",
"🥅",
"⛳️",
"🏹",
"🎣",
"🥊",
"🥋",
"🎽",
"🛷",
"⛸",
"🥌",
"🎿",
"⛷",
"🏂",
"🏆",
"🥇",
"🥈",
"🥉",
"🏅",
"🎖",
"🏵",
"🎗",
"🎫",
"🎟",
"🎪",
"🎭",
"🎨",
"🎬",
"🎤",
"🎧",
"🎼",
"🎹",
"🥁",
"🎷",
"🎺",
"🎸",
"🎻",
"🎲",
"🎳",
"🎮",
"🎰",
"🚗",
"🚕",
"🚙",
"🚌",
"🚎",
"🏎",
"🚓",
"🚑",
"🚒",
"🚐",
"🚚",
"🚛",
"🚜",
"🛴",
"🚲",
"🛵",
"🏍",
"🚔",
"🚍",
"🚘",
"🚖",
"🚡",
"🚠",
"🚟",
"🚃",
"🚋",
"🚞",
"🚝",
"🚄",
"🚅",
"🚈",
"🚂",
"🚆",
"🚇",
"🚊",
"🚉",
"✈️",
"🛫",
"🛬",
"🛩",
"💺",
"🛰",
"🚀",
"🛸",
"🚁",
"🛶",
"⛵️",
"🚤",
"🛥",
"🛳",
"⛴",
"🚢",
"⚓️",
"⛽️",
"🚧",
"🚦",
"🚥",
"🚏",
"🗺",
"🗿",
"🗽",
"🗼",
"🏰",
"🏯",
"🏟",
"🎡",
"🎢",
"🎠",
"⛲️",
"⛱",
"🏖",
"🏝",
"🏜",
"🌋",
"⛰",
"🏔",
"🗻",
"🏕",
"⛺️",
"🏠",
"🏡",
"🏘",
"🏚",
"🏗",
"🏭",
"🏢",
"🏬",
"🏣",
"🏤",
"🏥",
"🏦",
"🏨",
"🏪",
"🏫",
"🏩",
"💒",
"🏛",
"⛪️",
"🕌",
"🕍",
"🕋",
"⛩",
"🛤",
"🛣",
"🗾",
"🎑",
"🏞",
"🌅",
"🌄",
"🌠",
"🎇",
"🎆",
"🌇",
"🏙",
"🌃",
"🌌",
"🌉",
"🌁",
"⌚️",
"📱",
"📲",
"💻",
"⌨️",
"🖥",
"🖨",
"🖱",
"🖲",
"🕹",
"🗜",
"💽",
"💾",
"💿",
"📀",
"📼",
"📷",
"📸",
"📹",
"🎥",
"📽",
"🎞",
"📞",
"☎️",
"📟",
"📠",
"📺",
"📻",
"🎙",
"🎚",
"🎛",
"⏱",
"⏲",
"⏰",
"🕰",
"⏳",
"📡",
"🔋",
"🔌",
"🔦",
"🕯",
"🛢",
"💵",
"💴",
"💶",
"💷",
"💰",
"💳",
"💎",
"⚖️",
"🔧",
"🔨",
"🛠",
"⛏",
"🔩",
"⚙️",
"⛓",
"🔫",
"💣",
"🔪",
"🗡",
"⚔️",
"🛡",
"🏺",
"📿",
"💈",
"⚗️",
"🔭",
"🔬",
"🕳",
"💊",
"💉",
"🌡",
"🚽",
"🚰",
"🚿",
"🛁",
"🛎",
"🔑",
"🗝",
"🚪",
"🛋",
"🛏",
"🛌",
"🖼",
"🛍",
"🛒",
"🎏",
"🎀",
"🎎",
"🏮",
"🎐",
"✉️",
"📩",
"📨",
"📧",
"💌",
"📥",
"📤",
"📦",
"🏷",
"📪",
"📫",
"📬",
"📭",
"📮",
"📯",
"📜",
"📃",
"📄",
"📑",
"📊",
"📈",
"📉",
"🗒",
"🗓",
"📆",
"📅",
"🗑",
"📇",
"🗃",
"🗳",
"🗄",
"📋",
"📁",
"📂",
"🗂",
"🗞",
"📰",
"📓",
"📔",
"📒",
"📕",
"📗",
"📘",
"📙",
"📖",
"🔖",
"🔗",
"📎",
"🖇",
"📐",
"📏",
"📌",
"📍",
"✂️",
"🖊",
"🖋",
"✒️",
"🖌",
"🖍",
"📝",
"✏️",
"🔍",
"🔎",
"🔏",
"🔐",
"🔒",
"🔓",
"🏳️",
"🏁",
"🚩",
"❤️",
"🧡",
"💛",
"💚",
"💙",
"💜",
"🖤",
"💔",
"❣️",
"💕",
"💞",
"💓",
"💗",
"💖",
"💘",
"💝",
"✨",
"💥",
"🔥",
"🌈",
"💧",
"💦",
"🍑",
"🍆",
"🍜",
"🎯",
"🚨",
"💡",
"💸",
"🔮",
"🎁",
"🎈",
"🎊",
"🎉",
"📚",
"🔔",
"📣",
"💅",
"👀",
"🧠",
"🏳️‍🌈",
"🐛",
"🦋",
"💄",
"💋",
"👄",
"💯",
"🎵",
"🎶",
"🙏",
"⭐️"
];
const getEmoji = (number = 10) => {
let id = "";
while (number > 0) {
id += emojis[Math.floor(Math.random() * emojis.length)];
number--;
}
return id;
}
module.exports = getEmoji;

3505
yarn.lock Normal file

File diff suppressed because it is too large Load Diff