├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── documentation.md │ ├── feature_request.md │ └── question.md └── workflows │ ├── cargo_publish.yml │ └── rust.yml ├── .gitignore ├── CHANGELOG.MD ├── Cargo.toml ├── LICENSE ├── README.MD ├── examples ├── data.rs ├── paste.rs ├── time.rs └── user.rs ├── images └── RustMyst.png └── src ├── data.rs ├── discord.rs ├── lib.rs ├── paste.rs ├── time.rs └── user.rs /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG] " 5 | labels: bug 6 | assignees: ANF-Studios 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | 12 | 13 | **To Reproduce** 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | 22 | 23 | **Screenshots** 24 | 25 | 26 | **Additional context** 27 | 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Documentation 3 | about: Something the docs have missing or could be improved 4 | title: "[DOCUMENTATION]" 5 | labels: documentation 6 | assignees: ANF-Studios 7 | 8 | --- 9 | 10 | **What's wrong?** 11 | 12 | 13 | **Proposed solution** 14 | 15 | 16 | **Additional context** 17 | 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE] " 5 | labels: enhancement 6 | assignees: ANF-Studios 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | 12 | 13 | **Describe the solution you'd like** 14 | 15 | 16 | **Describe alternatives you've considered** 17 | 18 | 19 | **Additional context** 20 | 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: A question for the maintainers 4 | title: "[QUESTION] " 5 | labels: question 6 | assignees: ANF-Studios 7 | 8 | --- 9 | 10 | **What's the question?** 11 | 12 | 13 | **Additional context** 14 | 15 | -------------------------------------------------------------------------------- /.github/workflows/cargo_publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish on Cargo 2 | 3 | 4 | on: 5 | workflow_dispatch: 6 | 7 | env: 8 | CARGO_TERM_COLOR: always 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: windows-latest 14 | 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v2 18 | - name: Build 19 | run: cargo build --verbose 20 | - name: Publish 21 | run: cargo publish --token ${{ secrets.CARGO_TOKEN }} --verbose --release --all-features 22 | 23 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ main, dev ] 6 | pull_request: 7 | branches: [ main, dev ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: windows-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Build 20 | run: cargo build --verbose 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | # VS Code's workspace file 13 | *.code-workspace 14 | -------------------------------------------------------------------------------- /CHANGELOG.MD: -------------------------------------------------------------------------------- 1 | # PasteMyst.RS' Changelog 2 | 3 | ### [v0.1.0](https://github.com/ANF/pastemyst-rs/releases/tag/0.1.0) 4 | * Ability to get pastes w/ async support. 5 | * Ability to get private pastes w/ async support. 6 | 7 | ### [v0.2.25](https://github.com/ANF/pastemyst-rs/releases/tag/0.2.25) 8 | * Ability to create pastes. 9 | * Ability to create pastes async. 10 | * Minor bug fixes and value changes. 11 | * Improvements and major additions to the documentation. 12 | 13 | ### [v0.7.75](https://github.com/ANF/pastemyst-rs/releases/tag/0.7.75) 14 | * Ability to create private pastes. 15 | * Ability to create private pastes async. 16 | * Fixed `create_paste` and `create_paste_async`'s return type. 17 | * Improved documentation. 18 | * Fixed some incorrect sentences and spellings in docs. 19 | * Added missing docs. 20 | * Fixed incorrect examples in docs. 21 | * Ability to edit pastes. (not fully done) 22 | * Renamed some modules. 23 | * Ability to delete pastes. 24 | * Added list of constants that have pastemyst's supported languages. 25 | * Ability to check if user exists 26 | * Ability to get users 27 | 28 | ### [0.8.0](https://github.com/ANF/pastemyst-rs/releases/tag/0.8.0) 29 | * Completed user module. 30 | * Completed paste module. 31 | * Added examples. 32 | * Added macro. 33 | * PastyObject no longer has the optional fields 34 | 35 | ### [1.0.0](https://github.com/ANF/pastemyst-rs/releases/tag/1.0.0) 36 | * Minor bug fixes. 37 | * Documentation improvements. 38 | * Added more fields in UserObject. 39 | * Fixed a bug where if a user does not exist, crate panics, now it returns an empty struct. 40 | * Added time module and time operations - completed fully. 41 | * Moved language module into data. 42 | * Added option to get a language by name. 43 | * Added option to get a language by extension. 44 | * Completed data module. 45 | * Bumped library to version 1. 46 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pastemyst" 3 | version = "1.0.0" 4 | authors = ["ANF-Studios "] 5 | edition = "2018" 6 | license = "MIT" 7 | keywords = ["pastemyst", "pastemyst-rs", "pastemystrs", "api-wrapper"] 8 | description = "An API wrapper for pastemyst written in Rust" 9 | repository = "https://github.com/ANF/pastemyst-rs" 10 | readme = "README.MD" 11 | 12 | exclude = [ 13 | "examples/*", 14 | ] 15 | 16 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 17 | 18 | [dependencies] 19 | reqwest = { version = "0.11.0", features = [ "blocking", "json" ] } 20 | tokio = { version = "1.0.1", features = ["macros"] } 21 | serde = { version = "1.0.118", features = ["derive"] } 22 | serde_json = { version = "1.0.61" } 23 | 24 | [features] 25 | discord = [] # You can add the dependency 26 | # name inside the curly-brackets 27 | # and mark it as optional 28 | #default = ["paste", "user", "data", "time"] 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 ANF-Studios 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 |

2 |
4 | PasteMyst.RS 5 |

6 |

pastemyst-rs is an api wrapper for pastemyst written in Rust.

7 |

⚠ This package is under development ⚠

8 | 9 | 10 | ### Sample usage 11 | 12 | To get a paste from pastemyst synchronously: 13 | ```rust 14 | use pastemyst::paste; 15 | use pastemyst::paste::PasteObject; 16 | 17 | fn main() -> Result<(), Box> { 18 | let paste: PasteObject = paste::get_paste("hipfqanx")?; 19 | println!("{}", paste.pasties[1].language); 20 | Ok(()) 21 | } 22 | ``` 23 | 24 | To create paste synchronously: 25 | ```rust 26 | use pastemyst::paste; 27 | use pastemyst::paste::PasteObject; 28 | 29 | fn main() -> Result<(), Box> { 30 | let pasties: Vec = vec![ 31 | PastyObject { 32 | _id: str!(""), 33 | language: str!(pastemyst::data::language::RUST), 34 | title: "A pasty title".to_string(), 35 | code: String::from("fn main() { println!(\"Hello World!\"); }"), 36 | }, 37 | PastyObject { 38 | _id: str!(""), 39 | title: "Another pasty title".to_string(), 40 | language: str!(pastemyst::data::language::CLANG), 41 | code: String::from("#include \"stdio.h\"\n\nint main() {\n\tprintf(\"Hello World!\");\n}"), 42 | }, 43 | ]; 44 | let data: CreateObject = CreateObject { 45 | title: String::from("[crates.io/crates/pastemyst] This is a title"), 46 | expiresIn: String::from("1d"), 47 | isPrivate: false, 48 | isPublic: false, 49 | tags: String::from(""), 50 | pasties: pasties, 51 | }; 52 | let paste /*: reqwest::Response*/ = paste::create_paste(data).unwrap(); // You don't need to add the commented part, that's jut for your information. 53 | println!("{}", paste._id); 54 | Ok(()) 55 | } 56 | ``` 57 | 58 | More from the [examples](./examples/) and [documentation](https://docs.rs/pastemyst/). 59 | 60 | ### Feature support 61 | | Feature | Support | Async | 62 | | :---------------------------------- | :-------: | -----: | 63 | | API v1 | ✔ | ⛔ | 64 | | API v2 | ✔ | ⛔ | 65 | | Get pastes | ✔ | ✔ | 66 | | Get private pastes | ✔ | ✔ | 67 | | Create pastes | ✔ | ✔ | 68 | | Create Private pastes* | ✔ | ✔ | 69 | | Edit pastes | ✔ | ✔ | 70 | | Delete pastes | ✔ | ✔ | 71 | | Get Users | ✔ | ✔ | 72 | | Check if a user exists | ✔ | ✔ | 73 | | Get a language by name | ✔ | ✔ | 74 | | Get a language by extension | ✔ | ✔ | 75 | | Time expires in to a unix timestamp | ✔ | ✔ | 76 | 77 | ✔ = Done/Implemented and fully functional 78 | 79 | ❌ = Not done/implemented 80 | 81 | ⛔ = N/A 82 | 83 | *This also includes a paste to be tied to your account, or create a private/public paste, or with tags. 84 | 85 | 86 | ### Repository structure 87 | This is the current structure of the code: 88 | ``` 89 | ./ 90 | ├───.github/ 91 | │ ├─.workflows/ 92 | │ │ └─ rust.yml 93 | │ └─ISSUE_TEMPLATES/ 94 | │ ├─ bug_report.md 95 | │ ├─ feature_request.md 96 | │ ├─ documentation.md 97 | │ └─ question.md 98 | ├───examples/ 99 | │ ├─ paste.rs 100 | │ ├─ time.rs 101 | │ ├─ data.rs 102 | │ └─ user.rs 103 | ├───images/ 104 | │ └─ RustMyst.png 105 | ├───src/ 106 | │ ├─ data.rs 107 | │ ├─ discord.rs 108 | │ ├─ lib.rs 109 | │ ├─ paste.rs 110 | │ ├─ time.rs 111 | │ └─ user.rs 112 | ├─── .gitattributes 113 | ├─── .gitignore 114 | ├─── Cargo.toml 115 | ├─── CHANGELOG.MD 116 | ├─── LICENSE 117 | └─── README.MD 118 | ``` 119 | 120 | ### Building and Running 121 | Being a Rust library, pastemyst-rs requires the Rust compiler installed. To check if it's installed, run: `rustc --version` and `cargo --version` to verify it. If it's not installed, install it from their [site](https://rust-lang.org). Once that's cleared out; run `cargo install` to get the packages. To test it on-hand, either 122 | 1. Create a main.rs with the main method and run those tests (`cargo run`). 123 | 2. Run from the examples using `cargo run --example example_name`, for example `cargo run --example get_paste`. 124 | 125 | #### Installation 126 | If you want to use it in your rust application, it is recommended to get the crate from https://crates.io/crates/pastemyst. 127 | In your `Cargo.toml` file, under `[dependencies]` paste this: 128 | ```toml 129 | pastemyst = "" 130 | # OR 131 | pastemyst = { version = "" } 132 | ``` 133 | 134 | ### Versioning 135 | pastemyst-rs uses [SemVer](https://semver.org/). 136 | > Given a version number MAJOR.MINOR.PATCH, increment the 137 | > 138 | > `MAJOR` version when you make incompatible API changes, 139 | > 140 | > `MINOR` version when you add functionality in a backwards compatible manner, and 141 | > 142 | > `PATCH` version when you make backwards compatible bug fixes. 143 | > 144 | > Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format. 145 | 146 | ### Help/Assistance 147 | You can [create an issue](https://github.com/ANF-Studios/BotANF/issues/new) or just join the support (discord) server. 148 | 149 | 150 | Discuss in the server 153 | -------------------------------------------------------------------------------- /examples/data.rs: -------------------------------------------------------------------------------- 1 | use pastemyst::data::*; 2 | 3 | #[tokio::main] 4 | async fn main() -> DataResult<()> { 5 | // Get language by name. 6 | tokio::task::spawn_blocking(||call_get_language_by_name().unwrap()); 7 | call_get_language_by_name_async().await?; 8 | 9 | // Get language by extension. 10 | tokio::task::spawn_blocking(||call_get_language_by_extension().unwrap()); 11 | call_get_language_by_extension_async().await?; 12 | Ok(()) 13 | } 14 | 15 | fn call_get_language_by_name() -> DataResult<()> { 16 | let language: DataObject = get_language_by_name(language::CSHARP)?; 17 | println!("{:?}", language.mimes[0]); 18 | Ok(()) 19 | } 20 | 21 | async fn call_get_language_by_name_async() -> DataResult<()> { 22 | let language: DataObject = get_language_by_name_async(language::JAVASCRIPT).await?; 23 | println!("{:?}", language.mode); 24 | Ok(()) 25 | } 26 | 27 | fn call_get_language_by_extension() -> DataResult<()> { 28 | let language: DataObject = get_language_by_extension("c")?; 29 | println!("{:?}", language.mimes[0]); 30 | Ok(()) 31 | } 32 | 33 | async fn call_get_language_by_extension_async() -> DataResult<()> { 34 | let language: DataObject = get_language_by_extension_async("d").await?; 35 | println!("{:?}", language.mode); 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /examples/paste.rs: -------------------------------------------------------------------------------- 1 | use pastemyst::str; 2 | use pastemyst::paste::*; 3 | 4 | type Error = Box; 5 | type Result = std::result::Result; 6 | 7 | #[tokio::main] 8 | async fn main() -> Result<()> { 9 | // Create pastes 10 | tokio::task::spawn_blocking(||call_create_paste().unwrap()); 11 | call_create_paste_async().await?; 12 | // tokio::task::spawn_blocking( 13 | // ||call_create_private_paste( 14 | // "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings").unwrap()); 15 | // call_create_private_paste_async( 16 | // "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings").await?; 17 | 18 | // Get pastes 19 | tokio::task::spawn_blocking(||call_get_paste().unwrap()); 20 | call_get_paste_async().await?; 21 | // tokio::task::spawn_blocking( 22 | // ||call_get_private_paste( 23 | // "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings").unwrap()); 24 | // call_get_private_paste_async( 25 | // "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings").await?; 26 | Ok(()) 27 | } 28 | 29 | /// Creates a paste synchronously. 30 | fn call_create_paste() -> Result<(), reqwest::Error> /*PasteResult<()>*/ { 31 | let pasties: Vec = vec![ 32 | PastyObject { 33 | _id: str!(""), 34 | language: str!(pastemyst::data::language::RUST), 35 | title: "A pasty title".to_string(), 36 | code: String::from("fn main() { println!(\"Hello World!\"); }"), 37 | }, 38 | PastyObject { 39 | _id: str!(""), 40 | title: "Another pasty title".to_string(), 41 | language: str!(pastemyst::data::language::CLANG), 42 | code: String::from("#include \"stdio.h\"\n\nint main() {\n\tprintf(\"Hello World!\");\n}"), 43 | }, 44 | ]; 45 | let data: CreateObject = CreateObject { 46 | title: String::from("[crates.io/crates/pastemyst] This is a title"), 47 | expiresIn: String::from("1d"), 48 | isPrivate: false, 49 | isPublic: false, 50 | tags: String::from(""), 51 | pasties: pasties, 52 | }; 53 | let paste = create_paste(data)?; 54 | println!("https://paste.myst.rs/{}", paste._id); 55 | Ok(()) 56 | } 57 | 58 | // Creates a paste asynchronously 59 | async fn call_create_paste_async() -> Result<()> { 60 | let pasties: Vec = vec![ 61 | PastyObject { 62 | _id: str!(""), 63 | language: str!(pastemyst::data::language::RUST), 64 | title: "A pasty title".to_string(), 65 | code: String::from("fn main() { println!(\"Hello World!\"); }"), 66 | }, 67 | PastyObject { 68 | _id: str!(""), 69 | title: "Another pasty title".to_string(), 70 | language: str!(pastemyst::data::language::CLANG), 71 | code: String::from("#include \"stdio.h\"\n\nint main() {\n\tprintf(\"Hello World!\");\n}"), 72 | }, 73 | ]; 74 | let data: CreateObject = CreateObject { 75 | title: String::from("[crates.io/crates/pastemyst] This is a title"), 76 | expiresIn: String::from("1d"), 77 | isPrivate: false, 78 | isPublic: false, 79 | tags: String::from(""), 80 | pasties, 81 | }; 82 | let paste = create_paste_async(data).await?; 83 | println!("https://paste.myst.rs/{}", paste._id); 84 | Ok(()) 85 | } 86 | 87 | /// Creates a private/owned paste synchronously. 88 | #[allow(dead_code)] 89 | fn call_create_private_paste(auth_token: &str) -> PasteResult<()> { 90 | let pasties: Vec = vec![ 91 | PastyObject { 92 | _id: str!(""), 93 | language: str!(pastemyst::data::language::RUST), 94 | title: "A pasty title".to_string(), 95 | code: String::from("fn main() { println!(\"Hello World!\"); }"), 96 | }, 97 | PastyObject { 98 | _id: str!(""), 99 | title: "Another pasty title".to_string(), 100 | language: str!(pastemyst::data::language::CLANG), 101 | code: String::from("#include \"stdio.h\"\n\nint main() {\n\tprintf(\"Hello World!\");\n}"), 102 | }, 103 | ]; 104 | let data: CreateObject = CreateObject { 105 | title: String::from("[crates.io/crates/pastemyst] This is a title"), 106 | expiresIn: String::from("1d"), 107 | isPrivate: false, 108 | isPublic: false, 109 | tags: String::from(""), 110 | pasties, 111 | }; 112 | let paste = create_private_paste( 113 | data, 114 | auth_token, 115 | )?; 116 | println!("https://paste.myst.rs/{}", paste._id); 117 | Ok(()) 118 | } 119 | 120 | /// Creates a private/owned paste asynchronously. 121 | #[allow(dead_code)] 122 | async fn call_create_private_paste_async(auth_token: &str) -> PasteResult<()> { 123 | let pasties: Vec = vec![ 124 | PastyObject { 125 | _id: str!(""), 126 | language: str!(pastemyst::data::language::RUST), 127 | title: "A pasty title".to_string(), 128 | code: String::from("fn main() { println!(\"Hello World!\"); }"), 129 | }, 130 | PastyObject { 131 | _id: str!(""), 132 | title: "Another pasty title".to_string(), 133 | language: str!(pastemyst::data::language::CLANG), 134 | code: String::from("#include \"stdio.h\"\n\nint main() {\n\tprintf(\"Hello World!\");\n}"), 135 | }, 136 | ]; 137 | let data: CreateObject = CreateObject { 138 | title: String::from("[crates.io/crates/pastemyst] This is a title"), 139 | expiresIn: String::from("1d"), 140 | isPrivate: false, 141 | isPublic: false, 142 | tags: String::from(""), 143 | pasties, 144 | }; 145 | let paste = create_private_paste( 146 | data, 147 | auth_token, 148 | )?; 149 | println!("https://paste.myst.rs/{}", paste._id); 150 | Ok(()) 151 | } 152 | 153 | /// Gets a paste from pastemyst synchronously. 154 | fn call_get_paste() -> PasteResult<()> { 155 | let paste: PasteObject = get_paste("hipfqanx")?; 156 | println!("{:#?}", paste.pasties[1].language); 157 | Ok(()) 158 | } 159 | 160 | /// Gets a paste from pastemyst asynchronously. 161 | async fn call_get_paste_async() -> PasteResult<()> { 162 | let paste: PasteObject = get_paste_async("hipfqanx").await?; 163 | println!("{:#?}", paste.pasties[0].language); 164 | Ok(()) 165 | } 166 | 167 | // You can use either the library's provided type or reqwest's 168 | // error and result (which requires it to be installed), 169 | // however, it is recommened to use the former. 170 | 171 | /// Gets a private paste from pastemyst synchronously. 172 | #[allow(dead_code)] 173 | fn call_get_private_paste() -> PasteResult<()> { 174 | let paste: PasteObject = get_private_paste( 175 | "pasteID", 176 | "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings")?; 177 | println!("{}", paste.ownerId); 178 | Ok(()) 179 | } 180 | 181 | /// Gets a private paste from pastemyst asynchronously. 182 | #[allow(dead_code)] 183 | async fn call_get_private_paste_async(auth_token: &str) -> PasteResult<()> { 184 | let paste: PasteObject = get_private_paste_async( 185 | "pasteID", 186 | auth_token, 187 | ) 188 | .await?; 189 | println!("{}", paste.isPrivate); 190 | Ok(()) 191 | } 192 | -------------------------------------------------------------------------------- /examples/time.rs: -------------------------------------------------------------------------------- 1 | use pastemyst::time::*; 2 | 3 | #[tokio::main] 4 | async fn main() -> TimeResult<()> { 5 | tokio::task::spawn_blocking(||call_expires_into_unix().unwrap()); 6 | call_expires_into_unix_async().await?; 7 | Ok(()) 8 | } 9 | 10 | fn call_expires_into_unix() -> TimeResult<()> { 11 | let unix_time: u64 = expires_into_unix(42, expires_in::ONE_DAY)?; 12 | println!("{}", unix_time.to_string()); 13 | Ok(()) 14 | } 15 | 16 | async fn call_expires_into_unix_async() -> TimeResult<()> { 17 | let unix_time: u64 = expires_into_unix_async(1337, expires_in::TWO_DAYS).await?; 18 | println!("{}", unix_time.to_string()); 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /examples/user.rs: -------------------------------------------------------------------------------- 1 | use pastemyst::user::*; 2 | 3 | #[tokio::main] 4 | async fn main() -> UserResult<()> { 5 | // Get a user. 6 | tokio::task::spawn_blocking(||call_get_user().unwrap()); 7 | call_get_user_async().await?; 8 | 9 | // Check if a user exists. 10 | tokio::task::spawn_blocking(||call_user_exists().unwrap()); 11 | call_user_exists_async().await?; 12 | Ok(()) 13 | } 14 | 15 | fn call_user_exists() -> UserResult<()> { 16 | const USERNAME: &str = "ANF-Studios"; 17 | let exists: bool = user_exists(USERNAME)?; 18 | println!("The user '{}' exists: {}", USERNAME, exists); 19 | Ok(()) 20 | } 21 | 22 | async fn call_user_exists_async() -> UserResult<()> { 23 | const USERNAME: &str = "ANF-Studios"; 24 | let exists: bool = user_exists_async(USERNAME).await?; 25 | println!("The user '{}' exists: {}", USERNAME, exists); 26 | Ok(()) 27 | } 28 | 29 | fn call_get_user() -> UserResult<()> { 30 | const USERNAME: &str = "ANF-Studios"; 31 | let user = get_user(USERNAME)?; 32 | println!("{}", user.publicProfile); 33 | Ok(()) 34 | } 35 | 36 | async fn call_get_user_async() -> UserResult<()> { 37 | const USERNAME: &str = "ANF-Studios"; 38 | let user = get_user_async(USERNAME).await?; 39 | println!("{}", user.publicProfile); 40 | Ok(()) 41 | } 42 | -------------------------------------------------------------------------------- /images/RustMyst.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ANF/pastemyst-rs/2c9430306cecf2850e9b77fa6171cb2f819640ee/images/RustMyst.png -------------------------------------------------------------------------------- /src/data.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | 3 | pub type DataResult = Result; 4 | 5 | const DATA_ENDPOINT: &str = "https://paste.myst.rs/api/v2/data/"; 6 | 7 | /// Get information on a specific language *supported by PasteMyst*. 8 | /// You are recommened to only use the language names provided within 9 | /// `pastemyst::data::language` to prevent panicking. This method is 10 | /// synchronous. 11 | /// 12 | /// This method does and will panic if a language is not found. The 13 | /// simplest solution to this is to use the language name you know - as 14 | /// mentioned earlier, it is recommended to use that specific module. 15 | /// 16 | /// Some fields, namely `color and `ext` may not be provided and will 17 | /// have the value of `None`. This is because they are not provided 18 | /// by PasteMyst which means that they do not exist or specified anywhere. 19 | /// 20 | /// ## Examples 21 | /// ```rust 22 | /// use pastemyst::data::*; 23 | /// 24 | /// fn main() -> DataResult<()> { 25 | /// let language: DataObject = get_language_by_name(language::DLANG)?; 26 | /// println!("{:?}", language.color); 27 | /// Ok(()) 28 | /// } 29 | /// ``` 30 | pub fn get_language_by_name(language_name: &str) -> DataResult { 31 | Ok(reqwest::blocking::get(&parse_url(language_name, "name"))?.json()?) 32 | } 33 | 34 | /// Get information on a specific language *supported by PasteMyst*. 35 | /// You are recommened to only use the language names provided within 36 | /// `pastemyst::data::language` to prevent panicking. This method is 37 | /// asynchronous. 38 | /// 39 | /// This method does and will panic if a language is not found. The 40 | /// simplest solution to this is to use the language name you know - as 41 | /// mentioned earlier, it is recommended to use that specific module. 42 | /// 43 | /// Some fields, namely `color` and `ext` may not be provided and will 44 | /// have the value of `None`. This is because they are not provided 45 | /// by PasteMyst which means that they do not exist or specified anywhere. 46 | /// 47 | /// ## Examples 48 | /// ```rust 49 | /// use pastemyst::data::*; 50 | /// 51 | /// #[tokio::main] 52 | /// async fn main() -> DataResult<()> { 53 | /// let language: DataObject = get_language_by_name_async(language::CLANG).await?; 54 | /// println!("{:?}", language.name); 55 | /// Ok(()) 56 | /// } 57 | /// ``` 58 | pub async fn get_language_by_name_async(language_name: &str) -> DataResult { 59 | Ok(reqwest::get(&parse_url(language_name, "name")).await?.json().await?) 60 | } 61 | 62 | /// The same thing as getting a language by a name, except that it is by 63 | /// extension, of a given language. This is a synchronous method. 64 | /// 65 | /// This method will also panic if a language extension is not found. The 66 | /// simplest solution to this is to use the language extension that PasteMyst 67 | /// has. The easiest way to confirm so is to check if your desired language 68 | /// exists in `pastemyst::data::langauge`. 69 | /// 70 | /// This will return a `DataObject`. Some fields, namely `color` and `ext` may 71 | /// not be provided and will have the value of `None`. This is because they are 72 | /// not provided by PasteMyst which means that they do not exist or specified 73 | /// anywhere. 74 | /// 75 | /// ## Examples 76 | /// ```rust 77 | /// use pastemyst::data::*; 78 | /// 79 | /// fn main() -> DataResult<()> { 80 | /// let language: DataObject = get_language_by_extension("cs")?; 81 | /// println!("{}", language.name); 82 | /// Ok(()) 83 | /// } 84 | /// ``` 85 | pub fn get_language_by_extension(lang_extension: &str) -> DataResult { 86 | Ok(reqwest::blocking::get(&parse_url(lang_extension, "ext"))?.json()?) 87 | } 88 | 89 | /// The same thing as getting a language by a name, except that it is by 90 | /// extension, of a given language. This is an asynchronous method. 91 | /// 92 | /// This method will also panic if a language extension is not found. The 93 | /// simplest solution to this is to use the language extension that PasteMyst 94 | /// has. The easiest way to confirm so is to check if your desired language 95 | /// exists in `pastemyst::data::langauge`. 96 | /// 97 | /// This will return a `DataObject`. Some fields, namely `color` and `ext` may 98 | /// not be provided and will have the value of `None`. This is because they are 99 | /// not provided by PasteMyst which means that they do not exist or specified 100 | /// anywhere. 101 | /// 102 | /// ## Examples 103 | /// ```rust 104 | /// use pastemyst::data::*; 105 | /// 106 | /// #[tokio::main] 107 | /// async fn main() -> DataResult<()> { 108 | /// let language: DataObject = get_language_by_extension_async("c").await?; 109 | /// println!("{:?}", language.color); 110 | /// Ok(()) 111 | /// } 112 | /// ``` 113 | pub async fn get_language_by_extension_async(lang_extension: &str) -> DataResult { 114 | Ok(reqwest::get(&parse_url(lang_extension, "ext")).await?.json().await?) 115 | } 116 | 117 | #[derive(Deserialize)] 118 | #[allow(non_snake_case)] 119 | pub struct DataObject { 120 | /// The name of the language. 121 | pub name: String, 122 | /// The mode of a language used 123 | /// in a pasty editor. 124 | pub mode: String, 125 | /// A vector of the data types 126 | /// of each language that is 127 | /// meant to be used by official 128 | /// standards. 129 | pub mimes: Vec, 130 | /// The extension(s) of a language 131 | pub ext: Option>, 132 | /// The color of a language used 133 | /// to identify a language. 134 | /// 135 | /// This field may, or may not be 136 | /// provided by PasteMyst. 137 | pub color: Option, 138 | // /// An optional message provided 139 | // /// by PasteMyst if the language 140 | // /// has been found. 141 | // statusMessage: Option 142 | // if result.statusMessage == None { println!("[pastemyst] The provided language does not exist!"); } 143 | // Note: 144 | // Might be implemented, might not. I'll let it stay here like so for now. 145 | } 146 | 147 | fn parse_url(value: &str, req_type: &str) -> String { 148 | let parsed_url: String; 149 | if req_type == "name" { parsed_url = format!("{}language?name={}", DATA_ENDPOINT, &value); } 150 | else if req_type == "ext" { parsed_url = format!("{}languageExt?extension={}", DATA_ENDPOINT, &value); } 151 | else { panic!("[pastemyst] Invalid valid: `req_type` provided. Report the developer about this."); } 152 | return parsed_url; 153 | } 154 | 155 | /// An enum of PasteMyt language constants. 156 | //#[allow(non_camel_case_types)] 157 | pub mod language { 158 | pub const AUTODETECT: &str = "Autodetect"; 159 | pub const PLAIN: &str = "Plain Text"; 160 | pub const APL: &str = "APL"; 161 | pub const PGP: &str = "PGP"; 162 | pub const ASN1: &str = "ASN.1"; 163 | pub const ASTERISK: &str = "Asterisk"; 164 | pub const BRAINFUCK: &str = "Brainfuck"; 165 | pub const CLANG: &str = "C"; 166 | pub const C: &str = "C"; 167 | pub const CPP: &str = "C++"; 168 | pub const COBOL: &str = "Cobol"; 169 | pub const CSHARP: &str = "C#"; 170 | pub const CLOJURE: &str = "Clojure"; 171 | pub const CLOJURE_SCRIPT: &str = "ClojureScript"; 172 | pub const GSS: &str = "Closure Stylesheets (GSS)"; 173 | pub const CMAKE: &str = "CMake"; 174 | pub const COFFEE_SCRIPT: &str = "CoffeeScript"; 175 | pub const LISP: &str = "Common Lisp"; 176 | pub const CYPHER: &str = "Cypher"; 177 | pub const CYTHON: &str = "Cython"; 178 | pub const CRYSTAL: &str = "Crystal"; 179 | pub const CSS: &str = "CSS"; 180 | pub const CQL: &str = "CQL"; 181 | pub const DLANG: &'static str = "D"; 182 | pub const D: &str = "D"; 183 | pub const DART: &str = "Dart"; 184 | pub const DIFF: &str = "diff"; 185 | pub const DJANGO: &str = "Django"; 186 | pub const DOCKER: &str = "Dockerfile"; 187 | pub const DTD: &str = "DTD"; 188 | pub const DYLAN: &str = "Dylan"; 189 | pub const EBNF: &str = "EBNF"; 190 | pub const ECL: &str = "ECL"; 191 | pub const EDN: &str = "edn"; 192 | pub const EIFFEL: &str = "Eiffel"; 193 | pub const ELM: &str = "Elm"; 194 | pub const EJS: &str = "Embedded Javascript"; 195 | pub const ERB: &str = "Embedded Ruby"; 196 | pub const ERLANG: &str = "Erlang"; 197 | pub const ESPER: &str = "Esper"; 198 | pub const FACTOR: &str = "Factor"; 199 | pub const FCL: &str = "FCL"; 200 | pub const FORTH: &str = "Forth"; 201 | pub const FORTRAN: &str = "Fortran"; 202 | pub const FSHARP: &str = "F#"; 203 | pub const GAS: &str = "Gas"; 204 | pub const GHERKIN: &str = "Gherkin"; 205 | pub const GFM: &str = "GitHub Flavored Markdown"; 206 | pub const GITHUB_MARKDOWN: &str = "GitHub Flavored Markdown"; 207 | pub const GO: &str = "Go"; 208 | pub const GROOVY: &str = "Groovy"; 209 | pub const HAML: &str = "HAML"; 210 | pub const HASKELL: &str = "Haskell"; 211 | pub const HASKELL_LITERATE: &str = "Haskell (Literate)"; 212 | pub const HAXE: &str = "Haxe"; 213 | pub const HXML: &str = "HXML"; 214 | pub const ASP_NET: &str = "ASP.NET"; 215 | pub const HTML: &str = "HTML"; 216 | pub const HTTP: &str = "HTTP"; 217 | pub const IDL: &str = "IDL"; 218 | pub const PUG: &str = "Pug"; 219 | pub const JAVA: &str = "Java"; 220 | pub const JSP: &str = "Java Server Pages"; 221 | pub const JAVASCRIPT: &str = "JavaScript"; 222 | pub const JSON: &str = "JSON"; 223 | pub const JSON_LD: &str = "JSON-LD"; 224 | pub const JSX: &str = "JSX"; 225 | pub const JINJA2: &str = "Jinja2"; 226 | pub const JULIA: &str = "Julia"; 227 | pub const KOTLIN: &str = "Kotlin"; 228 | pub const LESS: &str = "LESS"; 229 | pub const LIVESCRIPT: &str = "LiveScript"; 230 | pub const LUA: &str = "Lua"; 231 | pub const MARKDOWN: &str = "Markdown"; 232 | pub const MIRC: &str = "mIRC"; 233 | pub const MARIA_DB: &str = "MariaDB SQL"; 234 | pub const MATHEMATICA: &str = "Mathematica"; 235 | pub const MODELICA: &str = "Modelica"; 236 | pub const MUMPS: &str = "MUMPS"; 237 | pub const MS_SQL: &str = "MS SQL"; 238 | pub const MBOX: &str = "mbox"; 239 | pub const MYSQL: &str = "MySQL"; 240 | pub const NGINX: &str = "Nginx"; 241 | pub const NSIS: &str = "NSIS"; 242 | pub const NTRIPLES: &str = "NTriples"; 243 | pub const OBJ_C: &str = "Objective-C"; 244 | pub const OCAML: &str = "OCaml"; 245 | pub const OCTAVE: &str = "Octave"; 246 | pub const OZ: &str = "Oz"; 247 | pub const PASCAL: &str = "Pascal"; 248 | pub const PEG_JS: &str = "PEG.js"; 249 | pub const PERL: &str = "Perl"; 250 | pub const PHP: &str = "PHP"; 251 | pub const PIG: &str = "Pig"; 252 | pub const PLSQL: &str = "PLSQL"; 253 | pub const POWERSHELL: &str = "PowerShell"; 254 | pub const INI: &str = "Properties files"; 255 | pub const PROTOBUF: &str = "ProtoBuf"; 256 | pub const PYTHON: &str = "Python"; 257 | pub const PUPPET: &str = "Puppet"; 258 | pub const QLANG: &str = "Q"; 259 | pub const RSCRIPT: &str = "R"; 260 | pub const RST: &str = "reStructuredText"; 261 | pub const RPM_CHANGES: &str = "RPM Changes"; 262 | pub const RPM_SPEC: &str = "RPM Spec"; 263 | pub const RUBY: &str = "Ruby"; 264 | pub const RUST: &str = "Rust"; 265 | pub const SAS: &str = "SAS"; 266 | pub const SASS: &str = "Sass"; 267 | pub const SCALA: &str = "Scala"; 268 | pub const SCHEME: &str = "Scheme"; 269 | pub const SCSS: &str = "SCSS"; 270 | pub const SHELL: &str = "Shell"; 271 | pub const SIEVE: &str = "Sieve"; 272 | pub const SLIM: &str = "Slim"; 273 | pub const SMALLTALK: &str = "Smalltalk"; 274 | pub const SMARTY: &str = "Smarty"; 275 | pub const SOLR: &str = "Solr"; 276 | pub const SML: &str = "SML"; 277 | pub const SOY: &str = "Soy"; 278 | pub const SPARQL: &str = "SPARQL"; 279 | pub const SPREADSHEET: &str = "Spreadsheet"; 280 | pub const SQL: &str = "SQL"; 281 | pub const SQLITE: &str = "SQLite"; 282 | pub const SQUIRREL: &str = "Squirrel"; 283 | pub const STYLUS: &str = "Stylus"; 284 | pub const SWIFT: &str = "SWIFT"; 285 | pub const STEX: &str = "sTeX"; 286 | pub const LATEX: &str = "LaTeX"; 287 | pub const SYSTEM_VERILOG: &str = "SystemVerilog"; 288 | pub const TCL: &str = "Tcl"; 289 | pub const TEXTILE: &str = "Textile"; 290 | pub const TIDDLYWIKI: &str = "TiddlyWiki"; 291 | pub const TIKI_WIKI: &str = "Tiki Wiki"; 292 | pub const TOML: &str = "TOML"; 293 | pub const TORNADO: &str = "Tornado"; 294 | pub const TROFF: &str = "troff"; 295 | pub const TTCN: &str = "TTCN"; 296 | pub const TTCN_CFG: &str = "TTCN_CFG"; 297 | pub const TURTLE: &str = "Turtle"; 298 | pub const TYPESCRIPT: &str = "TypeScript"; 299 | pub const TYPESCRIPT_JSX: &str = "TypeScript-JSX"; 300 | pub const TWIG: &str = "Twig"; 301 | pub const WEB_IDL: &str = "Web IDL"; 302 | pub const VB_NET: &str = "VB.NET"; 303 | pub const VBSCRIPT: &str = "VBScript"; 304 | pub const VELOCITY: &str = "Velocity"; 305 | pub const VERILOG: &str = "Verilog"; 306 | pub const VHDL: &str = "VHDL"; 307 | pub const VUE: &str = "Vue.js Component"; 308 | pub const XML: &str = "XML"; 309 | pub const XQUERY: &str = "XQuery"; 310 | pub const YACAS: &str = "Yacas"; 311 | pub const YAML: &str = "YAML"; 312 | pub const Z80: &str = "Z80"; 313 | pub const MSCGEN: &str = "mscgen"; 314 | pub const XU: &str = "xu"; 315 | pub const MSGENNY: &str = "msgenny"; 316 | } 317 | -------------------------------------------------------------------------------- /src/discord.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | /// This macro can assist prevention of 2 | /// converting an str to a String and 3 | /// calling that method each time. 4 | /// 5 | /// It can be used for other purposes 6 | /// if you wish to, but it's designed 7 | /// to work with any struct field that 8 | /// takes in a String type. Not necessarily 9 | /// recommened to be used however you can 10 | /// if you wish to but it's not compulsory. 11 | /// 12 | /// You can also use other macros like 13 | /// methods like `String::from` or even 14 | /// `to_string()` if you wish to. 15 | /// 16 | /// This method calls the `String::from` method. 17 | #[macro_export] 18 | macro_rules! str { 19 | {$value:expr} => (String::from($value)); 20 | } 21 | 22 | //#[cfg(feature = "time")] 23 | pub mod time; 24 | 25 | //#[cfg(feature = "data")] 26 | pub mod data; 27 | 28 | //#[cfg(feature = "user")] 29 | pub mod user; 30 | 31 | //#[cfg(feature = "paste")] 32 | pub mod paste; 33 | 34 | #[cfg(feature = "discord")] 35 | pub mod discord; 36 | -------------------------------------------------------------------------------- /src/paste.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | 4 | /// The PasteResult type provided 5 | /// by this library for ease. It 6 | /// has a return value and error. 7 | /// 8 | /// ## Examples 9 | /// ```rust 10 | /// use pastemyst::paste::PasteResult; 11 | /// 12 | /// fn main() -> PasteResult<()> { 13 | /// Ok(()) 14 | /// } 15 | /// ``` 16 | pub type PasteResult> = std::result::Result; 17 | 18 | #[allow(dead_code)] 19 | const ENDPOINT: &str = "https://paste.myst.rs/"; 20 | #[allow(dead_code)] 21 | const BASE_ENDPOINT: &str = "https://paste.myst.rs/api/v2/"; 22 | /// This endpoint is temporarily here due to a bug in pastemyst 23 | /// which does not allow the paste to be end when the last 24 | /// slash is present. 25 | const SEND_ENDPOINT: &str = "https://paste.myst.rs/api/v2/paste"; 26 | const PASTE_ENDPOINT: &str = "https://paste.myst.rs/api/v2/paste/"; 27 | 28 | /// Gets a paste's data in json format 29 | /// from [pastemyst](https://paste.myst.rs) 30 | /// synchronously. It returns a `Result` 31 | /// with a `PasteObject` and error. 32 | /// 33 | /// ## Examples 34 | /// 35 | /// ```rust 36 | /// use pastemyst::paste::get_paste; 37 | /// use pastemyst::paste::PasteResult; 38 | /// 39 | /// fn main() -> PasteResult<()> { 40 | /// let foo = get_paste("hipfqanx"); 41 | /// println!("{:?}", foo.title); 42 | /// Ok(()) 43 | /// } 44 | /// ``` 45 | /// 46 | pub fn get_paste(id: &str) -> Result { 47 | let info: PasteObject = reqwest::blocking::get(&parse_url(id))?.json()?; 48 | Ok(info) 49 | } 50 | 51 | /// Gets a paste's data in json format 52 | /// from [pastemyst](https://paste.myst.rs) 53 | /// asynchronously. It returns a `Result` 54 | /// with a `PasteObject` and error. 55 | /// 56 | /// ## Examples 57 | /// 58 | /// ```rust 59 | /// use pastemyst::paste::get_paste_async; 60 | /// use pastemyst::paste::PasteResult; 61 | /// 62 | /// #[tokio::main] 63 | /// async fn main() -> PasteResult<()> { 64 | /// let foo = get_paste_async("hipfqanx").await?; 65 | /// println!("{:?}", foo._id); 66 | /// Ok(()) 67 | /// } 68 | /// ``` 69 | pub async fn get_paste_async(id: &str) -> Result { 70 | let info: PasteObject = reqwest::get(&parse_url(id)).await?.json().await?; 71 | Ok(info) 72 | } 73 | 74 | /// Gets a private paste's data in json format 75 | /// from [pastemyst](https://paste.myst.rs) 76 | /// synchronously. It returns a `Result` 77 | /// with a `PasteObject` and error. 78 | /// 79 | /// ## Examples 80 | /// 81 | /// ```rust 82 | /// use pastemyst::paste::get_private_paste; 83 | /// use pastemyst::paste::PasteResult; 84 | /// 85 | /// fn main() -> PasteResult<()> { 86 | /// let foo = get_private_paste("pasteID", "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings"); 87 | /// println!("{:?}", foo._id); 88 | /// Ok(()) 89 | /// } 90 | /// ``` 91 | pub fn get_private_paste(id: &str, auth_token: &str) -> Result { 92 | let info: PasteObject = reqwest::blocking::Client::builder() 93 | .build()? 94 | .get(&parse_url(id)) 95 | .header("Authorization", auth_token) 96 | .send()? 97 | .json()?; 98 | Ok(info) 99 | } 100 | 101 | /// Gets a private paste's data in json format 102 | /// from [pastemyst](https://paste.myst.rs) 103 | /// asynchronously. It returns a `Result` 104 | /// with a `PasteObject` and error. 105 | /// 106 | /// ## Examples 107 | /// 108 | /// ```rust 109 | /// use pastemyst::paste::get_private_paste_async; 110 | /// use pastemyst::paste::PasteResult; 111 | /// 112 | /// #[tokio::main] 113 | /// async fn main() -> Result<()> { 114 | /// let foo = get_private_paste_async("pasteID", "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings").await?; 115 | /// println!("{}", paste.isPrivate); 116 | /// Ok(()) 117 | /// } 118 | /// ``` 119 | pub async fn get_private_paste_async( 120 | id: &str, 121 | auth_token: &str, 122 | ) -> Result { 123 | let info: PasteObject = reqwest::Client::builder() 124 | .build()? 125 | .get(&parse_url(&id)) 126 | .header("Authorization", auth_token) 127 | .send() 128 | .await? 129 | .json() 130 | .await?; 131 | Ok(info) 132 | } 133 | 134 | /// Uses the `CreateObject` struct as a parameter for paste 135 | /// data to be constructed into json format and sent to 136 | /// [pastemyst](https://paste.myst.rs) in a synchronous manner. 137 | /// 138 | /// ## Examples 139 | /// 140 | /// ```rust 141 | /// use pastemyst::paste::PastyObject; 142 | /// use pastemyst::paste::*; 143 | /// 144 | /// fn main() -> PasteResult<()> { 145 | /// let pasties: Vec = vec![ 146 | /// PastyObject { 147 | /// _id: None, 148 | /// language: Some(String::from("autodetect")), 149 | /// title: Some(String::from("Pasty1")), 150 | /// code: Some(String::from("Code")), 151 | /// }, 152 | /// PastyObject { 153 | /// _id: None, 154 | /// language: Some(String::from("autodetect")), 155 | /// title: Some(String::from("Pasty2")), 156 | /// code: Some(String::from("Code")), 157 | /// }, 158 | /// ]; 159 | /// let data: CreateObject = CreateObject { 160 | /// title: String::from("[crates.io/crates/pastemyst] This is a title"), 161 | /// expiresIn: String::from("1d"), 162 | /// isPrivate: false, 163 | /// isPublic: false, 164 | /// tags: String::from(""), 165 | /// pasties: pasties, 166 | /// }; 167 | /// let paste = create_paste(data)?; 168 | /// println!("{:#?}", paste._id); 169 | /// Ok(()) 170 | /// } 171 | /// ``` 172 | pub fn create_paste(contents: CreateObject) -> Result { 173 | let content_type = reqwest::header::HeaderValue::from_static("application/json"); 174 | let result = reqwest::blocking::Client::builder() 175 | .build()? 176 | .post(SEND_ENDPOINT) 177 | .header(reqwest::header::CONTENT_TYPE, content_type) 178 | .body(serde_json::to_string(&contents).unwrap()) 179 | .send() 180 | .unwrap(); 181 | Ok(result.json()?) 182 | } 183 | 184 | /// Uses the `CreateObject` struct as a parameter for paste 185 | /// data to be constructed into json format and sent to 186 | /// [pastemyst](https://paste.myst.rs) in an asynchronous manner. 187 | /// 188 | /// ## Examples 189 | /// 190 | /// ```rust 191 | /// use pastemyst::paste::PastyObject; 192 | /// use pastemyst::paste::*; 193 | /// 194 | /// #[tokio::main] 195 | /// async fn main() -> PasteResult<()> { 196 | /// let pasties: Vec = vec![ 197 | /// PastyObject { 198 | /// _id: None, 199 | /// language: Some(String::from("autodetect")), 200 | /// title: Some(String::from("Pasty1")), 201 | /// code: Some(String::from("Code")), 202 | /// }, 203 | /// PastyObject { 204 | /// _id: None, 205 | /// language: Some(String::from("autodetect")), 206 | /// title: Some(String::from("Pasty2")), 207 | /// code: Some(String::from("Code")), 208 | /// }, 209 | /// ]; 210 | /// let data: CreateObject = CreateObject { 211 | /// title: String::from("[crates.io/crates/pastemyst] This is a title"), 212 | /// expiresIn: String::from("1d"), 213 | /// isPrivate: false, 214 | /// isPublic: false, 215 | /// tags: String::from(""), 216 | /// pasties: pasties, 217 | /// }; 218 | /// let paste = paste::create_paste_async(data).await?; 219 | /// println!("{:?}", paste._id); 220 | /// Ok(()) 221 | /// } 222 | /// ``` 223 | pub async fn create_paste_async(contents: CreateObject) -> Result { 224 | let content_type = reqwest::header::HeaderValue::from_static("application/json"); 225 | let result = reqwest::Client::builder() 226 | .build()? 227 | .post(SEND_ENDPOINT) 228 | .header(reqwest::header::CONTENT_TYPE, content_type) 229 | .body(serde_json::to_string(&contents).unwrap()) 230 | .send() 231 | .await?; 232 | Ok(result.json().await?) 233 | } 234 | 235 | /// Uses the `CreateObject` and `&str` (`auth_token`) to 236 | /// send a paste to [pastemyst](https://paste.myst.rs) 237 | /// held under your account which you can configure 238 | /// to be private/public or not. You also get the 239 | /// authority to delete that paste. This is a 240 | /// synchronous method. 241 | /// 242 | /// ## Examples 243 | /// 244 | /// ```rust 245 | /// use pastemyst::paste::create_private_paste; 246 | /// use pastemyst::paste::get_paste; 247 | /// use pastemyst::paste::PasteResult; 248 | /// 249 | /// #[tokio::main] 250 | /// async fn main() -> Result<()> { 251 | /// let contents = get_paste("hipfqanx"); 252 | /// let paste = create_private_paste(contents, "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings").await?; 253 | /// println!("{}", paste.isPrivate); 254 | /// Ok(()) 255 | /// } 256 | /// ``` 257 | pub fn create_private_paste( 258 | contents: CreateObject, 259 | auth_token: &str, 260 | ) -> Result { 261 | let content_type = reqwest::header::HeaderValue::from_static("application/json"); 262 | let result = reqwest::blocking::Client::builder() 263 | .build()? 264 | .post(SEND_ENDPOINT) 265 | .header("Authorization", auth_token) 266 | .header(reqwest::header::CONTENT_TYPE, content_type) 267 | .body(serde_json::to_string(&contents).unwrap()) 268 | .send()?; 269 | Ok(result.json()?) 270 | } 271 | 272 | /// Uses the `CreateObject` struct and a `&str` authorization 273 | /// key as a parameter which you can get from user settings 274 | /// on [pastemyst](https://paste.myst.rs/user/settings). 275 | /// This data is constructed into json format and sent to 276 | /// [pastemyst](https://paste.myst.rs) 277 | /// in an asynchronous manner. The paste is send under 278 | /// the ownership of the account the auth key belongs to. 279 | /// 280 | /// ## Examples 281 | /// 282 | /// ```rust 283 | /// use pastemyst::paste::*; 284 | /// 285 | /// fn main() -> Result<(), reqwest::Error> /*PasteResult<()>*/ { 286 | /// let pasties: Vec = vec![ 287 | /// PastyObject { 288 | /// _id: None, 289 | /// language: Some(String::from("autodetect")), 290 | /// title: Some(String::from("A pasty title")), 291 | /// code: Some(String::from("fn main() { println!(\"Hello World!\"); }")), 292 | /// }, 293 | /// PastyObject { 294 | /// _id: None, 295 | /// title: Some(String::from("Another pasty title")), 296 | /// language: Some(String::from("autodetect")), 297 | /// code: Some(String::from( 298 | /// "#include \"stdio.h\"\n\nint main() {\n\tprintf(\"Hello World!\");\n}", 299 | /// )), 300 | /// }, 301 | /// ]; 302 | /// let data: CreateObject = CreateObject { 303 | /// title: String::from("[crates.io/crates/pastemyst] This is a title"), 304 | /// expiresIn: String::from("1d"), 305 | /// isPrivate: false, 306 | /// isPublic: false, 307 | /// tags: String::from(""), 308 | /// pasties, 309 | /// }; 310 | /// let paste = create_private_paste( 311 | /// data, 312 | /// "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings", 313 | /// )?; 314 | /// println!("{:#?}", paste.ownerId); 315 | /// Ok(()) 316 | /// } 317 | /// ``` 318 | pub async fn create_private_paste_async( 319 | contents: CreateObject, 320 | auth_token: &str, 321 | ) -> Result { 322 | let content_type = reqwest::header::HeaderValue::from_static("application/json"); 323 | let result = reqwest::Client::builder() 324 | .build()? 325 | .post(SEND_ENDPOINT) 326 | .header("Authorization", auth_token) 327 | .header(reqwest::header::CONTENT_TYPE, content_type) 328 | .body(serde_json::to_string(&contents).unwrap()) 329 | .send() 330 | .await?; 331 | Ok(result.json().await?) 332 | } 333 | 334 | /// Sends a request to pastemyst to edit a 335 | /// specific paste. You need to provide the 336 | /// `EditObject` struct i.e, whatever you 337 | /// want to edit. This is a synchronous method. 338 | /// 339 | /// An important note, the pasty will **NOT** 340 | /// be edited if you do not supply the id 341 | /// (or the correct id) of the pasty. PasteMyst 342 | /// needs to know which pasty to edit exactly. 343 | /// 344 | /// The API does not allow you to append more 345 | /// pastes as of this version writing this, 346 | /// you can only append pastes when editing 347 | /// within the site itself as the user. 348 | /// 349 | /// ## Examples 350 | /// 351 | /// ```rust 352 | /// use pastemyst::str; 353 | /// use pastemyst::paste; 354 | /// 355 | /// fn main() { 356 | /// let pasties = vec![pastemyst::paste::PastyObject { 357 | /// _id: str!("PastyID"), 358 | /// code: String::from("print('Hello World!')"), 359 | /// language: str!(pastemyst::data::language::PYTHON), 360 | /// title: "Pasty Title".to_string(), 361 | /// }]; 362 | /// let edit_object = pastemyst::paste::EditObject { 363 | /// isPrivate: false, 364 | /// isPublic: false, 365 | /// pasties: pasties, 366 | /// tags: str!("Hello, World"), 367 | /// title: str!("My title") 368 | /// }; 369 | /// let paste_result: PasteObject = paste::edit_paste(edit_object, 370 | /// "PasteID", 371 | /// "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings", 372 | /// )?; 373 | /// } 374 | /// ``` 375 | pub fn edit_paste(edit_info: EditObject, id: &str, auth_token: &str) -> Result { 376 | let content_type = reqwest::header::HeaderValue::from_static("application/json"); 377 | let result = reqwest::blocking::Client::builder() 378 | .build()? 379 | .patch(&parse_url(&id)) 380 | .header("Authorization", auth_token) 381 | .header(reqwest::header::CONTENT_TYPE, content_type) 382 | .body(serde_json::to_string(&edit_info).unwrap()) 383 | .send()?; 384 | Ok(result.json()?) 385 | } 386 | 387 | /// Sends a request to pastemyst to edit a 388 | /// specific paste. You need to provide the 389 | /// `EditObject` struct i.e, whatever you 390 | /// want to edit. This is a asynchronous method. 391 | /// 392 | /// An important note, the pasty will **NOT** 393 | /// be edited if you do not supply the id 394 | /// (or the correct id) of the pasty. PasteMyst 395 | /// needs to know which pasty to edit exactly. 396 | /// 397 | /// The API does not allow you to append more 398 | /// pastes as of this version writing this, 399 | /// you can only append pastes when editing 400 | /// within the site itself as the user. 401 | /// 402 | /// ## Examples 403 | /// 404 | /// ```rust 405 | /// use pastemyst::str; 406 | /// use pastemyst::paste; 407 | /// 408 | /// #[tokio::main] 409 | /// async fn main() { 410 | /// let pasties = vec![pastemyst::paste::PastyObject { 411 | /// _id: str!("PastyID"), 412 | /// code: String::from("print('Hello World!')"), 413 | /// language: str!(pastemyst::data::language::PYTHON), 414 | /// title: "Pasty Title".to_string(), 415 | /// }]; 416 | /// let edit_object = pastemyst::paste::EditObject { 417 | /// isPrivate: false, 418 | /// isPublic: false, 419 | /// pasties: pasties, 420 | /// tags: str!("Hello, World"), 421 | /// title: str!("My title") 422 | /// }; 423 | /// let paste_result: PasteObject = paste::edit_paste(edit_object, 424 | /// "PasteID", 425 | /// "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings", 426 | /// ).await?; 427 | /// } 428 | /// ``` 429 | pub async fn edit_paste_async(edit_info: EditObject, id: &str, auth_token: &str) -> Result { 430 | let content_type = reqwest::header::HeaderValue::from_static("application/json"); 431 | let result = reqwest::Client::builder() 432 | .build()? 433 | .patch(&parse_url(&id)) 434 | .header("Authorization", auth_token) 435 | .header(reqwest::header::CONTENT_TYPE, content_type) 436 | .body(serde_json::to_string(&edit_info).unwrap()) 437 | .send().await?; 438 | Ok(result.json().await?) 439 | } 440 | 441 | /// You can only delete pastes on your account, which 442 | /// means you must also provide the authorization key. 443 | /// This action is irreversible can the paste cannot 444 | /// be restored in any way. This methods sends the 445 | /// request synchronously. 446 | /// 447 | /// This method returns an unsigned 16 bit integer 448 | /// which is a status code recieved by the PasteMyst 449 | /// server. If a paste deletes successfully, you 450 | /// should recieve a status code of `200`. For 451 | /// a list of all the web status codes, refer to: 452 | /// https://en.wikipedia.org/wiki/List_of_HTTP_status_codes 453 | /// 454 | /// ### API Docs 455 | /// The relevent link to the API Documentation 456 | /// is: https://paste.myst.rs/api-docs/paste 457 | /// 458 | /// ```rust 459 | /// use pastemyst::paste::*; 460 | /// 461 | /// fn main() -> PasteResult<()> { 462 | /// let paste_del_result = delete_paste( 463 | /// "PasteID", 464 | /// "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings", 465 | /// )?; 466 | /// if (paste_del_result == 200) { println!("Paste has been deleted successfully."); } 467 | /// else { println!("Something went wrong and we recieved a status code of {}", paste_del_result); } 468 | /// Ok(()) 469 | /// } 470 | /// ``` 471 | pub fn delete_paste(id: &str, auth_token: &str) -> Result { 472 | let result = reqwest::blocking::Client::builder() 473 | .build()? 474 | .delete(&parse_url(&id)) 475 | .header("Authorization", auth_token) 476 | .send()?; 477 | Ok(result.status().as_u16()) 478 | } 479 | 480 | /// You can only delete pastes on your account, which 481 | /// means you must also provide the authorization key. 482 | /// This action is irreversible can the paste cannot 483 | /// be restored in any way. This methods sends the 484 | /// request asynchronously. 485 | /// 486 | /// This method returns an unsigned 16 bit integer 487 | /// which is a status code recieved by the PasteMyst 488 | /// server. If a paste deletes successfully, you 489 | /// should recieve a status code of `200`. For 490 | /// a list of all the web status codes, refer to: 491 | /// https://en.wikipedia.org/wiki/List_of_HTTP_status_codes 492 | /// 493 | /// ### API Docs 494 | /// The relevent link to the API Documentation 495 | /// is: https://paste.myst.rs/api-docs/paste 496 | /// 497 | /// ```rust 498 | /// use pastemyst::paste::*; 499 | /// 500 | /// #[tokio::main] 501 | /// async fn main() -> PasteResult<()> { 502 | /// let paste_del_result = delete_paste( 503 | /// "PasteID", 504 | /// "Your PasteMyst Token. Get it from: https://paste.myst.rs/user/settings", 505 | /// ).await?; 506 | /// if (paste_del_result == 200) { println!("Paste has been deleted successfully."); } 507 | /// else { println!("Something went wrong and we recieved a status code of {}", paste_del_result); } 508 | /// Ok(()) 509 | /// } 510 | /// ``` 511 | pub async fn delete_paste_async(id: &str, auth_token: &str) -> Result { 512 | let result = reqwest::Client::builder() 513 | .build()? 514 | .delete(&parse_url(&id)) 515 | .header("Authorization", auth_token) 516 | .send().await?; 517 | Ok(result.status().as_u16()) 518 | } 519 | 520 | /// Parses the url by combining 521 | /// the `PASTE_ENDPOINT` with a 522 | /// provided id. 523 | fn parse_url(id: &str) -> String { return PASTE_ENDPOINT.to_owned() + &id } 524 | 525 | /// The paste object recieved when 526 | /// getting a paste. It contains 527 | /// both the `PastyObject` and 528 | /// `EditHistory` in an array. 529 | /// 530 | /// ### API Docs 531 | /// The relevent link to the API documentation 532 | /// is: https://paste.myst.rs/api-docs/objects 533 | /// 534 | /// ## Examples 535 | /// 536 | /// ```rust 537 | /// let _foo: PasteObject = get_paste("hipfqanx"); 538 | /// ``` 539 | #[derive(Deserialize)] 540 | #[allow(non_snake_case, dead_code)] 541 | pub struct PasteObject { 542 | /// Id of the paste. 543 | pub _id: String, 544 | /// Id of the owner, if it doesn't 545 | /// have an owner it's set to "". 546 | pub ownerId: String, 547 | /// Title of the paste. 548 | pub title: String, 549 | /// Unix time of when 550 | /// the paste is created. 551 | pub createdAt: u64, 552 | /// When the paste will expire, 553 | /// possible values are 554 | /// `never`, `1h`, `2h`, `10h`, 555 | /// `1d`, `2d`, `1w`, `1m`, `1y`. 556 | pub expiresIn: String, 557 | /// When the paste will be deleted, if 558 | /// it has no expiry time it's set to 0. 559 | pub deletesAt: u64, 560 | /// Number of stars the paste received. 561 | pub stars: u64, 562 | /// If it's private it's only 563 | /// accessible by the owner. 564 | pub isPrivate: bool, 565 | /// Is it displayed on the 566 | /// owner's public profile. 567 | pub isPublic: bool, 568 | /// List of tags. 569 | pub tags: Vec, 570 | /// List of pasties/files in 571 | /// the paste, can't be empty. 572 | pub pasties: Vec, 573 | /// List of edits. 574 | pub edits: Vec, 575 | } 576 | 577 | /// Information about a specific pasty in a paste. 578 | /// 579 | /// All fields except `language` are optional but due 580 | /// to Rust's nature, so you must provide them. The 581 | /// _id field should always be set to `None` though 582 | /// if it's not, it is ignored by PasteMyst's API. 583 | /// 584 | /// The design choice of the language field not being 585 | /// optional was because auto detect isn't perfect 586 | /// and you generally should not rely on it especially 587 | /// with close bonded languages like C++ and C# which is 588 | /// sometimes confused by the language detector. However, 589 | /// you do not need to and can change set it to auto detect. 590 | /// 591 | /// ### API Docs 592 | /// The relevent link to the API documentation 593 | /// is: https://paste.myst.rs/api-docs/objects 594 | /// 595 | /// ## Examples 596 | /// 597 | /// ```rust 598 | /// let pasty: PastyObject = PastyObject { 599 | /// _id: None, 600 | /// language: pastemyst::data::language::JSON, 601 | /// title: Some(String::from("This is a pasty title")), 602 | /// code: Some(String::from("{\"This_Is\": \"JSON_Code\"}")), 603 | /// }; 604 | /// ``` 605 | #[derive(Serialize, Deserialize)] 606 | #[allow(non_snake_case, dead_code)] 607 | pub struct PastyObject { 608 | /// Id of the pasty. 609 | pub _id: String, 610 | /// Language of the pasty. 611 | pub language: String, 612 | /// title of the pasty. 613 | pub title: String, 614 | /// contents of the pasty. 615 | pub code: String, 616 | } 617 | 618 | /// Infomation about edits in a pasty in a paste. 619 | /// 620 | /// ### API Docs 621 | /// The relevent link to the API documentation 622 | /// is: https://paste.myst.rs/api-docs/objects 623 | /// 624 | /// ## Examples 625 | /// 626 | /// ```rust 627 | /// // Get paste from pastemyst 628 | /// let edits: EditHistory = paste.edits[0]; 629 | /// ``` 630 | #[derive(Deserialize)] 631 | #[allow(non_snake_case, dead_code)] 632 | pub struct EditHistory { 633 | /// Unique id of the edit. 634 | pub _id: String, 635 | /// Id of the edit, multiple edits can 636 | /// share the same id showing that multiple 637 | /// fields were changed at the same time. 638 | pub editId: String, 639 | /// Type of edit, possible values are 640 | /// title(0), pastyTitle(1), pastyLanguage(2), 641 | /// pastyContent(3), pastyAdded(4), pastyRemoved(5). 642 | pub editType: i32, 643 | /// Various metadata used internally, 644 | /// biggest usecase is storing exactly which 645 | /// pasty was edited. 646 | pub metadata: Vec, 647 | /// Actual paste edit, it stores old data 648 | /// before the edit as the current paste 649 | /// stores the new data 650 | pub edit: String, 651 | /// Unix time of when the edit was made 652 | pub editedAt: i32, 653 | } 654 | 655 | /// The structure object that holds 656 | /// the base to create a paste. This 657 | /// is then sent to pastemyst. All 658 | /// fields are optional *except* the 659 | /// `pasties` array which uses `PastyObject`. 660 | /// 661 | /// ### API Docs 662 | /// The relevent link to the API documentation 663 | /// is: https://paste.myst.rs/api-docs/objects 664 | /// 665 | /// ## Examples 666 | /// 667 | /// ```rust 668 | /// let _data: CreateObject = CreateObject { 669 | /// title: String::from("[crates.io/crates/pastemyst] This is a title"), 670 | /// expiresIn: String::from("1d"), 671 | /// isPrivate: false, 672 | /// isPublic: false, 673 | /// tags: String::from(""), 674 | /// pasties: pasties, 675 | /// }; 676 | /// ``` 677 | #[derive(Serialize)] 678 | #[allow(non_snake_case, dead_code)] 679 | pub struct CreateObject { 680 | /// Title of the paste. 681 | pub title: String, 682 | /// When the paste will expire, 683 | /// possible values are never, 1h, 684 | /// 2h, 10h, 1d, 2d, 1w, 1m, 1y. 685 | pub expiresIn: String, 686 | /// If it"s private it"s only 687 | /// accessible by the owner. 688 | pub isPrivate: bool, 689 | /// Is it displayed on the 690 | /// owner's public profile. 691 | pub isPublic: bool, 692 | /// List of tags, comma separated. 693 | pub tags: String, 694 | /// List of pasties. 695 | pub pasties: Vec, 696 | } 697 | 698 | /// The same as `CreateObject` except 699 | /// that it does not have the `expiresIn` 700 | /// field which has been removed for 701 | /// convenience. This may change in 702 | /// the future, but for the current 703 | /// moment, this shall remain. 704 | /// 705 | /// You can only edit pastes on your account, 706 | /// so you must provide the Authorization header. 707 | /// it returns a full paste object. To edit a paste 708 | /// you need to provide only the values you are 709 | /// editing in the JSON body. 710 | /// 711 | /// To edit a single pasty you will need to provide 712 | /// all of the original pasties changing the fields 713 | //// you want. it"s not possible to update a single 714 | /// pasty without providing all of the pasties. 715 | /// 716 | /// ### API Docs 717 | /// The relevent link to the API documentation 718 | /// is: https://paste.myst.rs/api-docs/paste#edit-a-paste 719 | /// 720 | /// ## Examples 721 | /// 722 | /// ```rust 723 | /// let _data: CreateObject = CreateObject { 724 | /// title: String::from("[crates.io/crates/pastemyst] This is a title"), 725 | /// expiresIn: String::from("1d"), 726 | /// isPrivate: false, 727 | /// isPublic: false, 728 | /// tags: String::from(""), 729 | /// pasties: var_pasties, 730 | /// }; 731 | /// ``` 732 | #[derive(Serialize)] 733 | #[allow(non_snake_case, dead_code)] 734 | pub struct EditObject { 735 | /// Title of the paste. 736 | pub title: String, 737 | /// If it"s private it"s only 738 | /// accessible by the owner. 739 | pub isPrivate: bool, 740 | /// Is it displayed on the 741 | /// owner's public profile. 742 | pub isPublic: bool, 743 | /// List of tags, comma separated. 744 | pub tags: String, 745 | /// List of pasties. 746 | pub pasties: Vec, 747 | } 748 | -------------------------------------------------------------------------------- /src/time.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | 3 | /// The type provided by the pastemyst lib. It takes 4 | /// a type `T` and evalutates to that type and a 5 | /// `Result` like so: `Result` where `E` has 6 | /// the default value of `reqwest::Error`. Keep note 7 | /// that `E` can be overriden. 8 | pub type TimeResult = Result; 9 | 10 | const TIME_ENDPOINT: &str = "https://paste.myst.rs/api/v2/time/expiresInToUnixTime"; 11 | 12 | /// All the possible values of the 13 | /// expiration of a paste provided 14 | /// by PasteMyst's API v2. 15 | pub mod expires_in { 16 | /// The paste will never expire. 17 | /// Granted that this will only 18 | /// not be deleted by the code 19 | /// base, the data may get lost 20 | /// from the physical drive 21 | /// though chances are extremely 22 | /// slim. 23 | pub const NEVER: &str = "never"; 24 | /// The paste will expire in 25 | /// an hour. 26 | pub const ONE_HOUR: &str = "1h"; 27 | /// The paste will expire in 28 | /// two hours. 29 | pub const TWO_HOURS: &str = "2h"; 30 | /// The paste will expire in 31 | /// ten hours. 32 | pub const TEN_HOURS: &str = "10h"; 33 | /// The paste will expire in 34 | /// one day (24 hours). 35 | pub const ONE_DAY: &str = "1d"; 36 | /// The paste will expire in 37 | /// two days (48 hours). 38 | pub const TWO_DAYS: &str = "2d"; 39 | /// The paste will expire in 40 | /// a week (168 hours). 41 | pub const ONE_WEEK: &str = "1w"; 42 | /// The paste will expire in 43 | /// a month (~672 hours). 44 | pub const ONE_MONTH: &str = "1m"; 45 | /// The paste will expire in 46 | /// a whole year (~8736 hours, 47 | /// followed by solar calander). 48 | pub const ONE_YEAR: &str = "1y"; 49 | } 50 | 51 | /// Synchronously sends a request to pastemyst's time 52 | /// module to convert the `expires_in` field to a unix 53 | /// timestamp. This method is really useful for time 54 | /// related operations where this kind of data is cruicial 55 | /// for certian functionality. 56 | /// 57 | /// If the `expires_in` field is not valid or recognized, 58 | /// it does **NOT** send any web requests and emits a warning. 59 | /// To prevent runtime exceptions, the return value, when unset 60 | /// i.e, when web requests aren't send, sets the value of the 61 | /// return integer to 0 regardless. 62 | /// 63 | /// The `created_at` value is an unsigned 64 bit integer meanwhile 64 | /// `expires_at` is a string. It's recommended to use provided strings 65 | /// by the library under `pastemyst::time::expires_in`. 66 | /// 67 | /// ### API Docs 68 | /// The relevent API documentation for this method is: 69 | /// https://paste.myst.rs/api-docs/time 70 | /// 71 | /// ## Examples 72 | /// 73 | /// ```rust 74 | /// use pastemyst::time::*; 75 | /// 76 | /// fn main() -> TimeResult<()> { 77 | /// let unix_time: u64 = expires_into_unix(42, expires_in::ONE_DAY)?; 78 | /// println!("{}", unix_time.to_string()); 79 | /// Ok(()) 80 | /// } 81 | /// ``` 82 | pub fn expires_into_unix(created_at: u64, expires_in: &str) -> TimeResult { 83 | let mut response: TimeObject = TimeObject { result: 0 }; 84 | #[allow(unused_assignments)] let mut valid_time: bool = false; 85 | match expires_in { 86 | expires_in::NEVER => valid_time = true, 87 | expires_in::ONE_HOUR => valid_time = true, 88 | expires_in::TWO_HOURS => valid_time = true, 89 | expires_in::ONE_DAY => valid_time = true, 90 | expires_in::TWO_DAYS => valid_time = true, 91 | expires_in::ONE_WEEK => valid_time = true, 92 | expires_in::ONE_MONTH => valid_time = true, 93 | expires_in::ONE_YEAR => valid_time = true, 94 | _ => valid_time = false 95 | } 96 | if valid_time { 97 | response = reqwest::blocking::get(&parse_time(created_at, expires_in))? 98 | .json().unwrap(); 99 | } else { println!("[pastemyst] The given expires timestamp is not valid and 0 will be returned."); } 100 | Ok(response.result) 101 | } 102 | 103 | /// Asynchronously sends a request to pastemyst's time 104 | /// module to convert the `expires_in` field to a unix 105 | /// timestamp. This method is really useful for time 106 | /// related operations where this kind of data is cruicial 107 | /// for certian functionality. 108 | /// 109 | /// If the `expires_in` field is not valid or recognized, 110 | /// it does **NOT** send any web requests and emits a warning. 111 | /// To prevent runtime exceptions, the return value, when unset 112 | /// i.e, when web requests aren't send, sets the value of the 113 | /// return integer to 0 regardless. 114 | /// 115 | /// The `created_at` value is an unsigned 64 bit integer meanwhile 116 | /// `expires_at` is a string. It's recommended to use provided strings 117 | /// by the library under `pastemyst::time::expires_in`. 118 | /// 119 | /// ### API Docs 120 | /// The relevent API documentation for this method is: 121 | /// https://paste.myst.rs/api-docs/time 122 | /// 123 | /// ## Examples 124 | /// 125 | /// ```rust 126 | /// use pastemyst::time::*; 127 | /// 128 | /// #[tokio::main] 129 | /// async fn main() -> TimeResult<()> { 130 | /// let unix_time: u64 = expires_into_unix_async(1337, expires_in::TWO_DAYS).await?; 131 | /// println!("{}", unix_time.to_string()); 132 | /// Ok(()) 133 | /// } 134 | /// ``` 135 | pub async fn expires_into_unix_async(created_at: u64, expires_in: &str) -> TimeResult { 136 | let mut response: TimeObject = TimeObject { result: 0 }; 137 | #[allow(unused_assignments)] let mut valid_time: bool = false; 138 | match expires_in { 139 | expires_in::NEVER => valid_time = true, 140 | expires_in::ONE_HOUR => valid_time = true, 141 | expires_in::TWO_HOURS => valid_time = true, 142 | expires_in::ONE_DAY => valid_time = true, 143 | expires_in::TWO_DAYS => valid_time = true, 144 | expires_in::ONE_WEEK => valid_time = true, 145 | expires_in::ONE_MONTH => valid_time = true, 146 | expires_in::ONE_YEAR => valid_time = true, 147 | _ => valid_time = false 148 | } 149 | if valid_time { 150 | response = reqwest::Client::builder() 151 | .build()? 152 | .get(&parse_time(created_at, expires_in)) 153 | .send().await? 154 | .json().await?; 155 | } else { println!("[pastemyst] The given expires timestamp is not valid and 0 will be returned."); } 156 | Ok(response.result) 157 | } 158 | 159 | /// This struct is only here so 160 | /// that the json object recieved 161 | /// from the API can be serialized 162 | /// for the variable to be extracted 163 | /// and be returned directly instead 164 | /// of the struct itself for ease. 165 | /// This is the main reason why this 166 | /// struct has been kept private. 167 | #[derive(Deserialize)] 168 | struct TimeObject { result: u64 } 169 | 170 | /// Parses the time module's API path 171 | fn parse_time(created_at: u64, expires_in: &str) -> String { 172 | return format!( 173 | "{}?createdAt={}&expiresIn={}", 174 | TIME_ENDPOINT, created_at, expires_in 175 | ) 176 | } 177 | -------------------------------------------------------------------------------- /src/user.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | 3 | /// The type provided by the pastemyst lib. It takes 4 | /// a type `T` and evalutates to that type and a 5 | /// `Result` like so: `Result` where `E` has 6 | /// the default value of `reqwest::Error`. Keep note 7 | /// that `E` can be overriden. 8 | pub type UserResult = Result; 9 | 10 | const USER_ENDPOINT: &str = "https://paste.myst.rs/api/v2/user/"; 11 | 12 | /// Gets a user synchronously from [pastemyst](https://paste.myst.rs) 13 | /// This information is stored in the `UserObject` struct. If a user 14 | /// does not exist, it will return nothing and emit a console log 15 | /// warning about the user not existing. 16 | /// 17 | /// As of now, there is no specific way to disable this warning 18 | /// unless you compile your own version. This might change in 19 | /// the future, but for now, a warning will be emmited if 20 | /// it returns false. 21 | /// 22 | /// It still returns the struct when a user is not found and emit 23 | /// a warning as stated earlier except that this method will return 24 | /// an empty struct i.e, all the strings will be set to `""`, all 25 | /// the booleans set to false and all numerics set to 0. 26 | /// 27 | /// ### API Docs 28 | /// The relevent API documentation for this method is: 29 | /// https://paste.myst.rs/api-docs/user 30 | /// 31 | /// ## Examples 32 | /// 33 | /// ```rust 34 | /// use pastemyst::user::*; 35 | /// 36 | /// fn main() -> UserResult<()> { 37 | /// let user_data = get_user("ANF-Studios")?; 38 | /// println!("{:?}", user_data.defaultLang); 39 | /// Ok(()) 40 | /// } 41 | /// ``` 42 | pub fn get_user(username: &str) -> UserResult { 43 | let mut result: UserObject = UserObject { 44 | _id: str!(""), 45 | username: str!(""), 46 | avatarUrl: str!(""), 47 | defaultLang: str!(""), 48 | publicProfile: false, 49 | supporterLength: 0, 50 | contributor: false 51 | }; 52 | if user_exists(username)? == false { 53 | print!("[pastemyst] The user '{}' does not exist and an empty object is returned.\n", username); 54 | } else { 55 | result = reqwest::blocking::Client::builder() 56 | .build()? 57 | .get(&parse_user(username)) 58 | .send()? 59 | .json()?; 60 | } 61 | Ok(result) 62 | } 63 | 64 | /// Gets a user asynchronously from [pastemyst](https://paste.myst.rs) 65 | /// This information is stored in the `UserObject` struct. If a user 66 | /// does not exist, it will return nothing and emit a console log 67 | /// warning about the user not existing. 68 | /// 69 | /// As of now, there is no specific way to disable this warning 70 | /// unless you compile your own version. This might change in 71 | /// the future, but for now, a warning will be emmited if 72 | /// it returns false. 73 | /// 74 | /// It still returns the struct when a user is not found and emit 75 | /// a warning as stated earlier except that this method will return 76 | /// an empty struct i.e, all the strings will be set to `""`, all 77 | /// the booleans set to false and all numerics set to 0. 78 | /// 79 | /// ### API Docs 80 | /// The relevent API documentation for this method is: 81 | /// https://paste.myst.rs/api-docs/user 82 | /// 83 | /// ## Examples 84 | /// 85 | /// ```rust 86 | /// use pastemyst::user::*; 87 | /// 88 | /// #[tokio::main] 89 | /// async fn main() -> UserResult<()> { 90 | /// let user_data = get_user_async("ANF-Studios").await?; 91 | /// println!("{:?}", user_data._id); 92 | /// Ok(()) 93 | /// } 94 | /// ``` 95 | pub async fn get_user_async(username: &str) -> Result { 96 | let mut result: UserObject = UserObject { 97 | _id: str!(""), 98 | username: str!(""), 99 | avatarUrl: str!(""), 100 | defaultLang: str!(""), 101 | publicProfile: false, 102 | supporterLength: 0, 103 | contributor: false 104 | }; 105 | if user_exists_async(username).await? == false { 106 | print!("[pastemyst] The user '{}' does not exist and an empty object is returned.\n", username); 107 | } else { 108 | result = reqwest::Client::builder() 109 | .build()? 110 | .get(&parse_user(username)) 111 | .send().await? 112 | .json().await?; 113 | } 114 | Ok(result) 115 | } 116 | 117 | /// Sends a request to [pastemyst](https://paste.myst.rs) 118 | /// to check if a user exists. If a user *does exist*, 119 | /// it returns a value of `200` i.e, `true` else `false`. 120 | /// This methods runs synchronously. 121 | /// 122 | /// The return value of this function is not to be confused 123 | /// with an integer -- this method returns a boolean. 124 | /// 125 | /// ### API Docs 126 | /// The relevent API documentation for this method is: 127 | /// https://paste.myst.rs/api-docs/user 128 | /// 129 | /// ## Examples 130 | /// 131 | /// ```rust 132 | /// use pastemyst::user::*; 133 | /// 134 | /// fn main() -> UserResult<()> { 135 | /// const USERNAME: &str = "ANF-Studios"; 136 | /// let exists: bool = user_exists(USERNAME)?; 137 | /// print!("The user '{}' exists: {}", USERNAME, exists); 138 | /// Ok(()) 139 | /// } 140 | /// ``` 141 | /// 142 | /// ```rust 143 | /// use pastemyst::user::*; 144 | /// 145 | /// fn main() -> Result<(), Box> { 146 | /// const USERNAME: &str = "ANF-Studios"; 147 | /// if user_exists(USERNAME)? == true { 148 | /// println!("{} does indeed exist!", USERNAME); 149 | /// } else { println!("{} was not found and does not exist.", USERNAME); } 150 | /// Ok(()) 151 | /// } 152 | /// ``` 153 | pub fn user_exists(username: &str) -> UserResult { 154 | let result = reqwest::blocking::Client::builder() 155 | .build()? 156 | .get(&parse_user_get(username)) 157 | .send()?; 158 | let mut user_exists: bool = false; 159 | if result.status().as_u16() == 200 { user_exists = true; } 160 | else if result.status().as_u16() == 404 { user_exists = false; } 161 | Ok(user_exists) 162 | } 163 | 164 | /// Sends a request to [pastemyst](https://paste.myst.rs) 165 | /// to check if a user exists. If a user *does exist*, 166 | /// it returns a value of `200` i.e, `true` else `false`. 167 | /// This methods runs asynchronously. 168 | /// 169 | /// The return value of this function is not to be confused 170 | /// with an integer -- this method returns a boolean. 171 | /// 172 | /// ### API Docs 173 | /// The relevent API documentation for this method is: 174 | /// https://paste.myst.rs/api-docs/user 175 | /// 176 | /// ## Examples 177 | /// 178 | /// ```rust 179 | /// use pastemyst::user::*; 180 | /// 181 | /// #[tokio::main] 182 | /// async fn main() -> UserResult<()> { 183 | /// const USERNAME: &str = "ANF-Studios"; 184 | /// let exists: bool = user_exists(USERNAME).await?; 185 | /// print!("The user '{}' exists: {}", USERNAME, exists); 186 | /// Ok(()) 187 | /// } 188 | /// ``` 189 | /// 190 | /// ```rust 191 | /// use pastemyst::user::*; 192 | /// 193 | /// #[tokio::main] 194 | /// async fn main() -> Result<(), Box> { 195 | /// const USERNAME: &str = "ANF-Studios"; 196 | /// if user_exists(USERNAME).await? == true { 197 | /// println!("{} does indeed exist!", USERNAME); 198 | /// } else { println!("{} was not found and does not exist.", USERNAME); } 199 | /// Ok(()) 200 | /// } 201 | /// ``` 202 | pub async fn user_exists_async(username: &str) -> UserResult { 203 | let result = reqwest::Client::builder() 204 | .build()? 205 | .get(&parse_user_get(username)) 206 | .send().await?; 207 | let mut user_exists: bool = false; 208 | if result.status().as_u16() == 200 { user_exists = true; } 209 | else if result.status().as_u16() == 404 { user_exists = false; } 210 | Ok(user_exists) 211 | } 212 | 213 | /// Parses a user `GET` url endpoint. 214 | fn parse_user(username: &str) -> String { return format!("{}{}", USER_ENDPOINT, username) } 215 | /// Parses a user exists url endpoint. 216 | fn parse_user_get(username: &str) -> String { return format!("{}{}/exists", USER_ENDPOINT, username) } 217 | 218 | /// The user object that pastemyst provides. 219 | /// It has all the public details of a user. 220 | /// 221 | /// ### API Docs 222 | /// The relevent API documentation for this method is: 223 | /// https://paste.myst.rs/api-docs/user 224 | #[derive(Deserialize)] 225 | #[allow(non_snake_case, dead_code, unused_doc_comments)] 226 | pub struct UserObject { 227 | /// Id of the user. 228 | pub _id: String, 229 | /// The username of the user. 230 | pub username: String, 231 | /// URL of the avatar image. 232 | pub avatarUrl: String, 233 | /// The default pasty language 234 | /// of the user. 235 | pub defaultLang: String, 236 | /// If their profile is public 237 | /// or not. 238 | pub publicProfile: bool, 239 | /// How long has the user 240 | /// been a supporter for, 241 | /// 0 if not a supporter 242 | pub supporterLength: u32, 243 | /// If the user has contributed 244 | /// to pastemyst. 245 | pub contributor: bool, 246 | } 247 | --------------------------------------------------------------------------------