mirror of https://github.com/zer0bin-dev/zer0bin
Compare commits
186 Commits
Author | SHA1 | Date |
---|---|---|
Kainoa Kanter | 832ccc3e88 | |
Kainoa Kanter | 1677032f4e | |
Daniel Mason | 9c245cf827 | |
Kainoa Kanter | ac1f4cf33a | |
hkc | 90d1966779 | |
Kainoa Kanter | f0a3670913 | |
Kainoa Kanter | 81e5a3f7a8 | |
Mars | e7c96047cf | |
Kainoa Kanter | e2037f7522 | |
idanoo | 7eb63190f0 | |
Kainoa Kanter | 82d2087281 | |
Kainoa Kanter | 5e77dcf43b | |
mellowmarshe | db0d09bad7 | |
Noel | 0c78b83b30 | |
Noel | 6e8e2b119a | |
Noel | 479354fe2c | |
Noel | 75de8c53e3 | |
Noel | e9e18e3501 | |
domterion | de58aa84c2 | |
ThatOneCalculator | fd6b91977b | |
ThatOneCalculator | 0050ea2fb9 | |
ThatOneCalculator | 5bb8c3441b | |
Kainoa Kanter | 3ee8b85213 | |
ThatOneCalculator | 535530c34f | |
ThatOneCalculator | 21ec4c1ef0 | |
ThatOneCalculator | d683701360 | |
ThatOneCalculator | 0e1bb82944 | |
ThatOneCalculator | f1ccf6a836 | |
ThatOneCalculator | fa07222803 | |
ThatOneCalculator | 3cfda99765 | |
ThatOneCalculator | d96287c206 | |
mellowmarshe | 1146f4b7da | |
Kainoa Kanter | 7be6aa6cf2 | |
ThatOneCalculator | 6f55b59d7b | |
ThatOneCalculator | 9ff53c1345 | |
ThatOneCalculator | f001286f5b | |
Kainoa Kanter | b03ca2c8f7 | |
ThatOneCalculator | 648b6aac4e | |
ThatOneCalculator | fff67c1a43 | |
ThatOneCalculator | 4f62e7f4ee | |
Kainoa Kanter | 8ad0b5790d | |
ThatOneCalculator | 6ee88465fa | |
Dominic Harris | 36e81a6c4f | |
Kainoa Kanter | 794403ae97 | |
ThatOneCalculator | ead9d9108e | |
ThatOneCalculator | be7617476f | |
ThatOneCalculator | bbccfc4314 | |
ThatOneCalculator | a2b6392b03 | |
ThatOneCalculator | 407a4997f6 | |
ThatOneCalculator | 0081ddeafa | |
ThatOneCalculator | ee5e9a1ca3 | |
ThatOneCalculator | 667e00b894 | |
ThatOneCalculator | 8d6e3b6378 | |
ThatOneCalculator | bd718fadde | |
Kainoa Kanter | 44e996c60d | |
ThatOneCalculator | 18e2ba0200 | |
ThatOneCalculator | 70c84ebaba | |
ThatOneCalculator | abeebd045f | |
ThatOneCalculator | a2b3104c08 | |
ThatOneCalculator | 3eb141ec72 | |
ThatOneCalculator | cbd21b6bb2 | |
ThatOneCalculator | 5fe090c302 | |
ThatOneCalculator | 35004d8f0f | |
ThatOneCalculator | fa78dd4246 | |
ThatOneCalculator | 1bd6d3721a | |
ThatOneCalculator | d260e338f5 | |
ThatOneCalculator | 658538fd61 | |
ThatOneCalculator | 67f753c0d6 | |
ThatOneCalculator | 4a921a947e | |
ThatOneCalculator | d543cfc154 | |
ThatOneCalculator | 5021a3df8d | |
Kainoa Kanter | 4fad42ff6a | |
ThatOneCalculator | 95d45b09d6 | |
ThatOneCalculator | 9a2ccf73c3 | |
Dominic Harris | a78713c24a | |
Dominic Harris | f3e135df46 | |
Dominic Harris | f2eb61fa0e | |
Dominic Harris | 0e0e6daf8f | |
mellowmarshe | 51f3293279 | |
Dominic Harris | 871dcc5c38 | |
Dominic Harris | c179f8bf90 | |
Dominic Harris | dc5c178152 | |
Kainoa Kanter | 1b4da8955d | |
Kainoa Kanter | e11a496e8c | |
ThatOneCalculator | fb81db3add | |
Kainoa Kanter | 113287e5dc | |
ThatOneCalculator | 202cb98c39 | |
Dominic Harris | 161662c4de | |
Dominic Harris | 77340f763c | |
Dominic Harris | c8a46307b8 | |
Dominic Harris | b983bc352f | |
Dominic Harris | 788235d411 | |
ThatOneCalculator | 297042ab0e | |
Dominic Harris | 6bc1e8c421 | |
ThatOneCalculator | fb4b814e0a | |
ThatOneCalculator | f57312e308 | |
Kainoa Kanter | fd3334ea7c | |
Kainoa Kanter | 024feb777a | |
Kainoa Kanter | 92cbc3f49e | |
Dominic Harris | 9b8fcbd757 | |
Kainoa Kanter | bc59fc6359 | |
Kainoa Kanter | e863421fae | |
Kainoa Kanter | 807aa1f516 | |
ThatOneCalculator | 40f2d7a578 | |
ThatOneCalculator | 02f91b3f8d | |
Kainoa Kanter | 30cc4c3890 | |
Kainoa Kanter | 525a254531 | |
Kainoa Kanter | 4e25416f80 | |
Kainoa Kanter | e9db6c2c7b | |
ThatOneCalculator | a5a9620efd | |
ThatOneCalculator | 2f1dd15048 | |
Kainoa Kanter | f844f5f4ae | |
Kainoa Kanter | 062f0c8b22 | |
Kainoa Kanter | f468e12125 | |
ThatOneCalculator | bfc3825d15 | |
ThatOneCalculator | 397479b13c | |
Kainoa Kanter | 921fc40916 | |
ThatOneCalculator | dbfed7a7dc | |
ThatOneCalculator | 4ed5065bef | |
ThatOneCalculator | 1ffb3abdfd | |
ThatOneCalculator | f35b619619 | |
ThatOneCalculator | cc65f2fe78 | |
ThatOneCalculator | 7505d619ea | |
Kainoa Kanter | fa05a899db | |
Kainoa Kanter | aab7682760 | |
Kainoa Kanter | 0408c5f023 | |
ThatOneCalculator | a90250dcec | |
ThatOneCalculator | 46cb4de1ef | |
Kainoa Kanter | 36d648b8b5 | |
ThatOneCalculator | 94e282b039 | |
ThatOneCalculator | 6235dfa6ab | |
ThatOneCalculator | fd84b62cbd | |
ThatOneCalculator | 619b327ec2 | |
ThatOneCalculator | f77fdbf850 | |
Dominic Harris | 15e376c3d9 | |
Dominic Harris | 50581c022b | |
ThatOneCalculator | 63c20b56bc | |
Kainoa Kanter | 083a2a8de9 | |
Kainoa Kanter | ab0c21fd9f | |
ThatOneCalculator | 9b4eed484a | |
ThatOneCalculator | 5ff0cef35e | |
ThatOneCalculator | dbd5ce3eeb | |
ThatOneCalculator | 2bc96946f5 | |
ThatOneCalculator | 2b69f8a615 | |
ThatOneCalculator | 02ca472369 | |
ThatOneCalculator | fa29569ba1 | |
ThatOneCalculator | 8013d12a21 | |
ThatOneCalculator | 50ecb91151 | |
Kainoa Kanter | 294b50150f | |
Kainoa Kanter | 22639a244d | |
Kainoa Kanter | 597fd3663b | |
Kainoa Kanter | 41e290102c | |
ThatOneCalculator | 973e7a91f6 | |
ThatOneCalculator | e9c4842719 | |
ThatOneCalculator | 5948dcfda5 | |
Kainoa Kanter | e6a4341976 | |
Kainoa Kanter | 5056a83225 | |
ThatOneCalculator | 01cffc24d5 | |
ThatOneCalculator | 21c25dce94 | |
ThatOneCalculator | b1e792472b | |
ThatOneCalculator | e4183c9070 | |
ThatOneCalculator | 331abc7c8d | |
ThatOneCalculator | 0610f5bba2 | |
ThatOneCalculator | 6ec8b47cfb | |
ThatOneCalculator | db834b108f | |
ThatOneCalculator | 08352498c8 | |
ThatOneCalculator | 82cb6ff2e5 | |
ThatOneCalculator | 8621c29c9d | |
ThatOneCalculator | 918068f0be | |
ThatOneCalculator | 4184901345 | |
ThatOneCalculator | 2a8a4c3ac5 | |
ThatOneCalculator | 7f33ae0327 | |
ThatOneCalculator | 2155c90bc4 | |
Kainoa Kanter | 1867dde1f2 | |
Kainoa Kanter | 77eebaa42f | |
Kainoa Kanter | 49aaa073ab | |
ThatOneCalculator | a7b149f26e | |
Dominic Harris | 30a843c390 | |
Kainoa Kanter | 4c618f9486 | |
Kainoa Kanter | b6476606f8 | |
Daniel Mason | ed45574c84 | |
Kainoa Kanter | b99e63b018 | |
Dominic Harris | 7333afcbd6 | |
ThatOneCalculator | bbf6cfeada | |
ThatOneCalculator | 2844749225 | |
ThatOneCalculator | f70de0e290 |
|
@ -12,19 +12,13 @@ Thanks for offering us your public instance!
|
|||
|
||||
## Details
|
||||
|
||||
What country is the server in:
|
||||
|
||||
What server hardware/provider is the server on:
|
||||
|
||||
Are you using CloudFlare or any Google serives (domain, DNS, etc):
|
||||
|
||||
What version of zer0bin is it running:
|
||||
|
||||
Have you made any modifications to zer0bin? If so, what?:
|
||||
|
||||
What are the ratelimits:
|
||||
|
||||
What is the expiration time of pastes:
|
||||
|
||||
What is the max paste size:
|
||||
- Domain name:
|
||||
- What country is the server in:
|
||||
- What server hardware/provider is the server on:
|
||||
- Are you using CloudFlare or any Google services (domain, DNS, etc):
|
||||
- What version of zer0bin is it running:
|
||||
- Have you made any modifications to zer0bin? If so, what?:
|
||||
- What are the ratelimits:
|
||||
- What is the expiration time of pastes:
|
||||
- What is the max paste size:
|
||||
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
- Your code must be formatted with the formatters we use
|
||||
- The frontend must use our `prettier` config
|
||||
- The backend must use `rustfmt`
|
||||
- The frontend must be installed and compiled with `yarn` and `parcel`
|
||||
- The frontend must be installed with `yarn` and compiled with `parcel`
|
||||
- Additional frontend packages must not be considered bloated
|
||||
- All commits must follow [Conventional Commits](https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits)
|
||||
|
|
|
@ -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
|
||||
|
|
126
README.md
126
README.md
|
@ -10,126 +10,68 @@
|
|||
<br>
|
||||
<p align="center">
|
||||
<a href="https://github.com/zer0bin-dev/zer0bin/stargazers">
|
||||
<img alt="Stargazers" src="https://custom-icon-badges.herokuapp.com/github/stars/zer0bin-dev/zer0bin?style=for-the-badge&logo=star&color=f6c177&logoColor=31748f&labelColor=191724"></a>
|
||||
<img alt="Stargazers" src="https://custom-icon-badges.herokuapp.com/github/stars/zer0bin-dev/zer0bin?style=for-the-badge&logo=star&color=f6c177&logoColor=eb6f92&labelColor=191724"></a>
|
||||
<a href="https://github.com/zer0bin-dev/zer0bin/wiki">
|
||||
<img alt="Wiki" src="https://custom-icon-badges.herokuapp.com/badge/read_the-wiki-ebbcba?style=for-the-badge&logo=repo&logoColor=eb6f92&labelColor=191724"></a>
|
||||
<a href="https://github.com/zer0bin-dev/zer0bin/releases/latest">
|
||||
<img alt="Releases" src="https://img.shields.io/github/release/zer0bin-dev/zer0bin?style=for-the-badge&logo=github&color=31748f&logoColor=908caa&labelColor=191724"/></a>
|
||||
<img alt="Releases" src="https://img.shields.io/github/release/zer0bin-dev/zer0bin?style=for-the-badge&logo=github&color=31748f&logoColor=eb6f92&labelColor=191724"/></a>
|
||||
<a href="https://github.com/zer0bin-dev/zer0bin/blob/main/LICENSE">
|
||||
<img alt="License" src="https://custom-icon-badges.herokuapp.com/github/license/zer0bin-dev/zer0bin?style=for-the-badge&logo=law&color=c4a7e7&logoColor=eb6f92&labelColor=191724"></a>
|
||||
<a href="https://github.com/zer0bin-dev/zer0bin/issues">
|
||||
<img alt="Issues" src="https://custom-icon-badges.herokuapp.com/github/issues/zer0bin-dev/zer0bin?style=for-the-badge&logo=issue-opened&color=9ccfd8&logoColor=eb6f92&labelColor=191724"></a>
|
||||
<a href="https://github.com/zer0bin-dev/zer0bin/blob/main/LICENSE">
|
||||
<img alt="License" src="https://custom-icon-badges.herokuapp.com/github/license/zer0bin-dev/zer0bin?style=for-the-badge&logo=law&color=c4a7e7&logoColor=ebbcba&labelColor=191724"></a>
|
||||
</p>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
# Features
|
||||
|
||||
- ✨ Code highlighting and line numbers (default)
|
||||
- 📖 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
|
||||
- <kbd>Ctrl</kbd> + <kbd>M</kbd>: toggle markdown mode
|
||||
- 📱 Mobile-friendly UI
|
||||
- 🧈 Super smooth scrolling
|
||||
- 🖼️ Badge generation for stats (seen below)
|
||||
|
||||
# Public instances
|
||||
|
||||
Submit your public instance [here](https://github.com/Domterion/zer0bin/issues/new?assignees=&labels=&template=03_public_instance.md&title=%F0%9F%9A%80+)!
|
||||
|
||||
| Website | Expiration | Max paste size | Version | Country |
|
||||
| ---------------------------------------------- | ---------- | -------------- | ------- | ------- |
|
||||
| zer0b.in | 7 days | 40,000 chars | v1.0.0 | 🇺🇸 USA |
|
||||
| [stepbro.voring.me](https://stepbro.voring.me) | 365 days | 69,000 chars | v0.7.1 | 🇺🇸 USA |
|
||||
| URL | Expiration | Max paste size | Total Pastes | Version | Country |
|
||||
| ---------------------------------------------- | ---------- | -------------- | -------------------------------------------- | --------------------------------------------- | ------- |
|
||||
| [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://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/953177926688464936/HLJS.svg" height=40/></a> <a href="https://github.com/ant-design/ant-design-icons"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953181625259266059/AntIcons-Dark.svg" height=40/></a> <a href="https://github.com/idiotWu/smooth-scrollbar"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953564432628322364/SmoothScrollJS.svg" height=40/></a><br><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://definitelytyped.org/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953567495321710602/DefinitelyTyped.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:
|
||||
|
||||
<a href="https://www.rust-lang.org/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Rust.svg" height=40/></a> <a href="https://actix.rs/"><img src="https://user-images.githubusercontent.com/44733677/158648238-0586f185-4e0c-43bc-b6a9-effd18b3b1ac.svg" height=40/></a> <a href="https://github.com/serde-rs/serde"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953176309964627978/Serde-Dark.svg" height=40/></a> <a href="https://github.com/launchbadge/sqlx"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953176310354673704/SQLX-Dark.svg" height=40/></a> <a href="https://github.com/chronotope/chrono"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953178919169835018/NPM-svg.png" height=40/></a> <a href="https://www.postgresql.org/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/PostgreSQL-Dark.svg" height=40/></a> <a href="https://github.com/nikolay-govorov/nanoid"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953176309629067354/NanoID-Dark.svg" height=40/></a>
|
||||
<a href="https://www.rust-lang.org/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Rust.svg" height=40/></a> <a href="https://actix.rs/"><img src="https://user-images.githubusercontent.com/44733677/158648238-0586f185-4e0c-43bc-b6a9-effd18b3b1ac.svg" height=40/></a> <a href="https://github.com/serde-rs/serde"><img src="https://cdn.discordapp.com/attachments/810799100940255260/956227498792849418/serde.svg" height=40/></a> <a href="https://github.com/launchbadge/sqlx"><img src="https://cdn.discordapp.com/attachments/810799100940255260/956227498608320562/sqlx.svg" height=40/></a> <a href="https://github.com/chronotope/chrono"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953178919169835018/NPM-svg.png" height=40/></a> <a href="https://www.postgresql.org/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/PostgreSQL-Dark.svg" height=40/></a> <a href="https://github.com/nikolay-govorov/nanoid"><img src="https://cdn.discordapp.com/attachments/810799100940255260/953176309629067354/NanoID-Dark.svg" height=40/></a> <a href="https://github.com/cgburgess/badge-maker"><img src="https://cdn.discordapp.com/attachments/810799100940255260/956244924930617385/RustBadgeMaker.svg" height=40/></a>
|
||||
|
||||
### Misc:
|
||||
|
||||
<a href="https://nginx.com/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Nginx.svg" height=40/></a> <!-- <a href="https://docker.com/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Docker.svg" height=40/></a> --> <a href="https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Markdown-Dark.svg" height=40/></a> <a href="https://git-scm.com/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Git.svg" height=40/></a> <a href="https://www.conventionalcommits.org/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/954930714007191582/ConventionalCommits.svg" height=40/></a>
|
||||
<a href="https://nginx.com/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Nginx.svg" height=40/></a> <!-- <a href="https://docker.com/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Docker.svg" height=40/></a> --> <a href="https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Markdown-Dark.svg" height=40/></a> <a href="https://git-scm.com/"><img src="https://github.com/tandpfun/skill-icons/raw/main/icons/Git.svg" height=40/></a> <a href="https://www.conventionalcommits.org/"><img src="https://cdn.discordapp.com/attachments/810799100940255260/955896756095320074/ConventionalCommits.svg" height=40/></a>
|
||||
|
||||
###### (Sorta) made with [Skill Icons](https://skillicons.dev/)
|
||||
|
||||
# API
|
||||
# More info
|
||||
|
||||
- **GET** `/api/p/:id` - Get a paste by ID
|
||||
- **POST** `/api/p/n` - Post a new paste
|
||||
- **GET** `/api/s` - Get stats about the instance
|
||||
### Looking for API reference, self-hosting instructions, and/or benchmarks?
|
||||
|
||||
# Self-host instructions
|
||||
<a href="https://github.com/zer0bin-dev/zer0bin/wiki">
|
||||
<img alt="Stargazers" src="https://custom-icon-badges.herokuapp.com/badge/read_the-wiki-ebbcba?style=for-the-badge&logo=repo&logoColor=eb6f92&labelColor=191724" height=50></a>
|
||||
|
||||
### Requirements
|
||||
|
||||
- 🦀 [Rust](https://www.rust-lang.org/) ≥ 1.58.0
|
||||
- 🐈 [Yarn](https://yarnpkg.com/) ≥ 1.0.0
|
||||
- 🐘 [PostgreSQL](https://www.postgresql.org/) ≥ 9.6
|
||||
- 🦝 [Nginx](https://www.nginx.com/) ≥ 1.18.0
|
||||
- 🌾 [Brotli plugin](https://github.com/google/ngx_brotli) recommended
|
||||
- 🐧 [Linux](https://kernel.org/) or 😈 [FreeBSD](https://freebsd.org/)
|
||||
- 🌄 Domain with [SSL](https://letsencrypt.org/)
|
||||
|
||||
<details>
|
||||
<summary><h3>Steps</h3></summary>
|
||||
|
||||
Please run each command one at a time!
|
||||
|
||||
```bash
|
||||
# export EDITOR=nano
|
||||
git clone https://github.com/zer0bin-dev/zer0bin && cd zer0bin
|
||||
$EDITOR example.nginx # Edit as appropriate
|
||||
mv example.nginx yourdomain.tld
|
||||
sudo cp ./yourdomain.tld /etc/nginx/sites-available
|
||||
sudo cp ./yourdomain.tld /etc/nginx/sites-enabled
|
||||
systemctl nginx restart # Or whichever process manager you use
|
||||
cd frontend
|
||||
cp config.example.json config.json
|
||||
$EDITOR config.json # Edit as appropriate
|
||||
yarn && yarn build
|
||||
cd ../backend
|
||||
psql -f schema.sql -U postgres zer0bin
|
||||
cp config.example.json config.json
|
||||
$EDITOR config.json # Edit as appropriate
|
||||
cargo build --release
|
||||
./target/release/zer0bin-bin # Preferably in a tmux session or as a service
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><h3>Configuration</h3></summary>
|
||||
|
||||
| Key | Values | Description |
|
||||
| ------------------------------------------ | ------------------------ | ------------------------------------------------------------------------------ |
|
||||
| server.backend_host | 127.0.0.1 or 0.0.0.0 | The host to run the backend on |
|
||||
| server.backend_port | Any open port | The port to run the backend on |
|
||||
| pastes.character_limit | Number up to 2^64 - 1 | The amount of characters allowed in a single paste |
|
||||
| pastes.days_til_expiration | Number up to 2^63 or -1 | The days till a paste is to expire. If set to -1 then pastes will never expire |
|
||||
| pastes.id_length | Number up to 2^64 - 1 | The length of the ID for each paste |
|
||||
| databases.postgres_uri | PostreSQL Connection URI | The URI to use when connecting to a PostgreSQL database |
|
||||
| ratelimits.seconds_in_between_pastes | Number up to 2^64 - 1 | The seconds between paste uploads |
|
||||
| ratelimits.allowed_pastes_before_ratelimit | Number up to 2^32 - 1 | Amount of requests that can be made before they are blocked and have to wait |
|
||||
| logging.on_post_paste | true or false | Log on new paste is made |
|
||||
| logging.on_get_paste | true or false | Log on paste get |
|
||||
|
||||
</details>
|
||||
|
||||
# Benchmarks
|
||||
|
||||
###### Measured with Lighthouse and Firefox Network Performance Analysis
|
||||
|
||||
<details>
|
||||
<summary><h3>Results</h3></summary>
|
||||
|
||||
### Homepage
|
||||
|
||||
![image](https://user-images.githubusercontent.com/44733677/159143364-a6e06aee-256e-4998-83f2-541c77e85184.png)
|
||||
![image](https://user-images.githubusercontent.com/44733677/159143316-c8e95ed6-ec32-44b3-abcc-18bd204a004d.png)
|
||||
![image](https://user-images.githubusercontent.com/44733677/159143321-aa8a5f6f-53d2-40d1-bff9-71d72347e7ea.png)
|
||||
|
||||
### 20 line paste
|
||||
|
||||
![image](https://user-images.githubusercontent.com/44733677/159143373-6e8787d8-61ef-44dc-9d66-52cd74e2a495.png)
|
||||
![image](https://user-images.githubusercontent.com/44733677/159143298-f8c7420d-ff76-4db7-a98e-03ff3615315e.png)
|
||||
![image](https://user-images.githubusercontent.com/44733677/159143303-efb71e15-623a-42cc-abf6-7e602843d801.png)
|
||||
|
||||
</details>
|
||||
|
||||
# Contributing
|
||||
|
||||
See [CONTRIBUTING.md](./CONTRIBUTING.md)
|
||||
|
|
|
@ -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",
|
||||
|
@ -71,7 +70,7 @@ dependencies = [
|
|||
"http",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"itoa 1.0.1",
|
||||
"language-tags",
|
||||
"local-channel",
|
||||
"log",
|
||||
|
@ -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]]
|
||||
|
@ -182,7 +181,7 @@ dependencies = [
|
|||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"itoa",
|
||||
"itoa 1.0.1",
|
||||
"language-tags",
|
||||
"log",
|
||||
"mime",
|
||||
|
@ -194,7 +193,7 @@ dependencies = [
|
|||
"serde_urlencoded",
|
||||
"smallvec",
|
||||
"socket2",
|
||||
"time 0.3.7",
|
||||
"time 0.3.9",
|
||||
"url",
|
||||
]
|
||||
|
||||
|
@ -268,12 +267,13 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
|||
|
||||
[[package]]
|
||||
name = "backend"
|
||||
version = "0.7.0"
|
||||
version = "1.1.1"
|
||||
dependencies = [
|
||||
"actix-cors",
|
||||
"actix-governor",
|
||||
"actix-rt",
|
||||
"actix-web",
|
||||
"badge-maker",
|
||||
"chrono",
|
||||
"nanoid",
|
||||
"serde",
|
||||
|
@ -281,12 +281,37 @@ dependencies = [
|
|||
"sqlx",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "badge-maker"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "383647c1ae7388c2801ef995f6de2f9551a361ad637f2a0e4fea41c51dd37b81"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"bincode",
|
||||
"itoa 0.4.8",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"seahash",
|
||||
"serde",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -313,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",
|
||||
|
@ -384,7 +409,7 @@ dependencies = [
|
|||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"time 0.1.43",
|
||||
"time 0.1.44",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -401,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",
|
||||
]
|
||||
|
@ -440,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",
|
||||
|
@ -450,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",
|
||||
|
@ -480,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",
|
||||
|
@ -532,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",
|
||||
|
@ -714,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]]
|
||||
|
@ -742,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",
|
||||
|
@ -755,7 +780,7 @@ dependencies = [
|
|||
"indexmap",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util 0.6.9",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -819,7 +844,7 @@ checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
|
|||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
"itoa 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -847,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",
|
||||
|
@ -873,6 +898,12 @@ dependencies = [
|
|||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
|
@ -911,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"
|
||||
|
@ -935,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",
|
||||
]
|
||||
|
@ -1007,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",
|
||||
]
|
||||
|
||||
|
@ -1044,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]]
|
||||
|
@ -1099,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"
|
||||
|
@ -1136,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]]
|
||||
|
@ -1155,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",
|
||||
|
@ -1168,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"
|
||||
|
@ -1216,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",
|
||||
]
|
||||
|
@ -1262,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",
|
||||
|
@ -1356,7 +1389,7 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
|||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.7.1"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
|
||||
dependencies = [
|
||||
|
@ -1365,10 +1398,16 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.6"
|
||||
name = "seahash"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d"
|
||||
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
|
@ -1396,7 +1435,7 @@ version = "1.0.79"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"itoa 1.0.1",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
@ -1408,7 +1447,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"itoa",
|
||||
"itoa 1.0.1",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
@ -1461,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"
|
||||
|
@ -1533,7 +1572,7 @@ dependencies = [
|
|||
"hex",
|
||||
"hmac",
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"itoa 1.0.1",
|
||||
"libc",
|
||||
"log",
|
||||
"md-5",
|
||||
|
@ -1607,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",
|
||||
|
@ -1638,21 +1677,22 @@ 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",
|
||||
"itoa 1.0.1",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"time-macros",
|
||||
|
@ -1660,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"
|
||||
|
@ -1722,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",
|
||||
]
|
||||
|
@ -1833,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"
|
||||
|
@ -1954,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",
|
||||
|
@ -1967,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"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "backend"
|
||||
version = "0.7.1"
|
||||
version = "1.1.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
@ -14,7 +14,9 @@ actix-web = "4.0.0-rc.1"
|
|||
actix-cors = "0.6.0"
|
||||
actix-governor = "0.3.0"
|
||||
|
||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "postgres", "chrono"] }
|
||||
badge-maker = "0.2.1"
|
||||
|
||||
sqlx = { version = "0.5.11", features = ["runtime-tokio-rustls", "postgres", "chrono"] }
|
||||
|
||||
chrono = { version = "0.4.19", features = ["serde"] }
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
"backend_port": 8000
|
||||
},
|
||||
"pastes": {
|
||||
"character_limit": 40000,
|
||||
"days_til_expiration": 7,
|
||||
"id_length": 10
|
||||
"character_limit": 50000,
|
||||
"days_til_expiration": 30,
|
||||
"id_length": 6
|
||||
},
|
||||
"ratelimits": {
|
||||
"seconds_in_between_pastes": 2,
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE pastes ADD column single_view BOOLEAN DEFAULT false;
|
|
@ -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, 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
|
||||
|
@ -63,7 +79,12 @@ async fn main() -> io::Result<()> {
|
|||
.wrap(Governor::new(&paste_governor))
|
||||
.service(get_paste)
|
||||
.service(new_paste)
|
||||
// .service(get_raw_paste),
|
||||
.service(get_raw_paste),
|
||||
)
|
||||
.service(
|
||||
web::scope("/b")
|
||||
.service(get_version_badge)
|
||||
.service(get_total_pastes_badge),
|
||||
)
|
||||
})
|
||||
.bind(address)?
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,9 @@ use actix_web::{
|
|||
HttpResponse, Responder,
|
||||
};
|
||||
|
||||
use chrono::Duration;
|
||||
use badge_maker::{BadgeBuilder, Style};
|
||||
|
||||
use chrono::Duration;
|
||||
use nanoid::nanoid;
|
||||
use sqlx::{postgres::PgRow, types::chrono::Utc, Row};
|
||||
|
||||
|
@ -17,35 +18,7 @@ use crate::{
|
|||
AppState,
|
||||
};
|
||||
|
||||
#[get("/s")]
|
||||
pub async fn get_stats(state: web::Data<AppState>) -> impl Responder {
|
||||
let version = env!("CARGO_PKG_VERSION").to_string();
|
||||
// TODO: Maybe there's a less hacky way to do this..?
|
||||
let count: Result<i64, sqlx::Error> = sqlx::query(r#"SELECT COUNT(*) FROM pastes"#)
|
||||
.try_map(|row: PgRow| row.try_get::<i64, _>("count"))
|
||||
.fetch_one(&state.pool)
|
||||
.await;
|
||||
|
||||
if let Err(e) = count {
|
||||
eprintln!("Error occurred while retrieving paste count: {:?}", e);
|
||||
|
||||
return HttpResponse::InternalServerError().json(ApiResponse {
|
||||
success: false,
|
||||
data: ApiError {
|
||||
message: "Error occurred while retrieving paste count, please try again."
|
||||
.to_string(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
HttpResponse::Ok().json(ApiResponse {
|
||||
success: true,
|
||||
data: GetStatsResponse {
|
||||
count: count.unwrap(),
|
||||
version
|
||||
},
|
||||
})
|
||||
}
|
||||
// Pastes
|
||||
|
||||
#[get("/{id}")]
|
||||
pub async fn get_paste(state: web::Data<AppState>, id: web::Path<String>) -> impl Responder {
|
||||
|
@ -59,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 {
|
||||
|
@ -75,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,
|
||||
},
|
||||
})
|
||||
|
@ -102,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();
|
||||
|
@ -115,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 => {
|
||||
|
@ -172,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;
|
||||
|
@ -184,16 +178,17 @@ 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,
|
||||
},
|
||||
})},
|
||||
success: true,
|
||||
data: NewPasteResponse {
|
||||
id,
|
||||
content,
|
||||
single_view,
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error occurred while creating paste: {:?}", e);
|
||||
|
||||
|
@ -206,3 +201,86 @@ pub async fn new_paste(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stats
|
||||
|
||||
#[get("/s")]
|
||||
pub async fn get_stats(state: web::Data<AppState>) -> impl Responder {
|
||||
let version = env!("CARGO_PKG_VERSION").to_string();
|
||||
// TODO: Maybe there's a less hacky way to do this..?
|
||||
let count: Result<i64, sqlx::Error> = sqlx::query(r#"SELECT COUNT(*) FROM pastes"#)
|
||||
.try_map(|row: PgRow| row.try_get::<i64, _>("count"))
|
||||
.fetch_one(&state.pool)
|
||||
.await;
|
||||
|
||||
if let Err(e) = count {
|
||||
eprintln!("Error occurred while retrieving paste count: {:?}", e);
|
||||
|
||||
return HttpResponse::InternalServerError().json(ApiResponse {
|
||||
success: false,
|
||||
data: ApiError {
|
||||
message: "Error occurred while retrieving paste count, please try again."
|
||||
.to_string(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
HttpResponse::Ok().json(ApiResponse {
|
||||
success: true,
|
||||
data: GetStatsResponse {
|
||||
count: count.unwrap(),
|
||||
version,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Badges
|
||||
|
||||
#[get("/v")]
|
||||
pub async fn get_version_badge() -> impl Responder {
|
||||
let version = env!("CARGO_PKG_VERSION").to_string();
|
||||
|
||||
let badge = BadgeBuilder::new()
|
||||
.label("version")
|
||||
.message(&version)
|
||||
.color_parse("#31748f")
|
||||
.label_color_parse("#191724")
|
||||
.style(Style::FlatSquare)
|
||||
.build()
|
||||
.expect("Failed to build badge")
|
||||
.svg();
|
||||
|
||||
HttpResponse::Ok().content_type("image/svg+xml").body(badge)
|
||||
}
|
||||
|
||||
#[get("/t")]
|
||||
pub async fn get_total_pastes_badge(state: web::Data<AppState>) -> impl Responder {
|
||||
let count: Result<i64, sqlx::Error> = sqlx::query(r#"SELECT COUNT(*) FROM pastes"#)
|
||||
.try_map(|row: PgRow| row.try_get::<i64, _>("count"))
|
||||
.fetch_one(&state.pool)
|
||||
.await;
|
||||
|
||||
if let Err(e) = count {
|
||||
eprintln!("Error occurred while retrieving paste count: {:?}", e);
|
||||
|
||||
return HttpResponse::InternalServerError().json(ApiResponse {
|
||||
success: false,
|
||||
data: ApiError {
|
||||
message: "Error occurred while retrieving paste count, please try again."
|
||||
.to_string(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
let badge = BadgeBuilder::new()
|
||||
.label("total pastes")
|
||||
.message(&count.unwrap().to_string())
|
||||
.color_parse("#ebbcba")
|
||||
.label_color_parse("#191724")
|
||||
.style(Style::FlatSquare)
|
||||
.build()
|
||||
.expect("Failed to build badge")
|
||||
.svg();
|
||||
|
||||
HttpResponse::Ok().content_type("image/svg+xml").body(badge)
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
# replace `example.tld` with your domain
|
||||
# replace `/location/of/zer0bin` with the location of the zer0bin folder
|
||||
# uncomment the `brotli on;` lines if you have the nginx brotoli plugin
|
||||
# uncomment the `ssl_certificate` lines if you have letsencrypt certs
|
||||
# comment out line 15 and uncomment line 16 if you have the nginx brotoli plugin
|
||||
# uncomment lines 51 and 52 if you have letsencrypt certs
|
||||
|
||||
server {
|
||||
#listen 80 is default
|
||||
server_name www.example.tld;
|
||||
server_name example.tld;
|
||||
return 301 https://example.tld$request_uri;
|
||||
# brotli on;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443;
|
||||
server_name example.tld;
|
||||
|
||||
gzip_static on;
|
||||
# brotli on;
|
||||
|
||||
root /location/of/zer0bin/frontend/dist;
|
||||
|
@ -21,10 +21,14 @@ server {
|
|||
|
||||
location / {
|
||||
index index.html;
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, no-transform";
|
||||
}
|
||||
|
||||
location ~ \.(css|js|html) {
|
||||
try_files $uri =404;
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, no-transform";
|
||||
}
|
||||
|
||||
location ^~ /.well-known/ {
|
||||
|
@ -37,11 +41,13 @@ server {
|
|||
proxy_pass http://localhost:8000/;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $host;
|
||||
add_header Last-Modified $date_gmt;
|
||||
add_header Cache-Control 'no-store, no-cache';
|
||||
if_modified_since off;
|
||||
expires off;
|
||||
etag off;
|
||||
}
|
||||
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, no-transform";
|
||||
|
||||
# ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem;
|
||||
# ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem;
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"extends": "@parcel/config-default",
|
||||
"compressors": {
|
||||
"*.{html,css,js,svg,map}": [
|
||||
"...",
|
||||
"@parcel/compressor-gzip",
|
||||
"@parcel/compressor-brotli"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
{
|
||||
"api_url": "https://example.tld/api"
|
||||
"api_url": "https://yourdomain.tld/api",
|
||||
"confetti_chance": "10"
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
|
@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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>
|
|
@ -1,40 +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')
|
||||
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:
|
||||
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:
|
||||
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')
|
|
@ -1,31 +1,32 @@
|
|||
{
|
||||
"name": "zer0bin",
|
||||
"source": "index.pug",
|
||||
"version": "0.7.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"
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@parcel/compressor-brotli": "^2.3.2",
|
||||
"@parcel/compressor-gzip": "^2.3.2",
|
||||
"@parcel/config-default": "^2.3.2",
|
||||
"@parcel/transformer-pug": "2.3.2",
|
||||
"@parcel/transformer-sass": "^2.3.2",
|
||||
"@types/core-js": "^2.5.5",
|
||||
"@types/node": "^17.0.21",
|
||||
"parcel": "^2.3.2"
|
||||
"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/Domterion/zer0bin",
|
||||
"repository": "https://github.com/zer0bin-dev/zer0bin",
|
||||
"author": "Domterion, ThatOneCalculator",
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^4.7.0",
|
||||
"@ant-design/icons-svg": "^4.2.1",
|
||||
"highlight.js": "^11.4.0",
|
||||
"highlight.js": "^11.5.0",
|
||||
"js-confetti": "^0.10.2",
|
||||
"marked": "^4.0.12",
|
||||
"no-darkreader": "^1.0.1",
|
||||
"smooth-scrollbar": "^8.7.4",
|
||||
"tippy.js": "^6.3.7"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
declare const API_URL: string
|
||||
declare const CONFETTI_CHANCE: string
|
|
@ -6,38 +6,72 @@ 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>",
|
||||
placement: "bottom",
|
||||
animation: "scale",
|
||||
theme: "rosepine",
|
||||
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,
|
||||
|
@ -45,6 +79,7 @@ tippy("#save-button", {
|
|||
|
||||
tippy("#new-button", {
|
||||
content: "New paste<br><span class='keybind'>Ctrl + N</span>",
|
||||
placement: "bottom",
|
||||
animation: "scale",
|
||||
theme: "rosepine",
|
||||
allowHTML: true,
|
||||
|
@ -52,6 +87,15 @@ tippy("#new-button", {
|
|||
|
||||
tippy("#copy-button", {
|
||||
content: "Duplicate paste<br><span class='keybind'>Ctrl + D</span>",
|
||||
placement: "bottom",
|
||||
animation: "scale",
|
||||
theme: "rosepine",
|
||||
allowHTML: true,
|
||||
})
|
||||
|
||||
tippy("#share-button", {
|
||||
content: `Share paste<br><span class='keybind'>Copies URL</span>`,
|
||||
placement: "top",
|
||||
animation: "scale",
|
||||
theme: "rosepine",
|
||||
allowHTML: true,
|
||||
|
@ -66,7 +110,52 @@ tippy("#github-button", {
|
|||
})} ${renderIconDefinitionToSVGElement(HeartOutlined, {
|
||||
extraSVGAttrs: extraSVGAttrs,
|
||||
})}</span>`,
|
||||
placement: "bottom",
|
||||
animation: "scale",
|
||||
theme: "rosepine",
|
||||
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() {
|
||||
let theme = ""
|
||||
|
||||
if (window.location.pathname == "/") {
|
||||
theme = "rosepine"
|
||||
} else {
|
||||
theme = "rosepine-extended"
|
||||
}
|
||||
|
||||
document.querySelectorAll("button").forEach(function (btn) {
|
||||
//@ts-ignore
|
||||
btn._tippy.setProps({ theme: theme })
|
||||
})
|
||||
}
|
||||
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,26 @@
|
|||
import hljs from "highlight.js"
|
||||
import "no-darkreader"
|
||||
|
||||
import { marked } from "marked"
|
||||
import JSConfetti from "js-confetti"
|
||||
import Scrollbar from "smooth-scrollbar"
|
||||
|
||||
import config from "../config.json"
|
||||
const apiUrl = config.api_url
|
||||
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")
|
||||
|
@ -23,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) {
|
||||
|
@ -41,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",
|
||||
|
@ -66,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",
|
||||
|
@ -96,6 +117,8 @@ function newPaste() {
|
|||
enable(saveButton)
|
||||
disable(newButton)
|
||||
disable(copyButton)
|
||||
disable(shareButton)
|
||||
enable(singleViewButton)
|
||||
|
||||
editor.value = ""
|
||||
rawContent = ""
|
||||
|
@ -106,6 +129,8 @@ function newPaste() {
|
|||
hide(codeViewPre)
|
||||
hide(viewCounterLabel)
|
||||
hide(viewCounter)
|
||||
viewCounterLabel.style.display = "none"
|
||||
viewCounter.style.display = "none"
|
||||
}
|
||||
|
||||
function addMessage(message: string) {
|
||||
|
@ -121,21 +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")
|
||||
) {
|
||||
codeView.innerHTML = marked.parse(content.substring(3))
|
||||
} else {
|
||||
for (let i = 1; i <= content.split("\n").length; i++) {
|
||||
lineNumbers.innerHTML = lineNumbers.innerHTML + `${i}<br>`
|
||||
}
|
||||
codeView.innerHTML = hljs.highlightAuto(content).value
|
||||
}
|
||||
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
|
||||
|
||||
|
@ -159,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() * 40)
|
||||
const rand = Math.floor(
|
||||
Math.random() * parseInt(CONFETTI_CHANCE ?? "10") * 6
|
||||
)
|
||||
|
||||
if (rand < 5) {
|
||||
jsConfetti.addConfetti({
|
||||
|
@ -188,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 () {
|
||||
|
@ -209,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
|
||||
|
@ -249,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
|
||||
|
||||
|
@ -264,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"]
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -1,17 +1,13 @@
|
|||
@font-face {
|
||||
font-family: "Cartograph CF";
|
||||
src: url("../fonts/CartographCF-Regular.woff2") format("woff2"),
|
||||
url("../fonts/CartographCF-Regular.woff") format("woff"),
|
||||
url("../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: url("../fonts/CartographCF-RegularItalic.woff2") format("woff2"),
|
||||
url("../fonts/CartographCF-RegularItalic.woff") format("woff"),
|
||||
url("../fonts/CartographCF-RegularItalic.ttf") format("truetype");
|
||||
src: url("../fonts/CartographCF-RegularItalic.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,20 +1,30 @@
|
|||
$color_1: #e0def4;
|
||||
$text: #e0def4;
|
||||
$bg: #26233a;
|
||||
$font-mono: "Cartograph CF", ui-monospace, SFMono-Regular, Menlo, Monaco,
|
||||
Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
$bg: #26233a;
|
||||
|
||||
@import "./font.scss";
|
||||
.tippy-box[data-theme~="rosepine"] {
|
||||
color: $color_1;
|
||||
|
||||
.rosepine-parent {
|
||||
color: $text;
|
||||
background-color: $bg;
|
||||
opacity: 0.8;
|
||||
margin-top: 30px;
|
||||
padding: 10px;
|
||||
font-family: $font-mono;
|
||||
font-size: 13px;
|
||||
border-radius: 10px;
|
||||
> .tippy-backdrop {
|
||||
background-color: $bg;
|
||||
}
|
||||
> .tippy-svg-arrow {
|
||||
fill: #26233a;
|
||||
fill: $bg;
|
||||
}
|
||||
}
|
||||
.tippy-box[data-theme~="rosepine"] {
|
||||
@extend .rosepine-parent;
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
.tippy-box[data-theme~="rosepine-extended"] {
|
||||
@extend .rosepine-parent;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
}
|
||||
})
|
2424
frontend/yarn.lock
2424
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue