Compare commits

...

95 Commits
v1.0.1 ... main

Author SHA1 Message Date
Kainoa Kanter 832ccc3e88
Update README.md 2023-09-05 14:49:43 -07:00
Kainoa Kanter 1677032f4e
Merge pull request #72 from idanoo/main 2023-05-01 13:07:15 -07:00
Daniel Mason 9c245cf827 Remove paste.m2.nz from instance list 2023-05-01 08:59:57 +00:00
Kainoa Kanter ac1f4cf33a
Merge pull request #69 from hatkidchan/fix-68-layout
Switched from e.key to e.code, fixes #68
2023-01-16 08:58:27 -08:00
hkc 90d1966779
Switched from e.key to e.code, fixes #68 2023-01-16 14:26:04 +03:00
Kainoa Kanter f0a3670913
Update README.md 2022-09-23 11:19:45 -07:00
Kainoa Kanter 81e5a3f7a8
Merge pull request #65 from pupbrained/patch-2
Update Domain in README
2022-09-22 21:41:02 -07:00
Mars e7c96047cf
Update Domain in README 2022-09-23 03:10:26 +00:00
Kainoa Kanter e2037f7522
Merge pull request #64 from idanoo/update_domain
Update domain/config in README.md
2022-09-11 20:35:52 -07:00
idanoo 7eb63190f0 Update link in README.md 2022-09-12 13:56:04 +12:00
Kainoa Kanter 82d2087281
Update README.md 2022-07-19 21:28:56 -07:00
Kainoa Kanter 5e77dcf43b
Update README.md 2022-07-19 21:27:52 -07:00
mellowmarshe db0d09bad7
Merge pull request #61 from auguwu/env-var-subsitution 2022-05-15 21:55:52 -04:00
Noel 0c78b83b30
remove full path from vite config 2022-05-15 18:51:32 -07:00
Noel 6e8e2b119a
Merge branch 'env-var-subsitution' of https://github.com/auguwu/zer0bin into env-var-subsitution 2022-05-15 18:49:22 -07:00
Noel 479354fe2c
remove .env 2022-05-15 18:49:18 -07:00
Noel 75de8c53e3
Merge branch 'zer0bin-dev:main' into env-var-subsitution 2022-05-15 18:48:20 -07:00
Noel e9e18e3501
add environment variable subsitution with `.env` files and system env 2022-05-15 18:47:07 -07:00
domterion de58aa84c2 Remove single_view from schema.sql, migrator will create this 2022-05-16 00:30:14 +00:00
ThatOneCalculator fd6b91977b refactor: ♻️ Comments to pug 2022-04-08 08:47:18 -07:00
ThatOneCalculator 0050ea2fb9 Merge branch 'main' of https://github.com/zer0bin-dev/zer0bin 2022-04-08 08:11:28 -07:00
ThatOneCalculator 5bb8c3441b refactor: ♻️ Config to TS 2022-04-08 08:11:16 -07:00
Kainoa Kanter 3ee8b85213
docs: 🤓 Free font option 2022-04-07 22:27:37 -07:00
ThatOneCalculator 535530c34f feat: Add free font option 2022-04-07 22:23:04 -07:00
ThatOneCalculator 21ec4c1ef0 perf: Add vite-plugin-compression for gzip 2022-04-07 19:35:47 -07:00
ThatOneCalculator d683701360 perf: Remove all fonts except woff2 2022-04-07 19:32:31 -07:00
ThatOneCalculator 0e1bb82944 fix: 🐛 Add lang to html 2022-04-07 19:30:39 -07:00
ThatOneCalculator f1ccf6a836 fix: 🐛 Metadata 2022-04-07 19:28:25 -07:00
ThatOneCalculator fa07222803 fix: 🐛 Favicon 2022-04-07 19:20:48 -07:00
ThatOneCalculator 3cfda99765 fix: 🐛 Favicon 2022-04-07 19:15:31 -07:00
ThatOneCalculator d96287c206 fix: Lighthouse accesibility 2022-04-07 19:15:11 -07:00
mellowmarshe 1146f4b7da
Merge pull request #60 from zer0bin-dev/vite 2022-04-07 21:08:04 -04:00
Kainoa Kanter 7be6aa6cf2
deps: 🔥 remove parcel 2022-04-07 17:54:51 -07:00
ThatOneCalculator 6f55b59d7b build: 🏗️ Switch to Vite for build system 2022-04-07 17:49:34 -07:00
ThatOneCalculator 9ff53c1345 Merge branch 'main' of https://github.com/zer0bin-dev/zer0bin 2022-04-04 12:14:40 -07:00
ThatOneCalculator f001286f5b refactor: 💄 Share button to top bar 2022-04-04 12:14:25 -07:00
Kainoa Kanter b03ca2c8f7
docs: 📝 Fix broken links on button illusts 2022-04-04 12:04:22 -07:00
ThatOneCalculator 648b6aac4e feat: Share button = copy to clipboard if no sharenav 2022-04-04 11:59:26 -07:00
ThatOneCalculator fff67c1a43 feat: Share button 2022-04-04 11:49:03 -07:00
ThatOneCalculator 4f62e7f4ee feat: 🚧 Share button 2022-04-04 11:34:08 -07:00
Kainoa Kanter 8ad0b5790d
🔖 v1.1.1 2022-04-04 11:05:51 -07:00
ThatOneCalculator 6ee88465fa feat: 🔖 v1.1.1
Upgrade deps
2022-04-04 10:42:04 -07:00
Dominic Harris 36e81a6c4f
🐛 fix: Fix migrator 2022-04-04 13:37:35 -04:00
Kainoa Kanter 794403ae97
docs: 📝 Make keybinds bullet points 2022-04-04 09:50:04 -07:00
ThatOneCalculator ead9d9108e refactor: 🚧 Use built in migrator (WIP) 2022-04-04 09:35:50 -07:00
ThatOneCalculator be7617476f refactor: ♻️ Still use extraSVGAttrs with new method 2022-04-04 00:40:19 -07:00
ThatOneCalculator bbccfc4314 refactor: ♻️ Render icon method 2022-04-04 00:35:27 -07:00
ThatOneCalculator a2b6392b03 refactor: 🎨 Pug formatting 2022-04-04 00:22:17 -07:00
ThatOneCalculator 407a4997f6 fix: 🥚 Add `.htmlnanorc` for comments 2022-04-04 00:18:27 -07:00
ThatOneCalculator 0081ddeafa feat: 🥚 Inspect element suprise 2022-04-04 00:13:07 -07:00
ThatOneCalculator ee5e9a1ca3 feat: Markdown mode keybind (Ctrl + M) 2022-04-03 23:56:38 -07:00
ThatOneCalculator 667e00b894 fix: 🐛 Disable markdown button when viewing paste 2022-04-03 23:44:57 -07:00
ThatOneCalculator 8d6e3b6378 feat: 💄 Fade for hiding and colors 2022-04-03 23:43:06 -07:00
ThatOneCalculator bd718fadde refactor: ♻️ use `toggle()` for changing classes 2022-04-03 23:33:28 -07:00
Kainoa Kanter 44e996c60d docs: 📝 Improve features section 2022-04-03 23:24:22 -07:00
ThatOneCalculator 18e2ba0200 fix: 🗃️ Seperate schema and migrations 2022-04-03 23:06:11 -07:00
ThatOneCalculator 70c84ebaba fix: ✏️ Func capitalization 2022-04-03 22:44:59 -07:00
ThatOneCalculator abeebd045f fix: ✏️ Typo in migration 2022-04-03 22:41:53 -07:00
ThatOneCalculator a2b3104c08 refactor: 🗃️ Migrations to lc 2022-04-03 22:39:26 -07:00
ThatOneCalculator 3eb141ec72 refactor: 🎨 Make editor.value var 2022-04-03 22:28:38 -07:00
ThatOneCalculator cbd21b6bb2 feat: Markdown button 2022-04-03 22:26:32 -07:00
ThatOneCalculator 5fe090c302 fix: 🥅 Catch migration error 2022-04-03 22:11:56 -07:00
ThatOneCalculator 35004d8f0f feat: ⚗️ migrations 2022-04-03 21:55:29 -07:00
ThatOneCalculator fa78dd4246 fix: 🔥 Remove fire animation until parcel is fixed 2022-04-03 20:03:15 -07:00
ThatOneCalculator 1bd6d3721a fix: ⚗️ Try secondary calc 2022-04-03 19:37:13 -07:00
ThatOneCalculator d260e338f5 style: ⚗️ Try `math.div()` 2022-04-03 19:36:19 -07:00
ThatOneCalculator 658538fd61 build: ⬆️ Upgrade parcel 2022-04-03 19:34:20 -07:00
ThatOneCalculator 67f753c0d6 fix: ⚗️ Test CSS fix 2022-04-03 19:33:37 -07:00
ThatOneCalculator 4a921a947e fix: 💄 Particle animation 2022-04-03 19:11:39 -07:00
ThatOneCalculator d543cfc154 feat: 🔊 Alert user if single view 2022-04-03 19:09:05 -07:00
ThatOneCalculator 5021a3df8d fix: 🚨 Remove `/` for division outside of `calc()` 2022-04-03 19:04:04 -07:00
Kainoa Kanter 4fad42ff6a
Merge pull request #49 from zer0bin-dev/single-view-pastes 2022-04-03 19:00:08 -07:00
ThatOneCalculator 95d45b09d6 feat: 🔖 v1.1.0 2022-04-03 18:56:09 -07:00
ThatOneCalculator 9a2ccf73c3 feat: Single view paste icon 2022-04-03 18:54:18 -07:00
Dominic Harris a78713c24a
🐛 fix: Add lang to html 2022-03-28 15:19:03 -04:00
Dominic Harris f3e135df46
feature: A little less padding on button wrapper 2022-03-28 13:48:11 -04:00
Dominic Harris f2eb61fa0e
feature: Rounded corners 2022-03-28 09:30:00 -04:00
Dominic Harris 0e0e6daf8f
feature: Single view pastes works on the frontend 2022-03-27 15:21:54 -04:00
mellowmarshe 51f3293279
Merge pull request #47 from zer0bin-dev/main
Merge upstream single-view-pastes
2022-03-26 09:08:25 -04:00
Dominic Harris 871dcc5c38
feature: Single view pastes work on the backend 2022-03-26 08:37:07 -04:00
Dominic Harris c179f8bf90
feature: svp 2022-03-26 08:19:15 -04:00
Dominic Harris dc5c178152
♻️ refactor: Remove useless API call 2022-03-25 21:25:03 -04:00
Kainoa Kanter 1b4da8955d
deps: 📦 Move parcel to dev deps 2022-03-25 16:07:44 -07:00
Kainoa Kanter e11a496e8c
refactor: Further minify highlight.js 2022-03-25 15:27:01 -07:00
ThatOneCalculator fb81db3add feat: Custom highlight.js 2022-03-25 15:19:17 -07:00
Kainoa Kanter 113287e5dc
Merge pull request #45 from zer0bin-dev/hide-button 2022-03-25 14:41:37 -07:00
ThatOneCalculator 202cb98c39 refactor: Cut bundle size by almost 600kb 2022-03-25 14:39:43 -07:00
Dominic Harris 161662c4de
♻️ refactor: Add display: none defaults where sensible 2022-03-25 08:38:28 -04:00
Dominic Harris 77340f763c
♻️ refactor: Change tooltip text size 2022-03-24 19:46:29 -04:00
Dominic Harris c8a46307b8
♻️ refactor: Some css tings 2022-03-24 19:34:35 -04:00
Dominic Harris b983bc352f
feature: Okay should be good now 2022-03-24 18:10:15 -04:00
Dominic Harris 788235d411
feature: Add hide button 2022-03-24 17:58:08 -04:00
ThatOneCalculator 297042ab0e release: 🔖 v1.0.2 2022-03-24 07:11:17 -07:00
Dominic Harris 6bc1e8c421
feature: Raw endpoint is back! 2022-03-24 09:19:52 -04:00
ThatOneCalculator fb4b814e0a fix: 💄 Fix spacing on viewing markdown pastes 2022-03-23 23:27:27 -07:00
31 changed files with 1277 additions and 1878 deletions

