commit 67c27c101b4223d648aad78cb25c99802ca67845 Author: Wessel Tip Date: Wed Feb 4 10:33:15 2026 +0100 feat: Initial rust API PoC diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..076f801 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,235 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "chrono" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.74" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "mueapi" +version = "0.1.0" +dependencies = [ + "chrono 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum chrono 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6" +"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" +"checksum libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10" +"checksum num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" +"checksum num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +"checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" +"checksum proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" +"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +"checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +"checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +"checksum serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3" +"checksum serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e" +"checksum serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)" = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" +"checksum syn 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4" +"checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d2203e8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "mueapi" +version = "0.1.0" +authors = ["Wessel T "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rand = "0.7.3" +serde = { version = "1.0.114", features = ["derive"] } +serde_json = "1.0.56" +chrono = "0.4.13" \ No newline at end of file diff --git a/src/Cargo.toml b/src/Cargo.toml new file mode 100644 index 0000000..d2203e8 --- /dev/null +++ b/src/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "mueapi" +version = "0.1.0" +authors = ["Wessel T "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rand = "0.7.3" +serde = { version = "1.0.114", features = ["derive"] } +serde_json = "1.0.56" +chrono = "0.4.13" \ No newline at end of file diff --git a/src/images.json b/src/images.json new file mode 100644 index 0000000..2fc9543 --- /dev/null +++ b/src/images.json @@ -0,0 +1,1927 @@ +[ + { + "id": 1, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/62f7603fd6cb98a1.jpg", + "photographer": "Glasvegas", + "location": "Tenerife" + }, + { + "id": 2, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c4ee1485bd4cf6a2.jpg", + "photographer": "Glasvegas", + "location": "Tenerife" + }, + { + "id": 3, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/3b2097ce4f2f1edf.jpg", + "photographer": "Glasvegas", + "location": "Tenerife" + }, + { + "id": 4, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e76e1d2246102fef.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 5, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9480579e58ba1528.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 6, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/faf04a55c8b8dbe2.jpg", + "photographer": "Eartharoid", + "location": "Leicester" + }, + { + "id": 7, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/7bd1894f9149bf39.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 8, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/5b2e267e16e91289.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 9, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c828af5314229a86.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 10, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/79f7ecb8ac8b0739.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 11, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e68ed7001124079b.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 12, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/6d1db610f497bc69.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 13, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9b6e3d8ea246c6f4.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 14, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/35b6e796e68e89e3.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 15, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/f16f6a1854d89bbd.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 16, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/141dc3bc66992f7e.jpg", + "photographer": "Eartharoid", + "location": "Devon" + }, + { + "id": 17, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/5c2a768ffb58e276.jpg", + "photographer": "Eartharoid", + "location": "Scotland" + }, + { + "id": 18, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/04ab199be7a203d9.jpg", + "photographer": "Eartharoid", + "location": "Scotland" + }, + { + "id": 19, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/a4f28bd4fcff2894.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 20, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/60c37b211381bb9c.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 21, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9d54fd66ecb7fc08.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 22, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/b6fdee9d2fab9d91.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 23, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/f60976f0304f072f.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 24, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/adef4624dc02175c.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 25, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/b0d7e2fca0320db0.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 26, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/dbf5291e041180f7.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 27, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/50fae089fb76151d.jpg", + "photographer": "Nikka Lai", + "location": "Wetland Park" + }, + { + "id": 28, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/5a2bcf7e892546af.jpg", + "photographer": "Nikka Lai", + "location": "Wetland Park" + }, + { + "id": 29, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/808d604a45f7cd85.jpg", + "photographer": "Nikka Lai", + "location": "Wetland Park" + }, + { + "id": 30, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/78906e0d0b8214e2.jpg", + "photographer": "Roee Lupo", + "location": "Israel" + }, + { + "id": 31, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/dfb64fd5f491e112.jpg", + "photographer": "Roee Lupo", + "location": "Israel" + }, + { + "id": 32, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/be86e4ebe19a097a.jpg", + "photographer": "Roee Lupo", + "location": "New York" + }, + { + "id": 33, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/b6fd19c06cb51e01.jpg", + "photographer": "Roee Lupo", + "location": "New York" + }, + { + "id": 34, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/dde2effbd881fc2d.jpg", + "photographer": "Anders", + "location": "Møre og Romsdal" + }, + { + "id": 35, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/153c602749e2a3d1.jpg", + "photographer": "Anders", + "location": "Møre og Romsdal" + }, + { + "id": 36, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e8326f7f27379c3e.jpg", + "photographer": "Anders", + "location": "Møre og Romsdal" + }, + { + "id": 37, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/47f9dc11019c5053.jpg", + "photographer": "Anders", + "location": "Møre og Romsdal" + }, + { + "id": 38, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9e8f54751c6a24d5.jpg", + "photographer": "Anders", + "location": "Møre og Romsdal" + }, + { + "id": 39, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c3dfbaccecb7e705.jpg", + "photographer": "Anders", + "location": "Storseisundet Bridge" + }, + { + "id": 40, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/7dcdbc0e23a54ef1.jpg", + "photographer": "Alex Sparkes", + "location": "Rotherham" + }, + { + "id": 41, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/649402556a3c2f9d.jpg", + "photographer": "Alex Sparkes", + "location": "Rotherham" + }, + { + "id": 42, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/f14d1c2d150e28ce.jpg", + "photographer": "Alex Sparkes", + "location": "Rotherham" + }, + { + "id": 43, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/a643b26a1f2a6131.jpg", + "photographer": "Alex Sparkes", + "location": "Rotherham" + }, + { + "id": 44, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/782771e85ac67b1c.jpg", + "photographer": "Alex Sparkes", + "location": "Manchester" + }, + { + "id": 45, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c46e62aabd31dcad.jpg", + "photographer": "Alex Sparkes", + "location": "Manchester" + }, + { + "id": 46, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/09132e550e915bcc.jpg", + "photographer": "Alex Sparkes", + "location": "Manchester" + }, + { + "id": 47, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/14a93d54c86ea734.jpg", + "photographer": "Alex Sparkes", + "location": "Manchester" + }, + { + "id": 48, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/5fc23656d792e90d.jpg", + "photographer": "Alex Sparkes", + "location": "Cardiff" + }, + { + "id": 49, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e3958c3e90ae1e5c.jpg", + "photographer": "Alex Sparkes", + "location": "Cardiff" + }, + { + "id": 50, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/d7eb7a574e11fc43.jpg", + "photographer": "Alex Sparkes", + "location": "Cardiff" + }, + { + "id": 51, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/72e6d5f17b3981fc.jpg", + "photographer": "Alex Sparkes", + "location": "Cardiff" + }, + { + "id": 52, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/1161a3c99025ff13.jpg", + "photographer": "Alex Sparkes", + "location": "Cardiff" + }, + { + "id": 53, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/93f7e4935b9cca81.jpg", + "photographer": "Alex Sparkes", + "location": "Cardiff" + }, + { + "id": 54, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/7617290436ff5c4e.jpg", + "photographer": "Alex Sparkes", + "location": "Cardiff" + }, + { + "id": 55, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/71f1f0891e1e12b0.jpg", + "photographer": "Alex Sparkes", + "location": "London" + }, + { + "id": 56, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/2f0a3144cd91bf75.jpg", + "photographer": "Alex Sparkes", + "location": "London" + }, + { + "id": 57, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e0aca08791cf0092.jpg", + "photographer": "Alex Sparkes", + "location": "Filey" + }, + { + "id": 58, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/6403bc22107b6d66.jpg", + "photographer": "Alex Sparkes", + "location": "East Yorkshire" + }, + { + "id": 59, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/eea01f9a6d583bc7.jpg", + "photographer": "Alex Sparkes", + "location": "East Yorkshire" + }, + { + "id": 60, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/79d2e3ee99f8bf4d.jpg", + "photographer": "Alex Sparkes", + "location": "Bridlington" + }, + { + "id": 61, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/404af6647ecc3c3b.jpg", + "photographer": "Alex Sparkes", + "location": "Bridlington" + }, + { + "id": 62, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/95079ef20e508d3b.jpg", + "photographer": "David Ralph", + "location": "Lake District" + }, + { + "id": 63, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/70c635b29681dc3b.jpg", + "photographer": "David Ralph", + "location": "Lake District" + }, + { + "id": 64, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/2686908b6397e197.jpg", + "photographer": "David Ralph", + "location": "Lake District" + }, + { + "id": 65, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/2b8180278c3856f2.jpg", + "photographer": "David Ralph", + "location": "Lake District" + }, + { + "id": 66, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e895a9144c3a0a62.jpg", + "photographer": "David Ralph", + "location": "Lake District" + }, + { + "id": 67, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/775225ca745d5c10.jpg", + "photographer": "David Ralph", + "location": "Lake District" + }, + { + "id": 68, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/51c6bac821f52a1a.jpg", + "photographer": "David Ralph", + "location": "Lake District" + }, + { + "id": 69, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/5673dbea43d753ba.jpg", + "photographer": "David Ralph", + "location": "Lake District" + }, + { + "id": 70, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/648e58d1c4aece0f.jpg", + "photographer": "David Ralph", + "location": "Lake District" + }, + { + "id": 71, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/eddad8bdeced4826.jpg", + "photographer": "David Ralph", + "location": "Lake District" + }, + { + "id": 72, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c34b3ec03f32d3fc.jpg", + "photographer": "David Ralph", + "location": "Lake District" + }, + { + "id": 73, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/1ae15dd3366d70c1.jpg", + "photographer": "David Ralph", + "location": "Richmond" + }, + { + "id": 74, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/f0dac8fa2a80b524.jpg", + "photographer": "David Ralph", + "location": "Richmond" + }, + { + "id": 75, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/8010f60e55a304d1.jpg", + "photographer": "David Ralph", + "location": "Richmond" + }, + { + "id": 76, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/46394eb0f96b7b5a.jpg", + "photographer": "David Ralph", + "location": "Richmond" + }, + { + "id": 77, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ead99df8b4b67d6c.jpg", + "photographer": "David Ralph", + "location": "Skipton" + }, + { + "id": 78, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/45c7fe99637b0974.jpg", + "photographer": "David Ralph", + "location": "Chester Zoo" + }, + { + "id": 79, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/288dc661cde797fc.jpg", + "photographer": "David Ralph", + "location": "Chester Zoo" + }, + { + "id": 80, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/edc01b752693c749.jpg", + "photographer": "David Ralph", + "location": "Chester Zoo" + }, + { + "id": 81, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c1cdcebdd3084e7e.jpg", + "photographer": "David Ralph", + "location": "Chester Zoo" + }, + { + "id": 82, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/cb364208e2faa87d.jpg", + "photographer": "David Ralph", + "location": "Chester Zoo" + }, + { + "id": 86, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/64c5df8ca6cf6008.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 87, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e2bfbcce9c1279f9.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 88, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/73e7af655c5e35ae.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 89, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9d342223c6a1c1e3.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 90, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9c00d66e325f60cd.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 91, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/8e2feb2cab9f14a8.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 92, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/17a0e160588fcd3a.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 93, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/a6d021804e6d4162.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 94, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/2ae74ba22f101b17.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 95, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/f3e1273d0c696529.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 96, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e99be2505f192011.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 97, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/172e4c0910b5d820.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 98, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/f9954f44b3d1ce8b.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 99, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e729f3453193a341.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 100, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/5c7563ff16c06b47.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 101, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/607ae87926ed60bc.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 102, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/6a79bf21afc94791.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 103, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/a285b77b0ef8cff2.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 104, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/a0e2c654d6b913e9.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 105, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/83a350600982c5ad.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 106, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/666972d1442ff88b.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 107, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/f059462a6d43a368.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 108, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/38046c9b315eb3ef.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 109, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/db750b240c66e797.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 110, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/943bac322fcaed69.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 111, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c4e829ca4a2b8533.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 112, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9eaa7438a8a8a385.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 113, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c91940b7e59070c7.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 114, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ae3e3262672bc7bf.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 115, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/5dbaeccf99d60ae0.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 116, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/aabf440c29aac149.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 117, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/bca00513e3416f8a.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 118, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/6126280bee390eb8.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 119, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/a9015a1f4f410f70.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 120, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/a0db03ca91da41d9.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 121, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c9d6b3eed26ed745.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 122, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/5ead80a59c88779a.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 123, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/61a3c0ae8a6d919b.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 124, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/1ba18b1252dabe71.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 125, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/cae842dbfa60fd14.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 126, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/bae8fdc8632eaba0.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 127, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/fb668929571401d7.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 128, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/dbc73cbad7e23a26.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 129, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e959eea025d077b7.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 130, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/edf2b07af3639db2.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 131, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/52003d152b53bd47.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 132, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/bdbf94139fc5c5e4.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 133, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/81a69dde4a18859c.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 134, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c6eb5de841eccaf4.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 135, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/762653519c9abc2e.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 136, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/390e0617f8530af0.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 137, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/2f5a50885f473d6a.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 138, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/acd5582998a42f40.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 139, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/25c51b8f20df1f72.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 140, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ed533da3716a9ccd.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 141, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9fb954949d42bbac.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 142, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/8c6d319ea71986dc.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 143, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e01733f39b47fc2c.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 144, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/4bc1891b5eacca0b.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 145, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/890e05310ffd3584.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 146, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/1d96504a580623c5.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 147, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/bf2f557d5f717325.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 148, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/d3f87cf49831fe8a.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 149, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/51110fadd13cf18f.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 150, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/62e4bbd32dd0fe97.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 151, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c613325689b7510d.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 152, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/856af5442d8abdae.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 153, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/626c610558ae6647.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 154, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/35c66f7400201ec4.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 155, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/d019789eaf90de79.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 156, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ae8cfdab8ecf11b8.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 157, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/72ec3998834f99d6.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 158, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e9057cf47e117611.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 159, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e891f524dad357f3.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 160, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/a9f983c01d439038.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 161, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/6d852889561e8070.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 162, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/3d8b4c1bac9cfc0a.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 163, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/90d9fc866545886f.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 164, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ff1594c43e3623b1.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 165, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/147d5415c893d808.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 166, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9cd0bda48cf948fd.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 167, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/102a9b4a25f72ac4.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 168, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/89c6225d79c00417.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 169, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e423030123a81c72.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 170, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9b5df89c7ca168d7.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 171, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/1673c0c00a034a46.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 172, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/b7defe75fae00aa8.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 173, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/40b53708624d91c6.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 174, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/819a80699266e414.jpg", + "photographer": "Eartharoid", + "location": "Longleat Safari Park" + }, + { + "id": 175, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/19f07741330fce45.jpg", + "photographer": "Eartharoid", + "location": "Farewood Lakes" + }, + { + "id": 176, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e7d52cf921182dff.jpg", + "photographer": "Eartharoid", + "location": "Farewood Lakes" + }, + { + "id": 177, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/bce296a2b3d1b626.jpg", + "photographer": "Eartharoid", + "location": "Peak District" + }, + { + "id": 178, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ef786931a8366f17.jpg", + "photographer": "Eartharoid", + "location": "Peak District" + }, + { + "id": 179, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/3d586f836cf5ef98.jpg", + "photographer": "Eartharoid", + "location": "Lacock Village" + }, + { + "id": 180, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/5e7e254e8c589b30.jpg", + "photographer": "Eartharoid", + "location": "Lacock Village" + }, + { + "id": 181, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/44aa70dbf3e9dbbe.jpg", + "photographer": "Eartharoid", + "location": "Lacock Village" + }, + { + "id": 182, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/f8be05ad21e182ce.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 183, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c4e47bc6b9b30266.jpg", + "photographer": "David Ralph", + "location": "Skipton" + }, + { + "id": 184, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/23d3171e1a276e8a.jpg", + "photographer": "David Ralph", + "location": "Skipton" + }, + { + "id": 185, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/0592dfec575a8414.jpg", + "photographer": "David Ralph", + "location": "Skipton" + }, + { + "id": 186, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/78ff331a7aa4bda3.jpg", + "photographer": "David Ralph", + "location": "Cotswold Wildlife Park" + }, + { + "id": 187, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/0d3401be23d18082.jpg", + "photographer": "David Ralph", + "location": "Cotswold Wildlife Park" + }, + { + "id": 188, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e575f42e2faa4f73.jpg", + "photographer": "David Ralph", + "location": "Cotswold Wildlife Park" + }, + { + "id": 189, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/8baf83e10764b045.jpg", + "photographer": "David Ralph", + "location": "Cotswold Wildlife Park" + }, + { + "id": 190, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ac40c75468c2d05d.jpg", + "photographer": "David Ralph", + "location": "Cotswold Wildlife Park" + }, + { + "id": 191, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/bb7d5f8952a63a83.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 192, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/44469203f53794fe.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 193, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/caacfc282e3e0b75.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 194, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/f16441a89248bcd8.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 195, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/6ee38be83b80240d.jpg", + "photographer": "Jeroen", + "location": "Netherlands" + }, + { + "id": 196, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/962801ac0198719d.jpg", + "photographer": "Alex Sparkes", + "location": "Knaresborough" + }, + { + "id": 197, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9fc5d32b32b13f9a.jpg", + "photographer": "David Ralph", + "location": "Kenilworth Castle" + }, + { + "id": 198, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/02e0b707a25a5fed.jpg", + "photographer": "David Ralph", + "location": "Kenilworth Castle" + }, + { + "id": 199, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/fed7fc154bb20c65.jpg", + "photographer": "David Ralph", + "location": "Kenilworth Castle" + }, + { + "id": 200, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/b601db9ee5a2c617.jpg", + "photographer": "David Ralph", + "location": "Kenilworth Castle" + }, + { + "id": 201, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ca006b1f7f6c295b.jpg", + "photographer": "David Ralph", + "location": "Kenilworth Castle" + }, + { + "id": 202, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/62716497dc85fe19.jpg", + "photographer": "David Ralph", + "location": "Kenilworth Castle" + }, + { + "id": 203, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/06b8a3177d1559f0.jpg", + "photographer": "David Ralph", + "location": "Kenilworth Castle" + }, + { + "id": 204, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/3eb854e4b12c2345.jpg", + "photographer": "Oded Shapira", + "location": "Stavanger, Norway" + }, + { + "id": 205, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/9ca5e9a841894132.jpg", + "photographer": "Oded Shapira", + "location": "Stavanger, Norway" + }, + { + "id": 206, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/8414b893afe96a19.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 207, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/59a696812ea9f730.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 208, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/0f07283bccc925ec.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 209, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/4c9e7a0b16fe9045.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 210, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/363226b05f0bfe07.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 211, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/aed361c399cfa62d.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 212, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c7bfc9291fab6998.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 213, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/3a177c67399d5714.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 214, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/42289bedde5c3870.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 215, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ae6ffa3fb977b5ef.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 216, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/50c7fc0772ed144f.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 217, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/6fc173d871a43c6e.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 218, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/6fb751be47a3ddb6.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 219, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/de604fd5cacfe91a.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 220, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c27f47abeb08b94a.jpg", + "photographer": "Oded Shapira", + "location": "Forsand Municipality, Norway" + }, + { + "id": 221, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/4f1f5d5c88b67662.jpg", + "photographer": "Oded Shapira", + "location": "Bergen, Norway" + }, + { + "id": 222, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/b3565395f78c3290.jpg", + "photographer": "Oded Shapira", + "location": "Bergen, Norway" + }, + { + "id": 223, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/8d295ad95dd4e3d2.jpg", + "photographer": "Oded Shapira", + "location": "Ålesund, Norway" + }, + { + "id": 224, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e473437beeabed0c.jpg", + "photographer": "Oded Shapira", + "location": "Ålesund, Norway" + }, + { + "id": 225, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/4a789bc7398cc34e.jpg", + "photographer": "Oded Shapira", + "location": "Ålesund, Norway" + }, + { + "id": 226, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/8dd8205c2e1dba2c.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 227, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/85a2addb6a39dd3d.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 228, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/19f453e466ebc9f2.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 229, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/bce4d9dc514c7e73.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 230, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ebfc1e38dd26d911.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 231, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/32362b50633d8f0a.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 232, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/239274adc8f6c0f5.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 233, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/34dc94c292f6b044.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 234, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/6d761216482efbaf.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 235, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/1c502337231375b4.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 236, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/70116752d8e9936b.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 237, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e86747b319efb9b5.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 238, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/b1812a0e96c25511.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 239, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/fbf8c43ec0333d6f.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 240, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/40b4b8074e0c0736.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 241, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/89924b5e7bd26c14.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 242, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/efc995fa8d1d7173.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 243, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e730dcfccf3d4178.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 244, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/a07c239da666409f.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 245, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/4891620c7788dda7.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 246, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/d9418cd86c95ccac.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 247, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ac54d285b6e0e552.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 248, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/4cd86a33417006e4.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 249, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/4038f0ea6251f564.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 250, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/b8dc0fdb4f513233.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 251, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/2096911b67747bbe.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 252, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/7524f8b7b0cd413b.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 253, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/17b49e417e773d2a.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 254, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/ba563f8aee245813.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 255, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/f979189d9c52a64c.jpg", + "photographer": "Oded Shapira", + "location": "Norway" + }, + { + "id": 256, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/32138e4ca85a821d.jpg", + "photographer": "Noa Shapira", + "location": "New York" + }, + { + "id": 257, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/7ec7e10605c230d2.jpg", + "photographer": "Noa Shapira", + "location": "Norway" + }, + { + "id": 258, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/606a5333e2e12b61.jpg", + "photographer": "Noa Shapira", + "location": "Norway" + }, + { + "id": 259, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/efc983c498b7d8b2.jpg", + "photographer": "Noa Shapira", + "location": "Norway" + }, + { + "id": 260, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/94ecf5deb9c4bb74.jpg", + "photographer": "Noa Shapira", + "location": "Norway" + }, + { + "id": 261, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/76e28818ee5aa72d.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 262, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/0df607cca306bfec.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 263, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/2e71c7ac269ef64d.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 264, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/0a7a4c03610152a7.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 265, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/80d147e5097d980c.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 266, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/821539f01b5e96aa.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 267, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c4464bd49909acd2.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 268, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/4c65948beefd9866.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 269, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/465b06a059a7494d.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 270, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/3df74923e4e7c8cf.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 271, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/371be6e9e0fa0619.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 272, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/48baf28e1fd41b11.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 273, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/c3f5382fee5ac245.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 274, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e76be26885e9f6a1.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 275, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/cccf836d057cd703.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 276, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/f3264a1a8cd655f7.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 277, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/e72598131e5013f5.jpg", + "photographer": "Eartharoid", + "location": "Bradgate Park" + }, + { + "id": 278, + "category": "Outdoors", + "file": "https://cdn.derpyenterprises.org/mue/57c3ecf81e90541f.jpg", + "photographer": "Jack Shanks", + "location": "East Yorkshire" + } +] \ No newline at end of file diff --git a/src/json.rs b/src/json.rs new file mode 100644 index 0000000..79a6a5a --- /dev/null +++ b/src/json.rs @@ -0,0 +1,38 @@ +use serde_json; +use rand::Rng; +use std::fs; + +/// Converts the given file path into a JSON object +/// +/// # Arguments +/// * `filename` - The path to the file to parse +/// +/// # Examples +/// ``` +/// use json::parse; +/// let file = parse("./src/array.json"); +/// ``` +pub fn parse(filename: &str) -> serde_json::Value { + serde_json::from_str(&fs::read_to_string(filename).expect("Expected valid JSON")).expect("JSON was not well-formatted") +} + +/// Returns a random value from the given array, errors if not typeof `serde_json::Value::Array` +/// # Arguments +/// * `input` - The array to grab a random entry from +/// +/// # Examples +/// ``` +/// use json; +/// json::rand_or_error(&json::parse("./src/array.json")).unwrap(); +/// ``` +pub fn rand_or_error(input: &serde_json::Value) -> Result<&serde_json::Value, String> { + let mut rand = rand::thread_rng(); + let internal = String::from("{ \"code\": 500, \"message\": \"internal server error\" }"); + + if let serde_json::Value::Array(array) = input { + let entry = &array[(rand.gen::() * array.len() as f32).floor() as usize]; + Ok(entry) + } else { + Err(internal) + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..1a1e26a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,96 @@ +mod json; +mod thread; + +use std::str; +use std::sync::Arc; +use std::io::prelude::*; +use std::net::TcpStream; +use std::net::TcpListener; +use std::env; + +extern crate chrono; + +/* + args[1] = port + args[2] = threads + args[3] = host +*/ + +fn main() { + let mut args = vec![]; + for argument in env::args() { + args.push(argument); + } + + println!("PID; {}", std::process::id()); + + // ! Port to run on + let listener = TcpListener::bind(format!("127.0.0.1:{}", args[1])).unwrap(); + + // ! Amount of threads used + let threads = args[2].parse().unwrap(); + let pool = thread::ThreadPool::new(threads); + + let img = Arc::new(json::parse("./src/images.json")); + let quote = Arc::new(json::parse("./src/quotes.json")); + + for stream in listener.incoming() { + let stream = stream.unwrap_or_else(|ex| panic!(ex)); + let img_clone = Arc::clone(&img); + let quote_clone = Arc::clone("e); + + pool.execute(move || { + handle_connection(stream, img_clone, quote_clone); + }); + } +} + +fn response(status: String, content: String, headers: Vec) -> String { + let mut args = vec![]; + for argument in env::args() { + args.push(argument); + } + + // ! Change the domain name + let host = &args[3]; + let now = chrono::Utc::now().format("%a, %e %b %Y %T UTC").to_string(); + let mut header = Vec::new(); + + header.extend(headers.into_iter()); + + header.push(format!("Date: {}", now)); + header.push(format!("Server: {}", host)); + header.push(String::from("Cache-Control: max-age=0, private, must-revalidate")); + header.push(String::from("Access-Control-Allow-Origin: *")); + + format!("HTTP/1.1 {}\r\n{}\r\n\r\n{}", status, header.join("\r\n"), content) +} + +fn handle_connection(mut stream: TcpStream, img: Arc, quote: Arc) { + let mut buffer: Vec = vec![0; 512]; + + stream.read(&mut buffer).unwrap(); + + let req: &str = str::from_utf8(&buffer).unwrap().split("\r\n").next().unwrap(); + let base_headers: Vec = vec![String::from("Content-Type: application/json; charset=utf-8")]; + + let resp: String = if "GET /getimage HTTP/1.1".eq_ignore_ascii_case(req) { + let content = json::rand_or_error(&img); + response(String::from("200 Ok"), content.unwrap().to_string(), base_headers) + } else if "GET /update HTTP/1.1".eq_ignore_ascii_case(req) { + let content: String = String::from("{}"); + response(String::from("200 Ok"), content, base_headers) + } else if "GET /quote HTTP/1.1".eq_ignore_ascii_case(req) { + let content: Result<&serde_json::Value, String> = json::rand_or_error("e); + response(String::from("200 Ok"), content.unwrap().to_string(), base_headers) + } else if "GET /getcategories HTTP/1.1".eq_ignore_ascii_case(req) { + let content: String = String::from("[\"Outdoors\", \"Cheese\"]"); + response(String::from("200 Ok"), content, base_headers) + } else { + let content: String = String::from("{ \"code\": 404, \"message\": \"not found\" }"); + response(String::from("404 Not Found"), content, base_headers) + }; + + stream.write(resp.as_bytes()).unwrap(); + stream.flush().unwrap(); +} \ No newline at end of file diff --git a/src/quotes.json b/src/quotes.json new file mode 100644 index 0000000..4e40722 --- /dev/null +++ b/src/quotes.json @@ -0,0 +1,224 @@ +[ + { + "id": 1, + "author": "Albert Einstein", + "quote": "Be a voice not an echo.", + "language": "English" + }, + { + "id": 2, + "author": "Unknown", + "quote": "You are the only one who can limit your greatness", + "language": "English" + }, + { + "id": 3, + "author": "Ralph Waldo Emerson", + "quote": "Make the most of yourself...for that is all there is of you", + "language": "English" + }, + { + "id": 4, + "author": "E.E Cummings", + "quote": "It takes courage to grow up and become who you really are.", + "language": "English" + }, + { + "id": 5, + "author": "Mark Twain", + "quote": "The two most important days in your life are the day you are born and the day you find out why.", + "language": "English" + }, + { + "id": 6, + "author": "Munia Khan", + "quote": "You can find a better you inside of you. Why don’t you search for that?", + "language": "English" + }, + { + "id": 7, + "author": "George Eliot", + "quote": "It is never too late to be what you might have been.", + "language": "English" + }, + { + "id": 8, + "author": "Abraham Lincoln", + "quote": "Whatever you are, be a good one.", + "language": "English" + }, + { + "id": 9, + "author": "Al Goldstein", + "quote": "The true success is the person who invented himself.", + "language": "English" + }, + { + "id": 10, + "author": "Anna Quindlen", + "quote": "Give up on being perfect and start working on becoming yourself.", + "language": "English" + }, + { + "id": 11, + "author": "Robert De Niro", + "quote": "Time goes on. So whatever you’re going to do, do it. Do it now. Don’t wait.", + "language": "English" + }, + { + "id": 12, + "author": "Walt Disney", + "quote": "All our dreams can come true, if we have the courage to pursue them.", + "language": "English" + }, + { + "id": 13, + "author": "Confucius", + "quote": "It does not matter how slowly you go as long as you do not stop.", + "language": "English" + }, + { + "id": 14, + "author": "Roy T. Bennett", + "quote": "Believe in yourself. You are braver than you think, more talented than you know, and capable of more than you imagine.", + "language": "English" + }, + { + "id": 15, + "author": "Wayne Dyer", + "quote": "If you believe it will work out, you’ll see opportunities. If you believe it won’t, you will see obstacles.", + "language": "English" + }, + { + "id": 16, + "author": "George Addair", + "quote": "Everything you’ve ever wanted is on the other side of fear", + "language": "English" + }, + { + "id": 17, + "author": "Winston Churchill", + "quote": "Success is not final, failure is not fatal: it is the courage to continue that counts.", + "language": "English" + }, + { + "id": 18, + "author": "Paulo Coelho", + "quote": "There is only one thing that makes a dream impossible to achieve: the fear of failure.", + "language": "English" + }, + { + "id": 19, + "author": "Brian Tracy", + "quote": "Your true success in life begins only when you make the commitment to become excellent at what you do.", + "language": "English" + }, + { + "id": 20, + "author": "Chantal Sutherland", + "quote": "Believe in yourself, take on your challenges, dig deep within yourself to conquer fears. Never let anyone bring you down. You got to keep going", + "language": "English" + }, + { + "id": 21, + "author": "Les Brown", + "quote": "Too many of us are not living our dreams because we are living our fears.", + "language": "English" + }, + { + "id": 22, + "author": "Bob Riley", + "quote": "Hard times don’t create heroes. It is during the hard times when the ‘hero’ within us is revealed.", + "language": "English" + }, + { + "id": 23, + "author": "Jack Canfield", + "quote": "If you can tune into your purpose and really align with it, setting goals so that your vision is an expression of that purpose, then life flows much more easily.", + "language": "English" + }, + { + "id": 24, + "author": "Napoleon Hill", + "quote": "Whatever the mind can conceive and believe, it can achieve.", + "language": "English" + }, + { + "id": 25, + "author": "Jim Rohn", + "quote": "Don’t wish it were easier. Wish you were better.", + "language": "English" + }, + { + "id": 26, + "author": "Serena Williams", + "quote": "A champion is defined not by their wins but by how they can recover when they fall.", + "language": "English" + }, + { + "id": 27, + "author": "Sheryl Sandberg", + "quote": "Motivation comes from working on things we care about.", + "language": "English" + }, + { + "id": 28, + "author": "Reese Witherspoon", + "quote": "With the right kind of coaching and determination you can accomplish anything.", + "language": "English" + }, + { + "id": 29, + "author": "Hazrat Inayat Khan", + "quote": "Some people look for a beautiful place. Others make a place beautiful.", + "language": "English" + }, + { + "id": 30, + "author": "Albert Einstein", + "quote": "Life is like riding a bicycle. To keep your balance, you must keep moving.", + "language": "English" + }, + { + "id": 31, + "author": "Walt Disney", + "quote": "The way to get started is to quit talking and begin doing.", + "language": "English" + }, + { + "id": 32, + "author": "Winston Churchill", + "quote": "A pessimist sees the difficulty in every opportunity; an optimist sees the opportunity in every difficulty.", + "language": "English" + }, + { + "id": 33, + "author": "Will Rogers", + "quote": "Don't let yesterday take up too much of today.", + "language": "English" + }, + { + "id": 34, + "author": "Vince Lombardi", + "quote": "It's not whether you get knocked down, it's whether you get up.", + "language": "English" + }, + { + "id": 35, + "author": "Steve Jobs", + "quote": "If you are working on something that you really care about, you don’t have to be pushed. The vision pulls you.", + "language": "English" + }, + { + "id": 36, + "author": "DJ Khaled", + "quote": "You gotta water your plants. Nobody can water them for you.", + "language": "English" + }, + { + "id": 37, + "author": "Stephen Hawking", + "quote": "However difficult life may seem, there is always something you can do and succeed at.", + "language": "English" + } +] \ No newline at end of file diff --git a/src/thread.rs b/src/thread.rs new file mode 100644 index 0000000..ad5ec74 --- /dev/null +++ b/src/thread.rs @@ -0,0 +1,98 @@ +use std::thread; +use std::sync::Arc; +use std::sync::Mutex; +use std::sync::mpsc; + +enum Message { + NewJob(Job), + Terminate, +} + +#[allow(dead_code)] +pub struct ThreadPool { + workers: Vec, + sender: mpsc::Sender, +} + +type Job = Box; + +impl ThreadPool { + pub fn new(size: usize) -> ThreadPool { + assert!(size > 0); + let (sender, receiver) = mpsc::channel(); + let receiver = Arc::new(Mutex::new(receiver)); + + let mut workers = Vec::with_capacity(size); + + for id in 0..size { + workers.push(Worker::new(id, Arc::clone(&receiver))); + } + + ThreadPool { workers, sender } + } + + pub fn execute(&self, f: F) + where + F: FnOnce() + Send + 'static, + { + let job = Box::new(f); + + self.sender.send(Message::NewJob(job)).unwrap(); + } + +} + +impl Drop for ThreadPool { + fn drop(&mut self) { + println!("Sending terminate message to all workers."); + + for _ in &self.workers { + self.sender.send(Message::Terminate).unwrap(); + } + + println!("Shutting down all workers"); + for worker in &mut self.workers { + println!("Shutting down worker {}", worker.id); + + if let Some(thread) = worker.thread.take() { + thread.join().unwrap(); + } + } + } +} + +#[allow(dead_code)] +struct Worker { + id: usize, + thread: Option> +} + +impl Worker { + fn new(id: usize, receiver: Arc>>) -> Worker { + let thread = thread::spawn(move || loop { + let message = receiver + .lock() + .expect("[Worker] Failed to get Mutex, possibly in poisoned state") + .recv() + .unwrap(); + + match message { + Message::NewJob(job) => { + println!("[Worker {}] got a job; executing.", id); + + job(); + } + Message::Terminate => { + println!("[Worker {}] was told to terminate.", id); + + break; + } + } + }); + + Worker { + id, + thread: Some(thread) + } + } +} \ No newline at end of file