View File

@ -1,3 +1,10 @@
"Wait, but isn't Cartograph CF a paid font you need a license for?"
![You](https://c.tenor.com/Mxgk7rxrzq8AAAAC/lithiumare-kiracord.gif)
# Ok but fr
People have been pirating Cartograph CF for a looong time, but if you would like to use Fira Code (a free font) instead:
1. `cd frontend`
2. `mv style/font-fira.scss style/font.scss`
3. Rebuild frontend

View File

@ -26,11 +26,16 @@
# Features
- ✨ Code highlighting and line numbers (default)
- 📖 Markdown rendering (add `---` or `md` to the start of your paste)
- 📖 Markdown rendering (click the <a href="https://github.com/zer0bin-dev/zer0bin"><img alt="Markdown" src="https://user-images.githubusercontent.com/44733677/161484749-fdf60750-36ae-4d0a-aaa5-cdcae54fc805.svg" height=18></a> button)
- 🔥 Single-view pastes (click the <a href="https://github.com/zer0bin-dev/zer0bin"><img alt="Fire" src="https://user-images.githubusercontent.com/44733677/161485115-c5fccb81-fa21-4e67-88fd-9a6f9dff728e.svg" height=18></a> button)
- ‍🧑‍💻 [CLI Client](https://github.com/zer0bin-dev/zer0)
- 🚀 Easily selfhostable
- 👀 View counter
- ⌨️ Keybinds (<kbd>Ctrl</kbd> + <kbd>S</kbd>: save paste, <kbd>Ctrl</kbd> + <kbd>N</kbd>: new paste, <kbd>Ctrl</kbd> + <kbd>D</kbd>: duplicate paste)
- ⌨️ Keybinds
- <kbd>Ctrl</kbd> + <kbd>S</kbd>: save paste
- <kbd>Ctrl</kbd> + <kbd>N</kbd>: new paste
- <kbd>Ctrl</kbd> + <kbd>D</kbd>: duplicate paste
- <kbd>Ctrl</kbd> + <kbd>M</kbd>: toggle markdown mode
- 📱 Mobile-friendly UI
- 🧈 Super smooth scrolling
- 🖼️ Badge generation for stats (seen below)
@ -41,15 +46,14 @@ Submit your public instance [here](https://github.com/Domterion/zer0bin/issues/n
| URL | Expiration | Max paste size | Total Pastes | Version | Country |
| ---------------------------------------------- | ---------- | -------------- | -------------------------------------------- | --------------------------------------------- | ------- |
| [zer0b.in](https://zer0b.in) | 90 days | 50,000 chars | ![pastes](https://zer0b.in/api/b/t) | ![version](https://zer0b.in/api/b/v) | 🇺🇸 USA |
| [stepbro.voring.me](https://stepbro.voring.me) | 365 days | 69,000 chars | ![pastes](https://stepbro.voring.me/api/b/t) | ![version](https://stepbro.voring.me/api/b/v) | 🇺🇸 USA |
| [tinker.nz](https://tinker.nz/) | 28 days | 69,420 chars | ![pastes](https://tinker.nz/api/b/t) | ![version](https://tinker.nz/api/b/v) | 🇳🇿 NZ |
| [paste.mint.lgbt](https://paste.mint.lgbt) | 30 days | 50,000 chars | ![pastes](https://paste.mint.lgbt/api/b/t) | ![version](https://paste.mint.lgbt/api/b/v) | 🇨🇱 Chile |
# Technologies used
### Frontend:
<a href="https://www.typescriptlang.org/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/TypeScript.svg" height=40/></a> <a href="https://definitelytyped.org/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953567495321710602/DefinitelyTyped.svg" height=40/></a> <a href="https://sass-lang.com/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Sass.svg" height=40/></a> <a href="https://pugjs.org/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Pug-Dark.svg" height=40/></a> <a href="https://rosepinetheme.com/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953176309444542464/RosePine.svg" height=40/></a> <a href="https://highlightjs.org/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/956227499229061140/hljs.svg" height=40/></a> <a href="https://marked.js.org/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/956263178961047612/MarkedJS.svg" height=40/></a> <a href="https://github.com/ant-design/ant-design-icons"><img src="https://cdn.discordapp.com/attachments/810799100940255260/956227498985799690/anticons.svg" height=40/></a><br><a href="https://github.com/idiotWu/smooth-scrollbar"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953564432628322364/SmoothScrollJS.svg" height=40/></a> <a href="https://atomiks.github.io/tippyjs/"><img src="https://cdn.discordapp.com/attachments/872332549777666078/955624715521769522/Tippy.svg" height=40/></a> <a href="https://github.com/loonywizard/js-confetti"><img src="https://cdn.discordapp.com/attachments/810799100940255260/955609316042362930/JSConfetti.svg" height=40/></a> <a href="https://github.com/hadialqattan/no-darkreader"><img src="https://cdn.discordapp.com/attachments/810799100940255260/955869669535907870/NoDarkReader.svg" height=40/></a> <a href="https://parceljs.org/"><img src="https://user-images.githubusercontent.com/44733677/158683062-17ac3b62-cacd-4add-babb-1f74f36020d8.svg" height=40/></a> <a href="https://prettier.io/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953339670538887318/Prettier.svg" height=40/></a> <a href="https://yarnpkg.org"><img src="https://cdn.discordapp.com/attachments/810799100940255260/954823377493852170/Yarn.svg" height=40/></a> <a href="https://transfonter.org"><img src="https://user-images.githubusercontent.com/44733677/159066877-234f68ba-e95c-439d-b5fe-74def49dc762.svg" height=40></a>
<a href="https://www.typescriptlang.org/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/TypeScript.svg" height=40/></a> <a href="https://sass-lang.com/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Sass.svg" height=40/></a> <a href="https://pugjs.org/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Pug-Dark.svg" height=40/></a> <a href="https://rosepinetheme.com/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953176309444542464/RosePine.svg" height=40/></a> <a href="https://highlightjs.org/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/956227499229061140/hljs.svg" height=40/></a> <a href="https://marked.js.org/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/956263178961047612/MarkedJS.svg" height=40/></a> <a href="https://github.com/ant-design/ant-design-icons"><img src="https://cdn.discordapp.com/attachments/810799100940255260/956227498985799690/anticons.svg" height=40/></a><br><a href="https://github.com/idiotWu/smooth-scrollbar"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953564432628322364/SmoothScrollJS.svg" height=40/></a> <a href="https://atomiks.github.io/tippyjs/"><img src="https://cdn.discordapp.com/attachments/872332549777666078/955624715521769522/Tippy.svg" height=40/></a> <a href="https://github.com/loonywizard/js-confetti"><img src="https://cdn.discordapp.com/attachments/810799100940255260/955609316042362930/JSConfetti.svg" height=40/></a> <a href="https://github.com/hadialqattan/no-darkreader"><img src="https://cdn.discordapp.com/attachments/810799100940255260/955869669535907870/NoDarkReader.svg" height=40/></a> <a href="https://vitejs.dev/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/961789632834600960/Vite-Dark.svg" height=40/></a> <a href="https://prettier.io/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953339670538887318/Prettier.svg" height=40/></a> <a href="https://yarnpkg.org"><img src="https://cdn.discordapp.com/attachments/810799100940255260/954823377493852170/Yarn.svg" height=40/></a>
### Backend:

235
backend/Cargo.lock generated
View File

@ -16,16 +16,15 @@ dependencies = [
"memchr",
"pin-project-lite",
"tokio",
"tokio-util 0.7.0",
"tokio-util",
]
[[package]]
name = "actix-cors"
version = "0.6.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30dbd116ef7532f56e2f6d7c511736ea0b124d914ee8820a5271247bf89f06aa"
checksum = "414360eed71ba2d5435b185ba43ecbe281dfab5df3898286d6b7be8074372c92"
dependencies = [
"actix-service",
"actix-utils",
"actix-web",
"derive_more",
@ -49,9 +48,9 @@ dependencies = [
[[package]]
name = "actix-http"
version = "3.0.0"
version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3fdd63b9cfeaf92eeeece719dabbddddb420a57d3fd171ce1490ecfb7086b1"
checksum = "a5885cb81a0d4d0d322864bea1bb6c2a8144626b4fdc625d4c51eba197e7797a"
dependencies = [
"actix-codec",
"actix-rt",
@ -110,9 +109,9 @@ dependencies = [
[[package]]
name = "actix-rt"
version = "2.6.0"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdf3f2183be1241ed4dd22611850b85d38de0b08a09f1f7bcccbd0809084b359"
checksum = "7ea16c295198e958ef31930a6ef37d0fb64e9ca3b6116e6b93a8bdae96ee1000"
dependencies = [
"actix-macros",
"futures-core",
@ -121,20 +120,20 @@ dependencies = [
[[package]]
name = "actix-server"
version = "2.0.0"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9e7472ac180abb0a8e592b653744345983a7a14f44691c8394a799d0df4dbbf"
checksum = "0da34f8e659ea1b077bb4637948b815cd3768ad5a188fdcd74ff4d84240cd824"
dependencies = [
"actix-rt",
"actix-service",
"actix-utils",
"futures-core",
"futures-util",
"log",
"mio",
"num_cpus",
"socket2",
"tokio",
"tracing",
]
[[package]]
@ -194,7 +193,7 @@ dependencies = [
"serde_urlencoded",
"smallvec",
"socket2",
"time 0.3.7",
"time 0.3.9",
"url",
]
@ -268,7 +267,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backend"
version = "1.0.1"
version = "1.1.1"
dependencies = [
"actix-cors",
"actix-governor",
@ -339,9 +338,9 @@ dependencies = [
[[package]]
name = "brotli"
version = "3.3.3"
version = "3.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f838e47a451d5a8fa552371f80024dd6ace9b7acdf25c4c3d0f9bc6816fb1c39"
checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
@ -410,7 +409,7 @@ dependencies = [
"num-integer",
"num-traits",
"serde",
"time 0.1.43",
"time 0.1.44",
"winapi",
]
@ -427,15 +426,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05"
dependencies = [
"percent-encoding",
"time 0.3.7",
"time 0.3.9",
"version_check",
]
[[package]]
name = "cpufeatures"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b"
dependencies = [
"libc",
]
@ -466,9 +465,9 @@ dependencies = [
[[package]]
name = "crossbeam-queue"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dd435b205a4842da59efd07628f921c096bc1cc0a156835b4fa0bcb9a19bcce"
checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2"
dependencies = [
"cfg-if",
"crossbeam-utils",
@ -476,9 +475,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.7"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6"
checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
dependencies = [
"cfg-if",
"lazy_static",
@ -506,9 +505,9 @@ dependencies = [
[[package]]
name = "dashmap"
version = "5.1.0"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0834a35a3fce649144119e18da2a4d8ed12ef3862f47183fd46f625d072d96c"
checksum = "4c8858831f7781322e539ea39e72449c46b059638250c14344fec8d0aa6e539c"
dependencies = [
"cfg-if",
"num_cpus",
@ -558,9 +557,9 @@ dependencies = [
[[package]]
name = "dirs-sys"
version = "0.3.6"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users",
@ -740,13 +739,13 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.5"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77"
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
dependencies = [
"cfg-if",
"libc",
"wasi",
"wasi 0.10.0+wasi-snapshot-preview1",
]
[[package]]
@ -768,9 +767,9 @@ dependencies = [
[[package]]
name = "h2"
version = "0.3.11"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e"
checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57"
dependencies = [
"bytes",
"fnv",
@ -781,7 +780,7 @@ dependencies = [
"indexmap",
"slab",
"tokio",
"tokio-util 0.6.9",
"tokio-util",
"tracing",
]
@ -873,9 +872,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "1.8.0"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
dependencies = [
"autocfg",
"hashbrown",
@ -943,9 +942,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.119"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
[[package]]
name = "local-channel"
@ -967,18 +966,19 @@ checksum = "902eb695eb0591864543cbfbf6d742510642a605a61fc5e97fe6ceb5a30ac4fb"
[[package]]
name = "lock_api"
version = "0.4.6"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.14"
version = "0.4.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
dependencies = [
"cfg-if",
]
@ -1039,14 +1039,15 @@ dependencies = [
[[package]]
name = "mio"
version = "0.8.0"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2"
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
dependencies = [
"libc",
"log",
"miow",
"ntapi",
"wasi 0.11.0+wasi-snapshot-preview1",
"winapi",
]
@ -1076,13 +1077,12 @@ checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
[[package]]
name = "nom"
version = "7.1.0"
version = "7.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
dependencies = [
"memchr",
"minimal-lexical",
"version_check",
]
[[package]]
@ -1131,18 +1131,18 @@ dependencies = [
[[package]]
name = "num_threads"
version = "0.1.3"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97ba99ba6393e2c3734791401b66902d981cb03bf190af674ca69949b6d5fb15"
checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0"
dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
[[package]]
name = "opaque-debug"
@ -1168,7 +1168,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
dependencies = [
"lock_api",
"parking_lot_core 0.9.1",
"parking_lot_core 0.9.2",
]
[[package]]
@ -1187,9 +1187,9 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.1"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954"
checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37"
dependencies = [
"cfg-if",
"libc",
@ -1200,9 +1200,9 @@ dependencies = [
[[package]]
name = "paste"
version = "1.0.6"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
[[package]]
name = "percent-encoding"
@ -1248,16 +1248,16 @@ dependencies = [
"mach",
"once_cell",
"raw-cpuid",
"wasi",
"wasi 0.10.0+wasi-snapshot-preview1",
"web-sys",
"winapi",
]
[[package]]
name = "quote"
version = "1.0.15"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58"
dependencies = [
"proc-macro2",
]
@ -1294,37 +1294,38 @@ dependencies = [
[[package]]
name = "raw-cpuid"
version = "10.2.0"
version = "10.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "929f54e29691d4e6a9cc558479de70db7aa3d98cd6fe7ab86d7507aa2886b9d2"
checksum = "738bc47119e3eeccc7e94c4a506901aea5e7b4944ecd0829cbebf4af04ceda12"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_syscall"
version = "0.2.10"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.0"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom",
"redox_syscall",
"thiserror",
]
[[package]]
name = "regex"
version = "1.5.4"
version = "1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
dependencies = [
"aho-corasick",
"memchr",
@ -1404,9 +1405,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "semver"
version = "1.0.6"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d"
checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4"
[[package]]
name = "serde"
@ -1499,9 +1500,9 @@ dependencies = [
[[package]]
name = "slab"
version = "0.4.5"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
[[package]]
name = "smallvec"
@ -1645,9 +1646,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.86"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f"
dependencies = [
"proc-macro2",
"quote",
@ -1676,19 +1677,20 @@ dependencies = [
[[package]]
name = "time"
version = "0.1.43"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
[[package]]
name = "time"
version = "0.3.7"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d"
checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd"
dependencies = [
"itoa 1.0.1",
"libc",
@ -1698,9 +1700,9 @@ dependencies = [
[[package]]
name = "time-macros"
version = "0.2.3"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6"
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
[[package]]
name = "tinyvec"
@ -1760,48 +1762,47 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.6.9"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64910e1b9c1901aaf5375561e35b9c057d95ff41a44ede043a03e09279eabaf1"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio",
"tracing",
]
[[package]]
name = "tracing"
version = "0.1.31"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f"
checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
dependencies = [
"cfg-if",
"log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.22"
name = "tracing-attributes"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23"
checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee"
dependencies = [
"lazy_static",
]
@ -1871,9 +1872,15 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
@ -1992,9 +1999,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.32.0"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6"
checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
@ -2005,33 +2012,33 @@ dependencies = [
[[package]]
name = "windows_aarch64_msvc"
version = "0.32.0"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d"
[[package]]
name = "windows_i686_gnu"
version = "0.32.0"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed"
[[package]]
name = "windows_i686_msvc"
version = "0.32.0"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956"
[[package]]
name = "windows_x86_64_gnu"
version = "0.32.0"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4"
[[package]]
name = "windows_x86_64_msvc"
version = "0.32.0"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9"
[[package]]
name = "zstd"

View File

@ -1,6 +1,6 @@
[package]
name = "backend"
version = "1.0.1"
version = "1.1.1"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -16,7 +16,7 @@ actix-governor = "0.3.0"
badge-maker = "0.2.1"
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "postgres", "chrono"] }
sqlx = { version = "0.5.11", features = ["runtime-tokio-rustls", "postgres", "chrono"] }
chrono = { version = "0.4.19", features = ["serde"] }

View File

@ -0,0 +1 @@
ALTER TABLE pastes ADD column single_view BOOLEAN DEFAULT false;

0
backend/schema.sql Executable file → Normal file
View File

View File

@ -2,7 +2,7 @@ mod config;
mod models;
mod routes;
use std::{io, path::PathBuf};
use std::{io, path::Path, path::PathBuf};
use actix_cors::Cors;
use actix_governor::{Governor, GovernorConfigBuilder};
@ -12,9 +12,11 @@ use actix_web::{
};
use config::Config;
use sqlx::{postgres::PgPoolOptions, PgPool};
use sqlx::{migrate::Migrator, postgres::PgPoolOptions, PgPool};
use crate::routes::{get_paste, get_stats, get_total_pastes_badge, get_version_badge, new_paste};
use crate::routes::{
get_paste, get_raw_paste, get_stats, get_total_pastes_badge, get_version_badge, new_paste,
};
#[derive(Clone)]
pub struct AppState {
@ -22,15 +24,29 @@ pub struct AppState {
pub pool: PgPool,
}
pub async fn migrations(pool: &PgPool) -> Result<(), sqlx::Error> {
Migrator::new(Path::new("./migrations"))
.await?
.run(pool)
.await?;
Ok(())
}
#[actix_rt::main]
async fn main() -> io::Result<()> {
let config = config::load(PathBuf::from("config.json"));
let db_uri = &config.databases.postgres_uri.to_string();
let pool = PgPoolOptions::new()
.max_connections(100)
.connect(&config.databases.postgres_uri)
.connect(db_uri)
.await
.expect("Failed to connect to database");
migrations(&pool).await.expect("Failed to run migrations");
let address = format!(
"{}:{}",
config.server.backend_host, config.server.backend_port
@ -62,7 +78,8 @@ async fn main() -> io::Result<()> {
web::scope("/p")
.wrap(Governor::new(&paste_governor))
.service(get_paste)
.service(new_paste), // .service(get_raw_paste),
.service(new_paste)
.service(get_raw_paste),
)
.service(
web::scope("/b")

View File

@ -7,12 +7,14 @@ pub struct Paste {
pub id: String,
pub content: String,
pub views: i64,
pub single_view: bool,
pub expires_at: Option<NaiveDateTime>,
}
#[derive(Deserialize)]
pub struct PartialPaste {
pub content: String,
pub single_view: bool
}
#[derive(Serialize)]
@ -25,6 +27,7 @@ pub struct ApiResponse<T> {
pub struct NewPasteResponse {
pub id: String,
pub content: String,
pub single_view: bool,
}
#[derive(Serialize)]
@ -32,6 +35,7 @@ pub struct GetPasteResponse {
pub id: String,
pub content: String,
pub views: i64,
pub single_view: bool,
pub expires_at: Option<NaiveDateTime>,
}

View File

@ -32,14 +32,21 @@ pub async fn get_paste(state: web::Data<AppState>, id: web::Path<String>) -> imp
match res {
Ok(p) => {
// this may be worth handling at some point..
let _ = sqlx::query(r#"UPDATE pastes SET "views" = "views" + 1 WHERE "id" = $1"#)
.bind(id.clone())
.execute(&state.pool)
.await;
// Only increment views if its not a single view paste
if p.single_view {
let _ = sqlx::query(r#"DELETE FROM pastes WHERE "id" = $1"#)
.bind(id.clone())
.execute(&state.pool)
.await;
} else {
let _ = sqlx::query(r#"UPDATE pastes SET "views" = "views" + 1 WHERE "id" = $1"#)
.bind(id.clone())
.execute(&state.pool)
.await;
}
if state.config.logging.on_get_paste {
println!("[GET] id={} views={}", id, p.views + 1);
println!("[GET] id={} views={} single_view={}", id, p.views + 1, p.single_view);
}
HttpResponse::Ok().json(ApiResponse {
@ -48,6 +55,7 @@ pub async fn get_paste(state: web::Data<AppState>, id: web::Path<String>) -> imp
id: p.id,
content: p.content,
views: p.views + 1,
single_view: p.single_view,
expires_at: p.expires_at,
},
})
@ -75,7 +83,6 @@ pub async fn get_paste(state: web::Data<AppState>, id: web::Path<String>) -> imp
}
}
// TODO: Fix major vuln
#[get("/r/{id}")]
pub async fn get_raw_paste(state: web::Data<AppState>, id: web::Path<String>) -> impl Responder {
let id = id.into_inner();
@ -88,13 +95,25 @@ pub async fn get_raw_paste(state: web::Data<AppState>, id: web::Path<String>) ->
match res {
Ok(p) => {
// this may be worth handling at some point..
let _ = sqlx::query(r#"UPDATE pastes SET "views" = "views" + 1 WHERE "id" = $1"#)
.bind(id.clone())
.execute(&state.pool)
.await;
if p.single_view {
let _ = sqlx::query(r#"DELETE FROM pastes WHERE "id" = $1"#)
.bind(id.clone())
.execute(&state.pool)
.await;
} else {
let _ = sqlx::query(r#"UPDATE pastes SET "views" = "views" + 1 WHERE "id" = $1"#)
.bind(id.clone())
.execute(&state.pool)
.await;
}
HttpResponse::Ok().body(p.content)
if state.config.logging.on_get_paste {
println!("[GET] raw id={} views={} single_view={}", id, p.views + 1, p.single_view);
}
HttpResponse::Ok()
.content_type("text/plain")
.body(p.content)
}
Err(e) => match e {
sqlx::Error::RowNotFound => {
@ -145,11 +164,13 @@ pub async fn new_paste(
};
let content = data.content.clone();
let single_view = data.single_view;
let res =
sqlx::query(r#"INSERT INTO pastes("id", "content", "expires_at") VALUES ($1, $2, $3)"#)
sqlx::query(r#"INSERT INTO pastes("id", "content", "single_view", "expires_at") VALUES ($1, $2, $3, $4)"#)
.bind(id.clone())
.bind(content.clone())
.bind(single_view)
.bind(expires_at)
.execute(&state.pool)
.await;
@ -157,11 +178,15 @@ pub async fn new_paste(
match res {
Ok(_) => {
if state.config.logging.on_post_paste {
println!("[POST] id={} length={}", id, content.len());
println!("[POST] id={} length={} single_view={}", id, content.len(), single_view);
}
HttpResponse::Ok().json(ApiResponse {
success: true,
data: NewPasteResponse { id, content },
data: NewPasteResponse {
id,
content,
single_view,
},
})
}
Err(e) => {

View File

@ -1,10 +0,0 @@
{
"extends": "@parcel/config-default",
"compressors": {
"*.{html,css,js,svg,map}": [
"...",
"@parcel/compressor-gzip",
"@parcel/compressor-brotli"
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

195
frontend/favicon.svg Normal file
View File

@ -0,0 +1,195 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="256"
height="256"
viewBox="0 0 256 256"
fill="none"
version="1.1"
id="svg12"
sodipodi:docname="zer0bin.svg"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
inkscape:export-filename="/home/kainoa/Downloads/zer0bin.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs16">
<g
id="SVG"
fill="#ffffff"
transform="scale(2) translate(20,79)">
<path
id="S"
d="M 5.482,31.319 C2.163,28.001 0.109,23.419 0.109,18.358 C0.109,8.232 8.322,0.024 18.443,0.024 C28.569,0.024 36.782,8.232 36.782,18.358 L26.042,18.358 C26.042,14.164 22.638,10.765 18.443,10.765 C14.249,10.765 10.850,14.164 10.850,18.358 C10.850,20.453 11.701,22.351 13.070,23.721 L13.075,23.721 C14.450,25.101 15.595,25.500 18.443,25.952 L18.443,25.952 C23.509,26.479 28.091,28.006 31.409,31.324 L31.409,31.324 C34.728,34.643 36.782,39.225 36.782,44.286 C36.782,54.412 28.569,62.625 18.443,62.625 C8.322,62.625 0.109,54.412 0.109,44.286 L10.850,44.286 C10.850,48.480 14.249,51.884 18.443,51.884 C22.638,51.884 26.042,48.480 26.042,44.286 C26.042,42.191 25.191,40.298 23.821,38.923 L23.816,38.923 C22.441,37.548 20.468,37.074 18.443,36.697 L18.443,36.692 C13.533,35.939 8.800,34.638 5.482,31.319 L5.482,31.319 L5.482,31.319 Z" />
<path
id="V"
d="M 73.452,0.024 L60.482,62.625 L49.742,62.625 L36.782,0.024 L47.522,0.024 L55.122,36.687 L62.712,0.024 L73.452,0.024 Z" />
<path
id="G"
d="M 91.792,25.952 L110.126,25.952 L110.126,44.286 L110.131,44.286 C110.131,54.413 101.918,62.626 91.792,62.626 C81.665,62.626 73.458,54.413 73.458,44.286 L73.458,44.286 L73.458,18.359 L73.453,18.359 C73.453,8.233 81.665,0.025 91.792,0.025 C101.913,0.025 110.126,8.233 110.126,18.359 L99.385,18.359 C99.385,14.169 95.981,10.765 91.792,10.765 C87.597,10.765 84.198,14.169 84.198,18.359 L84.198,44.286 L84.198,44.286 C84.198,48.481 87.597,51.880 91.792,51.880 C95.981,51.880 99.380,48.481 99.385,44.291 L99.385,44.286 L99.385,36.698 L91.792,36.698 L91.792,25.952 L91.792,25.952 Z" />
</g>
<clipPath
id="_clipPath_8TWIgR1z3pxinjWBiigzcEIrVJKv9Gq4">
<rect
width="500"
height="500"
id="rect836" />
</clipPath>
<filter
id="Hmac7mZraFWHw0G84Yxj4QuzeTFp0E7Y"
x="-0.22015058"
y="-0.085804489"
width="1.4403012"
height="1.171609"
filterUnits="objectBoundingBox"
color-interpolation-filters="sRGB">
<feGaussianBlur
in="SourceGraphic"
stdDeviation="6.440413594258542"
id="feGaussianBlur843" />
<feOffset
dx="0"
dy="0"
result="pf_100_offsetBlur"
id="feOffset845" />
<feFlood
flood-color="#000000"
flood-opacity="0.65"
id="feFlood847" />
<feComposite
in2="pf_100_offsetBlur"
operator="in"
result="pf_100_dropShadow"
id="feComposite849" />
<feBlend
in="SourceGraphic"
in2="pf_100_dropShadow"
mode="normal"
id="feBlend851" />
</filter>
<linearGradient
id="linearGradient5041">
<stop
style="stop-color:#3e4b4b;stop-opacity:1;"
offset="0"
id="stop5043" />
<stop
style="stop-color:#1e3449;stop-opacity:1;"
offset="1"
id="stop5045" />
</linearGradient>
<radialGradient
r="640"
fy="825.16089"
fx="293.49887"
cy="825.16089"
cx="293.49887"
gradientTransform="matrix(2.7998301,-1.4738538,0.45507806,0.86449643,-926.2596,769.338)"
gradientUnits="userSpaceOnUse"
id="radialGradient3133"
xlink:href="#linearGradient4453-1"
inkscape:collect="always" />
<linearGradient
id="linearGradient4453-1">
<stop
id="stop4455-4"
offset="0"
style="stop-color:#070808;stop-opacity:1" />
<stop
id="stop4457-0"
offset="1"
style="stop-color:#152534;stop-opacity:1" />
</linearGradient>
</defs>
<sodipodi:namedview
id="namedview14"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="1.28"
inkscape:cx="111.32812"
inkscape:cy="116.40625"
inkscape:window-width="1183"
inkscape:window-height="686"
inkscape:window-x="1353"
inkscape:window-y="730"
inkscape:window-maximized="1"
inkscape:current-layer="svg12" />
<rect
style="fill:#191724;fill-opacity:1;stroke:#9ccfd8;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect2248"
width="256"
height="256"
x="0"
y="0" />
<g
inkscape:label="Layer 1"
id="layer1"
style="display:none"
transform="translate(-606.58583,-699.5242)">
<image
y="392.14789"
x="-90.714287"
id="image3047"
xlink:href="../../tomasi/Projects/nimrod/logo/new-symbols.png"
height="329"
width="800" />
</g>
<path
inkscape:connector-curvature="0"
d="m 602.64247,29.71093 h -28.65 v 7.28362 c 0,1.59787 0.4668,2.98732 1.4003,4.16834 0.9336,1.18104 2.0863,1.84067 3.4542,1.77155 h 23.6088 v 5.013 h -25.1124 c -2.2405,0 -4.1698,-0.86841 -5.7879,-2.60522 -1.556,-1.80627 -2.3339,-3.95992 -2.3339,-6.46093 V 14.28805 c 0,-2.50097 0.7779,-4.61988 2.3339,-6.35673 1.6181,-1.80625 3.5474,-2.70938 5.7879,-2.70942 h 17.1773 c 2.2405,4e-5 4.1387,0.90317 5.6946,2.70942 1.6181,1.73685 2.4272,3.85576 2.4272,6.35673 v 15.42288 m -4.9576,-4.59617 V 16.1748 c 0,-1.59784 -0.4668,-2.98729 -1.4003,-4.16836 -0.9336,-1.18099 -2.1161,-1.77151 -3.5475,-1.77154 h -13.8901 c -1.3693,3e-5 -2.5206,0.59055 -3.4542,1.77154 -0.9335,1.18107 -1.6566,2.59635 -1.4003,4.16836 v 8.93996 h 23.6924 m -40.8208,-41.56827 -0.093,64.40095 h -25.4857 c -2.2406,0 -4.1699,-0.86841 -5.788,-2.60522 -1.5559,-1.80627 -2.3339,-3.95992 -2.3339,-6.46093 l 0.093,-24.59324 c 0.062,-2.50097 0.8713,-4.61988 2.4272,-6.35673 1.5559,-1.80625 3.4541,-2.70938 5.6947,-2.70942 h 20.3414 l 0.093,-21.67541 h 5.051 m -5.1444,59.80479 -0.093,-33.53321 h -18.7445 c -1.3692,4e-5 -2.5206,0.66002 -3.4542,1.97996 -0.9335,1.32001 -1.4003,2.77893 -1.4003,4.37677 l 0.093,20.81975 c 0,1.59787 0.4357,3.05679 1.307,4.37675 0.8713,1.31999 1.9915,1.97998 3.3608,1.97998 h 18.9312 m -40.4211,-4.46999 c 0,2.50101 -0.8091,4.65466 -2.4272,6.46093 -1.5559,1.73681 -3.4541,2.60522 -5.6946,2.60522 h -19.0443 c -2.2406,0 -4.1699,-0.86841 -5.788,-2.60522 -1.5559,-1.80627 -2.3339,-3.95992 -2.3339,-6.46093 V 14.28805 c 0,-2.50097 0.778,-4.61988 2.3339,-6.35673 1.6181,-1.80625 3.5474,-2.70938 5.788,-2.70942 h 19.0443 c 2.2405,4e-5 4.1387,0.90317 5.6946,2.70942 1.6181,1.73685 2.4272,3.85576 2.4272,6.35673 v 24.59324 m -4.9576,-1.88674 V 16.1748 c 0,-1.59784 -0.4668,-2.98729 -1.4003,-4.16836 -0.9336,-1.18099 -2.1161,-1.77151 -3.5475,-1.77154 h -15.7572 c -1.3692,3e-5 -2.5206,0.59055 -3.4541,1.77154 -0.9336,1.18107 -1.4004,2.57052 -1.4004,4.16836 v 20.81975 c 0,1.59787 0.4668,2.98732 1.4004,4.16834 0.9335,1.18104 2.0849,1.77155 3.4541,1.77155 h 15.7572 c 1.4314,0 2.6139,-0.59051 3.5475,-1.77155 0.9335,-1.18102 1.4003,-2.57047 1.4003,-4.16834 m -43.2742,-8.62734 h -4.9577 V 16.1748 c 0,-1.59784 -0.4667,-2.98729 -1.4003,-4.16836 -0.9335,-1.18099 -2.116,-1.77151 -3.5474,-1.77154 h -13.8902 c -1.3692,3e-5 -2.5206,0.59055 -3.4541,1.77154 -0.9336,1.18107 -1.4003,2.57052 -1.4003,4.16836 v 20.81975 c 0,1.59787 0.4667,2.98732 1.4003,4.16834 0.9335,1.18104 2.0849,1.77155 3.4541,1.77155 h 23.5155 l 0.093,5.013 h -25.1124 c -2.2405,0 -4.1698,-0.86841 -5.7879,-2.60522 -1.5559,-1.80627 -2.3339,-3.95992 -2.3339,-6.46093 V 14.28805 c 0,-2.50097 0.778,-4.61988 2.3339,-6.35673 1.6181,-1.80625 3.5474,-2.70938 5.7879,-2.70942 h 17.1773 c 2.2405,4e-5 4.1387,0.90317 5.6946,2.70942 1.6181,1.73685 2.4272,3.85576 2.4272,6.35673 v 14.07916"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:87.357px;line-height:125%;font-family:Discognate;-inkscape-font-specification:Discognate;letter-spacing:0px;word-spacing:0px;display:none;fill:#ffffff;fill-opacity:1;stroke:none"
id="path4870" />
<g
id="g881"
transform="translate(-2.593955,-1.015618)">
<path
fill="currentColor"
d="m 130.59396,234.67648 c -55.515318,0 -78.87335,-25.08496 -78.87335,-105.66087 0,-80.575902 23.358032,-105.660854 78.87335,-105.660854 55.51531,0 78.87334,25.084952 78.87334,105.660854 0,80.57591 -23.35803,105.66087 -78.87334,105.66087 z m 0,-29.18977 c 32.79723,0 48.15593,-11.40225 48.15593,-76.4711 0,-65.068838 -15.3587,-76.471096 -48.15593,-76.471096 -32.797246,0 -48.15594,11.402258 -48.15594,76.471096 0,65.06885 15.358694,76.4711 48.15594,76.4711 z"
id="path1181"
style="fill:#9ccfd8;fill-opacity:1;stroke-width:0.155958"
sodipodi:nodetypes="ssssssssss" />
<g
id="g1392"
transform="matrix(1.9416434,-0.45122023,0.48590571,2.0908983,88.365407,95.983077)">
<path
fill="#c1694f"
d="M 3.968,33.446 C 2.211,35.204 0.47,36.312 0.079,35.921 -0.312,35.53 0.797,33.789 2.554,32.032 4.311,30.274 6.052,29.166 6.443,29.557 6.833,29.948 5.725,31.688 3.968,33.446 Z"
id="path1368"
style="fill:#eb6f92;fill-opacity:1" />
<path
fill="#ffcc4d"
d="M 6.443,29.558 4.321,27.436 c 0,0 -1.083,1.393 -2.284,3.63 -0.9,1.676 -1.251,2.734 -1.251,2.734 l 0.707,0.707 0.707,0.707 c 0,0 1.059,-0.352 2.734,-1.251 2.237,-1.201 3.629,-2.284 3.629,-2.284 z"
id="path1370"
style="fill:#f6c177;fill-opacity:1" />
<path
fill="#31373d"
d="m 34.02,1.98 c -3.535,-3.536 -18.164,10.297 -18.871,11.004 -0.707,0.707 -1.304,1.348 -0.928,1.724 L 12.1,16.829 C 9.978,18.951 3.614,26.728 4.321,27.435 l 2.122,2.122 2.121,2.121 c 0.707,0.707 8.485,-5.657 10.607,-7.778 l 2.121,-2.121 c 0.376,0.376 1.017,-0.222 1.724,-0.929 C 23.723,20.144 37.556,5.516 34.02,1.98 Z"
id="path1372"
style="fill:#31748f;fill-opacity:1" />
<path
fill="#ffcc4d"
d="m 23.016,20.851 c 0.085,-0.084 0.362,-0.375 0.774,-0.817 l -7.823,-7.822 c -0.442,0.411 -0.732,0.689 -0.817,0.774 -0.707,0.707 -1.304,1.348 -0.928,1.724 l 3.535,3.536 3.536,3.535 c 0.375,0.374 1.016,-0.223 1.723,-0.93 z"
id="path1374"
style="fill:#f6c177;fill-opacity:1" />
<path
fill="#ffac33"
d="M 31.212,2.001 C 30.285,1.074 29.048,0.102 27.28,0.986 25.512,1.87 19.967,5.427 17.402,7.991 c -1.322,1.322 -1.247,2.102 -0.751,2.165 0.821,0.106 1.37,0.088 2.122,-0.663 0.75,-0.751 0.883,-2.033 0.883,-2.033 0,0 3.05,-2.342 5.458,-3.778 2.409,-1.437 3.268,-1.682 4.11,-0.84 0.842,0.842 1.988,-0.841 1.988,-0.841 z"
id="path1376"
style="fill:#ebbcba;fill-opacity:1" />
<path
fill="#ffac33"
d="m 28.87,2.487 4.643,4.643 c 0.353,-0.709 0.631,-1.384 0.818,-2.011 l -3.45,-3.45 C 30.254,1.857 29.58,2.135 28.87,2.487 Z"
id="path1378"
style="fill:#ebbcba;fill-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

5
frontend/index.html Normal file
View File

@ -0,0 +1,5 @@
<!DOCTYPE html>
<link rel="icon" type="image/x-icon" href="/favicon.svg" />
<link rel="stylesheet" href="/style/style.scss" />
<script type="module" src="/src/index.ts" defer></script>
<pug src="index.pug"></pug>

View File

@ -1,41 +1,57 @@
doctype html
head
meta(charset='UTF-8')
meta(name='viewport' content='width=device-width, initial-scale=1.0')
title zer0bin
link(rel='shortcut icon' type='image/x-icon' href='favicon.ico')
meta(name='theme-color' content='#90BDC9')
meta(name='keywords' content='zerobin, zer0bin, paste, paste bin, pastebin, pastebin alternative, foss pastebin, open source pastebin, free pastebin, ghostbin, hastebin, pastebin.com, free pastebin online, paste online, github paste, github gist, github gist paste')
meta(name='darkreader' content='NO-DARKREADER-PLUGIN')
link(href='style/style.scss' rel='stylesheet')
link(href='style/rosepine.min.css' rel='stylesheet')
meta(name='title' content='zer0bin')
meta(name='description' content='🖊 Just a place to paste')
meta(property='og:type' content='website')
meta(property='og:title' content='zer0bin')
meta(property='og:description' content='🖊 Just a place to paste')
meta(property='og:image' content='https://raw.githubusercontent.com/zer0bin-dev/.github/main/zer0bin.png')
meta(property='twitter:title' content='zer0bin')
meta(property='twitter:description' content='🖊 Just a place to paste')
meta(property='twitter:image' content='https://raw.githubusercontent.com/zer0bin-dev/.github/main/zer0bin.png')
script(defer='' type='module' src='src/index.ts')
script(defer='' type='module' src='src/icons.ts')
!= '<!--\n'
!= '▀▀█ █▀▀ █▀▀█ █▀▀█ █▀▀▄ ▀ █▀▀▄ \n'
!= '▄▀ █▀▀ █▄▄▀ █▄▀█ █▀▀▄ █ █ █ \n'
!= '▀▀▀ ▀▀▀ ▀ ▀▀ █▄▄█ ▀▀▀ ▀ ▀ ▀ \n'
!= 'Thank you for using zer0bin!\n'
!= 'If you\'re reading this message, why not help with development?\n'
!= 'https://github.com/zer0bin-dev/zer0bin'
!= '\n-->\n'
ul.noselect#messages
.button-wrapper.noselect(style='position: fixed')
a.logo.noselect(href='/') zer0bin
.buttons.noselect
button#save-button.btn(aria-label='Save')
a(href='/' aria-label='New paste')
button#new-button.btn(aria-label='New paste')
button#copy-button.btn(aria-label='Copy')
a(href='https://github.com/zer0bin-dev/zer0bin' aria-label='GitHub repo')
button#github-button.btn(aria-label='GitHub')
span.viewcounter.noselect#viewcounter-label Views:&nbsp;
span.viewcounter.noselect#viewcounter-count
.scrollbar-container
.wrapper
.line-numbers.noselect
pre#code-view-pre
code#code-view
textarea#text-area(spellcheck='false' autofocus='' name='value' aria-label='Paste input area' disabled='')
html(lang='en')
head
meta(charset='UTF-8')
meta(name='viewport' content='width=device-width, initial-scale=1.0')
title zer0bin
meta(name='theme-color' content='#90BDC9')
meta(name='keywords' content='zerobin, zer0bin, paste, paste bin, pastebin, pastebin alternative, foss pastebin, open source pastebin, free pastebin, ghostbin, hastebin, pastebin.com, free pastebin online, paste online, github paste, github gist, github gist paste')
meta(name='darkreader' content='NO-DARKREADER-PLUGIN')
meta(name='title' content='zer0bin')
meta(name='description' content='🖊 Just a place to paste')
meta(property='og:type' content='website')
meta(property='og:title' content='zer0bin')
meta(property='og:description' content='🖊 Just a place to paste')
meta(property='og:image' content='https://raw.githubusercontent.com/zer0bin-dev/.github/main/zer0bin.png')
meta(property='twitter:title' content='zer0bin')
meta(property='twitter:description' content='🖊 Just a place to paste')
meta(property='twitter:image' content='https://raw.githubusercontent.com/zer0bin-dev/.github/main/zer0bin.png')
body
ul.noselect#messages
.button-wrapper.noselect()
a.logo.noselect(href='/') zer0bin
.buttons.noselect
button#save-button.btn(aria-label='Save')
button#markdown-button.btn(aria-label='Markdown')
button#single-view-button.btn(aria-label='Single View')
//- .fireBody(style='visibility: hidden')
//- - var parts = 20;
//- - while (parts--) {
//- .particle
//- - }
button#new-button.btn(aria-label='New paste')
button#copy-button.btn(aria-label='Copy')
button#share-button.btn(aria-label='Share')
a(href='https://github.com/zer0bin-dev/zer0bin' aria-label='GitHub repo')
button#github-button.btn(aria-label='GitHub')
span.viewcounter.noselect#viewcounter-label(style='visibility: hidden; display: none') Views:&nbsp;
span.viewcounter.noselect#viewcounter-count(style='visibility: hidden; display: none')
.bottom-button-wrapper
button#hide-button.btn(aria-label='Hide')
.scrollbar-container
.wrapper
.line-numbers.noselect
pre#code-view-pre(style='visibility: hidden')
code#code-view
textarea#text-area(spellcheck='false' autofocus='' name='value' aria-label='Paste input area' disabled='' style='visibility: hidden')

View File

@ -1,30 +1,32 @@
{
"name": "zer0bin",
"source": "index.pug",
"version": "1.0.1",
"version": "1.1.1",
"browserslist": "> 0.5%, last 2 versions, not dead",
"license": "MIT",
"scripts": {
"start": "parcel index.pug",
"build": "parcel build index.pug --public-url /"
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"@types/core-js": "^2.5.5",
"@types/node": "^17.0.21"
"@types/node": "^17.0.21",
"pug": "^3.0.2",
"sass": "^1.50.0",
"vite": "^2.9.0",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-pug": "^0.3.1"
},
"description": "just a place to paste",
"repository": "https://github.com/zer0bin-dev/zer0bin",
"author": "Domterion, ThatOneCalculator",
"dependencies": {
"@ant-design/icons": "^4.7.0",
"@ant-design/icons-svg": "^4.2.1",
"@parcel/core": "^2.4.0",
"@parcel/transformer-pug": "^2.4.0",
"highlight.js": "^11.4.0",
"highlight.js": "^11.5.0",
"js-confetti": "^0.10.2",
"marked": "^4.0.12",
"no-darkreader": "^1.0.1",
"parcel": "^2.4.0",
"smooth-scrollbar": "^8.7.4",
"tippy.js": "^6.3.7"
}

2
frontend/src/env.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
declare const API_URL: string
declare const CONFETTI_CHANCE: string

View File

@ -6,35 +6,51 @@ import {
ForkOutlined,
HeartOutlined,
StarOutlined,
EyeOutlined,
EyeInvisibleOutlined,
FireOutlined,
FileMarkdownOutlined,
ShareAltOutlined,
} from "@ant-design/icons-svg"
import { renderIconDefinitionToSVGElement } from "@ant-design/icons-svg/es/helpers"
import tippy from "tippy.js"
import "../style/tooltip.scss"
import "tippy.js/animations/scale.css"
import { IconDefinition } from "@ant-design/icons-svg/lib/types"
const saveButton = <HTMLButtonElement>document.getElementById("save-button")
const newButton = <HTMLButtonElement>document.getElementById("new-button")
const copyButton = <HTMLButtonElement>document.getElementById("copy-button")
const hideButton = <HTMLButtonElement>document.getElementById("hide-button")
const githubButton = <HTMLButtonElement>document.getElementById("github-button")
const shareButton = <HTMLButtonElement>document.getElementById("share-button")
const markdownButton = <HTMLButtonElement>(
document.getElementById("markdown-button")
)
const singleViewButton = <HTMLButtonElement>(
document.getElementById("single-view-button")
)
const extraSVGAttrs = {
width: "1em",
height: "1em",
fill: "currentColor",
}
function renderIcon(elem: HTMLButtonElement, icon: IconDefinition) {
elem.innerHTML += renderIconDefinitionToSVGElement(icon, {
extraSVGAttrs: extraSVGAttrs,
})
}
saveButton.innerHTML += renderIconDefinitionToSVGElement(SaveOutlined, {
extraSVGAttrs: extraSVGAttrs,
})
newButton.innerHTML += renderIconDefinitionToSVGElement(FileAddOutlined, {
extraSVGAttrs: extraSVGAttrs,
})
copyButton.innerHTML += renderIconDefinitionToSVGElement(CopyOutlined, {
extraSVGAttrs: extraSVGAttrs,
})
githubButton.innerHTML += renderIconDefinitionToSVGElement(GithubOutlined, {
extraSVGAttrs: extraSVGAttrs,
})
renderIcon(saveButton, SaveOutlined)
renderIcon(newButton, FileAddOutlined)
renderIcon(copyButton, CopyOutlined)
renderIcon(githubButton, GithubOutlined)
renderIcon(hideButton, EyeInvisibleOutlined)
renderIcon(markdownButton, FileMarkdownOutlined)
renderIcon(singleViewButton, FireOutlined)
renderIcon(shareButton, ShareAltOutlined)
tippy("#save-button", {
content: "Save paste<br><span class='keybind'>Ctrl + S</span>",
@ -44,6 +60,23 @@ tippy("#save-button", {
allowHTML: true,
})
tippy("#markdown-button", {
content: "Markdown mode<br><span class='keybind'>Ctrl + M</span>",
placement: "bottom",
animation: "scale",
theme: "rosepine",
allowHTML: true,
})
tippy("#single-view-button", {
content:
"Single view<br><span class='keybind'>Deletes after seen 👻</span>",
placement: "bottom",
animation: "scale",
theme: "rosepine",
allowHTML: true,
})
tippy("#new-button", {
content: "New paste<br><span class='keybind'>Ctrl + N</span>",
placement: "bottom",
@ -60,6 +93,14 @@ tippy("#copy-button", {
allowHTML: true,
})
tippy("#share-button", {
content: `Share paste<br><span class='keybind'>Copies URL</span>`,
placement: "top",
animation: "scale",
theme: "rosepine",
allowHTML: true,
})
tippy("#github-button", {
content: `GitHub<br><span class='keybind'>
${renderIconDefinitionToSVGElement(StarOutlined, {
@ -75,6 +116,14 @@ tippy("#github-button", {
allowHTML: true,
})
tippy("#hide-button", {
content: "Hide the button pane",
placement: "top",
animation: "scale",
theme: "rosepine",
allowHTML: true,
})
const observer = new MutationObserver(callback)
function callback() {
@ -95,3 +144,18 @@ function callback() {
observer.observe(document.getElementById("code-view-pre"), {
attributes: true,
})
export function toggleHiddenIcon(hidden: boolean) {
if (!hidden) {
hideButton.innerHTML = renderIconDefinitionToSVGElement(
EyeInvisibleOutlined,
{
extraSVGAttrs: extraSVGAttrs,
}
)
} else {
hideButton.innerHTML = renderIconDefinitionToSVGElement(EyeOutlined, {
extraSVGAttrs: extraSVGAttrs,
})
}
}

View File

@ -1,19 +1,26 @@
import "no-darkreader"
import hljs from "highlight.js"
import { marked } from "marked"
import JSConfetti from "js-confetti"
import Scrollbar from "smooth-scrollbar"
import config from "../config.json"
const apiUrl = config.api_url
const confettiChance = parseInt(config.confetti_chance)
import "./icons"
import hljs from "highlight.js/lib/common"
// import hljs from "../min/highlight.min"
import "../min/rosepine.min.css"
import { toggleHiddenIcon } from "./icons"
let rawContent = ""
let buttonPaneHidden = false
let isMarkdown = false
let singleView = false
const jsConfetti = new JSConfetti()
const lineNumbers = <HTMLElement>document.querySelector(".line-numbers")
const wrapper = <HTMLPreElement>document.querySelector(".wrapper")
const buttonWrapper = <HTMLPreElement>document.querySelector(".button-wrapper")
const editor = <HTMLTextAreaElement>document.getElementById("text-area")
const codeViewPre = <HTMLPreElement>document.getElementById("code-view-pre")
const codeView = <HTMLElement>document.getElementById("code-view")
@ -27,13 +34,23 @@ const viewCounter = <HTMLSpanElement>(
const saveButton = <HTMLButtonElement>document.getElementById("save-button")
const newButton = <HTMLButtonElement>document.getElementById("new-button")
const copyButton = <HTMLButtonElement>document.getElementById("copy-button")
const hideButton = <HTMLButtonElement>document.getElementById("hide-button")
const shareButton = <HTMLButtonElement>document.getElementById("share-button")
const markdownButton = <HTMLButtonElement>(
document.getElementById("markdown-button")
)
const singleViewButton = <HTMLButtonElement>(
document.getElementById("single-view-button")
)
function hide(element: HTMLElement) {
element.style.display = "none"
element.style.visibility = "hidden"
element.style.opacity = "0"
}
function show(element: HTMLElement) {
element.style.display = null
element.style.visibility = "visible"
element.style.opacity = "1"
}
function disable(element: HTMLButtonElement) {
@ -45,8 +62,8 @@ function enable(element: HTMLButtonElement) {
}
async function postPaste(content: string, callback: Function) {
const payload = { content }
await fetch(`${apiUrl}/p/n`, {
const payload = { content, single_view: singleView }
await fetch(`${API_URL}/p/n`, {
method: "POST",
headers: {
"Content-Type": "application/json",
@ -70,7 +87,7 @@ async function postPaste(content: string, callback: Function) {
}
async function getPaste(id: string, callback: Function) {
await fetch(`${apiUrl}/p/${id}`, {
await fetch(`${API_URL}/p/${id}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
@ -100,6 +117,8 @@ function newPaste() {
enable(saveButton)
disable(newButton)
disable(copyButton)
disable(shareButton)
enable(singleViewButton)
editor.value = ""
rawContent = ""
@ -110,6 +129,8 @@ function newPaste() {
hide(codeViewPre)
hide(viewCounterLabel)
hide(viewCounter)
viewCounterLabel.style.display = "none"
viewCounter.style.display = "none"
}
function addMessage(message: string) {
@ -125,26 +146,53 @@ function addMessage(message: string) {
}, 3000)
}
function viewPaste(content: string, views: string) {
function viewPaste(content: string, views: string, singleView: boolean) {
lineNumbers.innerHTML = ""
for (let i = 1; i <= content.split("\n").length; i++) {
lineNumbers.innerHTML = lineNumbers.innerHTML + `${i}<br>`
}
if (content.startsWith("---") || content.startsWith("md ") || content.startsWith("md\n")) {
if (
content.startsWith("---") ||
content.startsWith("md ") ||
content.startsWith("md\n")
) {
codeView.innerHTML = marked.parse(content.substring(3))
hide(lineNumbers)
} else {
for (let i = 1; i <= content.split("\n").length; i++) {
lineNumbers.innerHTML = lineNumbers.innerHTML + `${i}<br>`
}
codeView.innerHTML = hljs.highlightAuto(content).value
}
if (singleView) {
show(singleViewButton.firstElementChild as HTMLElement)
singleViewButton.lastElementChild.classList.add("fire")
addMessage("This is a single-view paste!")
}
enable(shareButton)
shareButton.addEventListener("click", function () {
const url = window.location.toString()
if (navigator.canShare) {
navigator.share({
title: "zer0bin paste",
url: url,
})
} else {
navigator.clipboard.writeText(url)
addMessage("Copied URL to clipboard!")
}
})
disable(saveButton)
disable(markdownButton)
enable(newButton)
enable(copyButton)
hide(editor)
disable(singleViewButton)
hide(editor)
show(codeViewPre)
show(viewCounterLabel)
show(viewCounter)
viewCounterLabel.style.display = null
viewCounter.style.display = null
viewCounter.textContent = views
@ -168,9 +216,11 @@ async function savePaste() {
window.history.pushState(null, "", `/${res["data"]["id"]}`)
rawContent = res["data"]["content"]
viewPaste(rawContent, "0")
viewPaste(rawContent, "0", res["data"]["single_view"])
const rand = Math.floor(Math.random() * confettiChance * 6)
const rand = Math.floor(
Math.random() * parseInt(CONFETTI_CHANCE ?? "10") * 6
)
if (rand < 5) {
jsConfetti.addConfetti({
@ -197,20 +247,24 @@ async function savePaste() {
}
async function duplicatePaste() {
const path = window.location.pathname
const split = path.split("/")
const id = split[split.length - 1]
await getPaste(id, function (err, res) {
if (err) {
return
}
const content = res["data"]["content"]
window.history.pushState(null, "", "/")
newPaste()
const content = rawContent
window.history.pushState(null, "", "/")
newPaste()
rawContent = content
editor.value = content
})
rawContent = content
editor.value = content
}
function toggleMarkdown() {
let val = editor.value
markdownButton.lastElementChild.classList.toggle("markdown")
if (isMarkdown) {
isMarkdown = false
val = val.substring(val.indexOf("\n") + 1)
} else {
isMarkdown = true
val = `---\n${val}`
}
}
saveButton.addEventListener("click", async function () {
@ -218,22 +272,25 @@ saveButton.addEventListener("click", async function () {
})
document.addEventListener("keydown", (e) => {
if (e.ctrlKey && e.key === "s") {
if (e.ctrlKey && e.code === "KeyS") {
e.preventDefault()
savePaste()
} else if (e.ctrlKey && e.key === "n") {
} else if (e.ctrlKey && e.code === "KeyN") {
e.preventDefault()
newPaste()
} else if (e.ctrlKey && e.key === "d") {
} else if (e.ctrlKey && e.code === "KeyD") {
e.preventDefault()
duplicatePaste()
} else if (e.ctrlKey && e.code === "KeyM") {
e.preventDefault()
toggleMarkdown()
}
})
editor.addEventListener(
"keydown",
function (e: KeyboardEvent) {
if (e.key == "Tab") {
if (e.code == "Tab") {
e.preventDefault()
let start: number = this.selectionStart
@ -258,6 +315,33 @@ newButton.addEventListener("click", function () {
window.location.href = "/"
})
hideButton.addEventListener("click", function () {
if (!buttonPaneHidden) {
buttonPaneHidden = true
hide(buttonWrapper)
} else {
buttonPaneHidden = false
show(buttonWrapper)
}
toggleHiddenIcon(buttonPaneHidden)
})
markdownButton.addEventListener("click", function () {
toggleMarkdown()
})
singleViewButton.addEventListener("click", function () {
singleViewButton.lastElementChild.classList.toggle("fire")
if (singleView) {
singleView = false
hide(singleViewButton.firstElementChild as HTMLElement)
} else {
singleView = true
show(singleViewButton.firstElementChild as HTMLElement)
}
})
async function handlePopstate() {
const path = window.location.pathname
@ -273,7 +357,11 @@ async function handlePopstate() {
newPaste()
} else {
rawContent = res["data"]["content"]
viewPaste(rawContent, res["data"]["views"].toString())
viewPaste(
rawContent,
res["data"]["views"].toString(),
res["data"]["single_view"]
)
}
})
}

View File

@ -24,7 +24,7 @@
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "es6" /* Specify what module code is generated. */,
"module": "esnext" /* Specify what module code is generated. */,
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */

View File

@ -0,0 +1,7 @@
@font-face {
font-family: "Cartograph CF";
src: url("../fonts/FiraCode-VF.woff2") format("woff2");
font-weight: normal;
font-style: normal;
font-display: swap;
}

View File

@ -1,17 +1,13 @@
@font-face {
font-family: "Cartograph CF";
src: local("../fonts/CartographCF-Regular.woff2") format("woff2"),
local("../fonts/CartographCF-Regular.woff") format("woff"),
local("../fonts/CartographCF-Regular.ttf") format("truetype");
src: url("../fonts/CartographCF-Regular.woff2") format("woff2");
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Cartograph CF";
src: local("../fonts/CartographCF-RegularItalic.woff2") format("woff2"),
local("../fonts/CartographCF-RegularItalic.woff") format("woff"),
local("../fonts/CartographCF-RegularItalic.ttf") format("truetype");
src: url("../fonts/CartographCF-RegularItalic.woff2") format("woff2");
font-weight: normal;
font-style: italic;
font-display: swap;

View File

@ -129,9 +129,11 @@ textarea {
position: fixed !important;
top: 0;
right: 0;
padding: 1rem 1rem 0.5rem 1rem;
padding: 0.7rem 0.7rem 0.5rem 0.7rem;
background-color: $bg_surface;
border-bottom-left-radius: 10px;
z-index: 10;
transition: opacity 0.2s, visibility 0.2s;
}
.buttons {
display: flex;
@ -170,11 +172,37 @@ a {
&:disabled {
color: $muted;
}
transition: all 0.2s ease-in;
}
.btn[disabled] {
color: $muted;
cursor: auto;
}
.bottom-button-wrapper {
position: fixed !important;
bottom: 0;
right: 0;
padding: 1rem 1rem 0.5rem 1rem;
z-index: 10;
.btn {
color: $muted;
&:hover {
color: $gold;
}
}
}
// #share-button {
// position: fixed !important;
// bottom: 0;
// left: 0;
// z-index: 10;
// color: $muted;
// &:hover {
// color: $rose;
// }
// padding: 10px;
// }
.keybind {
color: $subtle;
font-size: 11px;
@ -206,6 +234,58 @@ a {
animation: rainbow 3s ease infinite !important;
}
}
.markdown {
color: $iris;
}
.fire {
color: $love;
}
// $dur: 1s;
// $blur: 0.02em;
// $fireRad: 3em;
// $parts: 20;
// $partSize: 5em;
// .fireBody {
// font-size: 3px;
// filter: blur($blur);
// -webkit-filter: blur($blur);
// margin: 2em auto 0 auto;
// position: absolute;
// width: 6em;
// height: 5em;
// z-index: 0;
// opacity: 0.5;
// }
// .particle {
// animation: rise $dur ease-in infinite;
// background-image: radial-gradient($love 100%, $love 100%);
// border-radius: 50%;
// mix-blend-mode: screen;
// opacity: 0;
// position: absolute;
// bottom: 0;
// width: $partSize;
// height: $partSize;
// @for $p from 1 through $parts {
// &:nth-of-type(#{$p}) {
// animation-delay: $dur * random();
// left: calc((100% - #{$partSize}) * calc(($p - 1) / $parts));
// }
// }
// }
// @keyframes rise {
// from {
// opacity: 0;
// transform: translateY(0) scale(1);
// }
// 25% {
// opacity: 1;
// }
// to {
// opacity: 0;
// transform: translateY(-10em) scale(0);
// }
// }
#messages {
position: absolute;
top: 0;

View File

@ -11,6 +11,8 @@ $font-mono: "Cartograph CF", ui-monospace, SFMono-Regular, Menlo, Monaco,
opacity: 0.8;
padding: 10px;
font-family: $font-mono;
font-size: 13px;
border-radius: 10px;
> .tippy-backdrop {
background-color: $bg;
}

40
frontend/vite.config.ts Normal file
View File

@ -0,0 +1,40 @@
import { defineConfig, loadEnv } from "vite"
import pugPlugin from "vite-plugin-pug"
import viteCompression from "vite-plugin-compression"
import { createRequire } from "module"
export default defineConfig(async ({ mode }) => {
let config: any
const env = loadEnv(mode, process.cwd(), "")
try {
// @ts-ignore
// lazy hack so vite doesn't emit:
// [rollup-plugin-dynamic-import-variables] Unexpected token (46:55)
// file: zer0bin/frontend/src/index.ts:46:55
// error during build:
// SyntaxError: Unexpected token (46:55)
const _config = await import("./config.json")
config = {
api_url: JSON.stringify(_config.api_url),
confetti_chance: JSON.stringify(_config.confetti_chance),
}
} catch (e) {
config = {
api_url: JSON.stringify(env.ZEROBIN_API_URL ?? env.API_URL),
confetti_chance: JSON.stringify(
env.ZEROBIN_CONFETTI_CHANCE ?? env.CONFETTI_CHANCE
),
}
}
return {
plugins: [pugPlugin(), viteCompression()],
define: {
API_URL: config.api_url,
CONFETTI_CHANCE: config.confetti_chance,
},
}
})

File diff suppressed because it is too large Load Diff