commit 317a0f972c101a6fdb920b7411b9e36cecd9a0ed Author: Ruthenic Date: Sun Jan 29 06:42:37 2023 -0500 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1b8afd0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.ts \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..415c95c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "deno.enable": true, + "deno.unstable": true, + "deno.importMap": "./import_map.json", + "editor.formatOnSave": true +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6d95c71 --- /dev/null +++ b/LICENSE @@ -0,0 +1,11 @@ +Copyright 2023 Ruthenic + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3e39688 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Voltpad +simplistic wattpad frontend (ala invidious or nitter) written in Deno + +### Why? +Imho the Wattpad website is insufferable to use. The layout feels broken half the time, stories only take up the middle third of the screen (along with the rest of the site), fragmented and weird search page(s), inability to directly search by tag, the dumbass algorithm (especially on the homepage) which has never actually recommended me a story I'd like, on and on ad infinitum + +### Setup +1. Install Deno +2. Copy `config.template.ts` to `config.ts`, and fill out/change the information as you see fit +3. Run the index.tsx file `deno -A index.tsx` +4. Congrats, you are now running Voltpad + +### Contributing +You probably shouldn't because the code is jank, but I mean you can \ No newline at end of file diff --git a/components/Header.tsx b/components/Header.tsx new file mode 100644 index 0000000..538084e --- /dev/null +++ b/components/Header.tsx @@ -0,0 +1,19 @@ +import sass from "https://deno.land/x/denosass@1.0.6/mod.ts"; +import { Props } from "../types.d.ts"; +import { h } from "../jsx.ts"; + +interface BaseHeaderProps extends Props { + id?: string; + entries: { + name: string; + href: string; + }[]; +} + +export default (props: BaseHeaderProps) => ( +
+ {props.entries + .map((entry) => {entry.name}) + .join("")} +
+); diff --git a/config.template.ts b/config.template.ts new file mode 100644 index 0000000..576dc5f --- /dev/null +++ b/config.template.ts @@ -0,0 +1,22 @@ +interface Config { + serve: { + address: string; + port: number; + }; + user?: { + username: string; + password: string; + }; +} + +export default { + serve: { + address: "localhost", + port: 8080, + }, + // note that you can remove the user object and it will work; stories marked as mature will be inaccessible, however. + user: { + username: "USERNAME_OR_EMAIL", + password: "PASSWORD", + }, +} as Config; diff --git a/css/index.scss b/css/index.scss new file mode 100644 index 0000000..d54791f --- /dev/null +++ b/css/index.scss @@ -0,0 +1,107 @@ +html { + background-color:beige; + font-family: "IBM Plex Sans", system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; +} + +a { + &:link, + &:visited, + &:hover { + color: black; + } +} + +img { + max-width: 75%; +} + +.main { + display: flex; + flex-direction: column; + align-items: center; + /* a bit of jank */ + input { + border-radius: 0.25em; + } + label { + margin-right: 0.5em; + } +} + +.stories { + display: flex; + flex-direction: column; + align-items: center; + a { + color: black; + border: none; + outline: none; + text-decoration: none; + + &:link, + &:visited, + &:hover { + color: inherit; + } + } +} + +.story { + display: flex; + flex-direction: row; + div { + display: flex; + flex-direction: column; + align-items: start; + margin-left: 0.5em; + } + margin-top: 1em; + min-width: 75%; + max-width: 75%; +} + +.pagenav { + margin-top: 1em; + display: flex; + flex-direction: row; +} + +.header { + position: sticky; + top: 0.5em; + background-color: darkgrey; + width: 100%; + min-height: 2em; + display: flex; + align-items: center; + justify-content: center; + &#storyHeader { + justify-content: flex-start; + } + overflow-x: auto; + overflow-y: auto; + border-radius: 0.5em; + border-style: solid; + border-width: 1px; + border-color:#0f0f0f; + a { + &:first-child { + margin-left: 0.5em; + } + + &:last-child { + margin-right: 0.5em; + } + + &:link, + &:visited, + &:hover { + color: black; + } + + display: flex; + text-align: center; + margin-right: 0.5em; + width:fit-content; + } +} \ No newline at end of file diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..210442e --- /dev/null +++ b/deno.json @@ -0,0 +1,12 @@ +{ + "fmt": { + "options": { + "indentWidth": 4 + } + }, + "compilerOptions": { + "jsxFactory": "h", + "jsxFragmentFactory": "Fragment", + "lib": ["dom", "deno.window"] + } +} diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..7a47a89 --- /dev/null +++ b/deno.lock @@ -0,0 +1,185 @@ +{ + "version": "2", + "remote": { + "https://deno.land/std@0.131.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74", + "https://deno.land/std@0.131.0/_util/os.ts": "49b92edea1e82ba295ec946de8ffd956ed123e2948d9bd1d3e901b04e4307617", + "https://deno.land/std@0.131.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3", + "https://deno.land/std@0.131.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09", + "https://deno.land/std@0.131.0/path/_util.ts": "c1e9686d0164e29f7d880b2158971d805b6e0efc3110d0b3e24e4b8af2190d2b", + "https://deno.land/std@0.131.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633", + "https://deno.land/std@0.131.0/path/glob.ts": "cb5255638de1048973c3e69e420c77dc04f75755524cb3b2e160fe9277d939ee", + "https://deno.land/std@0.131.0/path/mod.ts": "4275129bb766f0e475ecc5246aa35689eeade419d72a48355203f31802640be7", + "https://deno.land/std@0.131.0/path/posix.ts": "663e4a6fe30a145f56aa41a22d95114c4c5582d8b57d2d7c9ed27ad2c47636bb", + "https://deno.land/std@0.131.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9", + "https://deno.land/std@0.131.0/path/win32.ts": "e7bdf63e8d9982b4d8a01ef5689425c93310ece950e517476e22af10f41a136e", + "https://deno.land/std@0.152.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74", + "https://deno.land/std@0.152.0/_util/os.ts": "3b4c6e27febd119d36a416d7a97bd3b0251b77c88942c8f16ee5953ea13e2e49", + "https://deno.land/std@0.152.0/async/deferred.ts": "bc18e28108252c9f67dfca2bbc4587c3cbf3aeb6e155f8c864ca8ecff992b98a", + "https://deno.land/std@0.152.0/bytes/bytes_list.ts": "aba5e2369e77d426b10af1de0dcc4531acecec27f9b9056f4f7bfbf8ac147ab4", + "https://deno.land/std@0.152.0/bytes/equals.ts": "3c3558c3ae85526f84510aa2b48ab2ad7bdd899e2e0f5b7a8ffc85acb3a6043a", + "https://deno.land/std@0.152.0/bytes/mod.ts": "763f97d33051cc3f28af1a688dfe2830841192a9fea0cbaa55f927b49d49d0bf", + "https://deno.land/std@0.152.0/crypto/timing_safe_equal.ts": "82a29b737bc8932d75d7a20c404136089d5d23629e94ba14efa98a8cc066c73e", + "https://deno.land/std@0.152.0/encoding/base64.ts": "c57868ca7fa2fbe919f57f88a623ad34e3d970d675bdc1ff3a9d02bba7409db2", + "https://deno.land/std@0.152.0/fmt/colors.ts": "6f9340b7fb8cc25a993a99e5efc56fe81bb5af284ff412129dd06df06f53c0b4", + "https://deno.land/std@0.152.0/http/_negotiation/common.ts": "410e902f01cdd324e4746e8017595be4fc357d6fc4cd6044f2f808a943d7eaf7", + "https://deno.land/std@0.152.0/http/_negotiation/encoding.ts": "f749c1d539d139af783e8a7741de5a47a98a5e3c9af82b8af512567ccf5fe632", + "https://deno.land/std@0.152.0/http/_negotiation/language.ts": "53c306186904d2dace4c624a8822542866ad332a7f40ac90e0af1504f95c63d0", + "https://deno.land/std@0.152.0/http/_negotiation/media_type.ts": "ecdda87286495f7ff25116858f5088856953e2f1585e593d314e0c71b826a137", + "https://deno.land/std@0.152.0/http/http_errors.ts": "fe9b7f95f7ee0592c3306f8c7aed03ba53d55d1ef81e00041c1171b9588f46d9", + "https://deno.land/std@0.152.0/http/http_status.ts": "897575a7d6bc2b9123f6a38ecbc0f03d95a532c5d92029315dc9f508e12526b8", + "https://deno.land/std@0.152.0/http/negotiation.ts": "f35b1ff2ad4ff9feaa00ac234960b398172768205c8eceaef7f2eafe34716ba2", + "https://deno.land/std@0.152.0/io/buffer.ts": "bd0c4bf53db4b4be916ca5963e454bddfd3fcd45039041ea161dbf826817822b", + "https://deno.land/std@0.152.0/io/readers.ts": "45847ad404afd2f605eae1cff193f223462bc55eeb9ae313c2f3db28aada0fd6", + "https://deno.land/std@0.152.0/io/types.d.ts": "0cae3a62da7a37043661746c65c021058bae020b54e50c0e774916e5d4baee43", + "https://deno.land/std@0.152.0/media_types/_util.ts": "ce9b4fc4ba1c447dafab619055e20fd88236ca6bdd7834a21f98bd193c3fbfa1", + "https://deno.land/std@0.152.0/media_types/mod.ts": "3829264ca0610cac40f3214f939d7733483523f82bc1041c51045d7c75fb93b8", + "https://deno.land/std@0.152.0/media_types/vendor/mime-db.v1.52.0.ts": "724cee25fa40f1a52d3937d6b4fbbfdd7791ff55e1b7ac08d9319d5632c7f5af", + "https://deno.land/std@0.152.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3", + "https://deno.land/std@0.152.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09", + "https://deno.land/std@0.152.0/path/_util.ts": "c1e9686d0164e29f7d880b2158971d805b6e0efc3110d0b3e24e4b8af2190d2b", + "https://deno.land/std@0.152.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633", + "https://deno.land/std@0.152.0/path/glob.ts": "cb5255638de1048973c3e69e420c77dc04f75755524cb3b2e160fe9277d939ee", + "https://deno.land/std@0.152.0/path/mod.ts": "56fec03ad0ebd61b6ab39ddb9b0ddb4c4a5c9f2f4f632e09dd37ec9ebfd722ac", + "https://deno.land/std@0.152.0/path/posix.ts": "c1f7afe274290ea0b51da07ee205653b2964bd74909a82deb07b69a6cc383aaa", + "https://deno.land/std@0.152.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9", + "https://deno.land/std@0.152.0/path/win32.ts": "bd7549042e37879c68ff2f8576a25950abbfca1d696d41d82c7bca0b7e6f452c", + "https://deno.land/std@0.152.0/streams/conversion.ts": "fc3db02026183da795fa32ac7549868e9f19c75ba029d4b4c3739af62b48517a", + "https://deno.land/std@0.152.0/testing/_diff.ts": "029a00560b0d534bc0046f1bce4bd36b3b41ada3f2a3178c85686eb2ff5f1413", + "https://deno.land/std@0.152.0/testing/_format.ts": "0d8dc79eab15b67cdc532826213bbe05bccfd276ca473a50a3fc7bbfb7260642", + "https://deno.land/std@0.152.0/testing/asserts.ts": "093735c88f52bbead7f60a1f7a97a2ce4df3c2d5fab00a46956f20b4a5793ccd", + "https://deno.land/std@0.162.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74", + "https://deno.land/std@0.162.0/_util/os.ts": "8a33345f74990e627b9dfe2de9b040004b08ea5146c7c9e8fe9a29070d193934", + "https://deno.land/std@0.162.0/fmt/colors.ts": "9e36a716611dcd2e4865adea9c4bec916b5c60caad4cdcdc630d4974e6bb8bd4", + "https://deno.land/std@0.162.0/fs/_util.ts": "fdc156f897197f261a1c096dcf8ff9267ed0ff42bd5b31f55053a4763a4bae3b", + "https://deno.land/std@0.162.0/fs/copy.ts": "73bdf24f4322648d9bc38ef983b818637ba368351d17aa03644209d3ce3eac31", + "https://deno.land/std@0.162.0/fs/empty_dir.ts": "c15a0aaaf40f8c21cca902aa1e01a789ad0c2fd1b7e2eecf4957053c5dbf707f", + "https://deno.land/std@0.162.0/fs/ensure_dir.ts": "76395fc1c989ca8d2de3aedfa8240eb8f5225cde20f926de957995b063135b80", + "https://deno.land/std@0.162.0/fs/ensure_file.ts": "b8e32ea63aa21221d0219760ba3f741f682d7f7d68d0d24a3ec067c338568152", + "https://deno.land/std@0.162.0/fs/ensure_link.ts": "5cc1c04f18487d7d1edf4c5469705f30b61390ffd24ad7db6df85e7209b32bb2", + "https://deno.land/std@0.162.0/fs/ensure_symlink.ts": "5273557b8c50be69477aa9cb003b54ff2240a336db52a40851c97abce76b96ab", + "https://deno.land/std@0.162.0/fs/eol.ts": "65b1e27320c3eec6fb653b27e20056ee3d015d3e91db388cfefa41616ebc7cb3", + "https://deno.land/std@0.162.0/fs/exists.ts": "6a447912e49eb79cc640adacfbf4b0baf8e17ede6d5bed057062ce33c4fa0d68", + "https://deno.land/std@0.162.0/fs/expand_glob.ts": "d3f62aefc7718d878904d60d91e8e6dbbf86c696d32b6cbbc333637acf7f8571", + "https://deno.land/std@0.162.0/fs/mod.ts": "354a6f972ef4e00c4dd1f1339a8828ef0764c1c23d3c0010af3fcc025d8655b0", + "https://deno.land/std@0.162.0/fs/move.ts": "6d7fa9da60dbc7a32dd7fdbc2ff812b745861213c8e92ba96dace0669b0c378c", + "https://deno.land/std@0.162.0/fs/walk.ts": "d96d4e5b6a3552e8304f28a0fd0b317b812298298449044f8de4932c869388a5", + "https://deno.land/std@0.162.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3", + "https://deno.land/std@0.162.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09", + "https://deno.land/std@0.162.0/path/_util.ts": "d16be2a16e1204b65f9d0dfc54a9bc472cafe5f4a190b3c8471ec2016ccd1677", + "https://deno.land/std@0.162.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633", + "https://deno.land/std@0.162.0/path/glob.ts": "cb5255638de1048973c3e69e420c77dc04f75755524cb3b2e160fe9277d939ee", + "https://deno.land/std@0.162.0/path/mod.ts": "56fec03ad0ebd61b6ab39ddb9b0ddb4c4a5c9f2f4f632e09dd37ec9ebfd722ac", + "https://deno.land/std@0.162.0/path/posix.ts": "6b63de7097e68c8663c84ccedc0fd977656eb134432d818ecd3a4e122638ac24", + "https://deno.land/std@0.162.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9", + "https://deno.land/std@0.162.0/path/win32.ts": "ee8826dce087d31c5c81cd414714e677eb68febc40308de87a2ce4b40e10fb8d", + "https://deno.land/std@0.162.0/testing/_diff.ts": "a23e7fc2b4d8daa3e158fa06856bedf5334ce2a2831e8bf9e509717f455adb2c", + "https://deno.land/std@0.162.0/testing/_format.ts": "cd11136e1797791045e639e9f0f4640d5b4166148796cad37e6ef75f7d7f3832", + "https://deno.land/std@0.162.0/testing/asserts.ts": "1e340c589853e82e0807629ba31a43c84ebdcdeca910c4a9705715dfdb0f5ce8", + "https://deno.land/x/another_cookiejar@v5.0.2/cookie.ts": "2be7548d01a3a9df97deb187761a843a77fd824057478919abf1e1e89ae1eb2e", + "https://deno.land/x/another_cookiejar@v5.0.2/cookie_jar.ts": "e47d7b2c608bcd9600fd26825b600946f16ae167216cea71935049188d2fc6d1", + "https://deno.land/x/another_cookiejar@v5.0.2/fetch_wrapper.ts": "4fbca1e77383cf7da4703798e06a1129b21120f4d01c3a4c0801674dd7b6d53b", + "https://deno.land/x/another_cookiejar@v5.0.2/mod.ts": "eff949014965771f2cd447fe78625a1ad28b59333afa40640f02c0922534d89a", + "https://deno.land/x/corfu@v2.0.1/mod.ts": "159efb94e08231a1f11abc6add4a15af299fd138f6469a7550cd96c628f7c10c", + "https://deno.land/x/corfu@v2.0.1/types.ts": "07e7123258ffed42e34f44ffe45a6e7f51658f60be3b8f456bf0dd775305355d", + "https://deno.land/x/denosass@1.0.6/mod.ts": "5e9c142055d658f3acb2b370d0b412c783ed4b27db830f387525fb7f69a7ab3d", + "https://deno.land/x/denosass@1.0.6/src/deps.ts": "cb5fa11799e3def8b593be3b5939d2755a2c7f1f4987f3af1bc4ad90922d3715", + "https://deno.land/x/denosass@1.0.6/src/mod.ts": "d2b63172f98238f77831995a5d6c8a06af5252ad8fbe7b9ec40b60eae86f2164", + "https://deno.land/x/denosass@1.0.6/src/types/module.types.ts": "7a5027482ded1d2967fbe690ef8f928446c5de8811c3333f9b09ae6e8122f9ba", + "https://deno.land/x/denosass@1.0.6/src/wasm/grass.deno.js": "a72432ce8d6b8f9c31e31c71415fdca03fe36aa22417e414bc81e2e21a8a687b", + "https://deno.land/x/nano_jsx@v0.0.34/component.ts": "6bd3dab67754e91308df863e11e2b7945bbe0bf575b4bc529e8a9e02087eb732", + "https://deno.land/x/nano_jsx@v0.0.34/components/helmet.ts": "59e598dc79c7b18620de175c61eb26f4aeb6905a6654cd63359208a26471541e", + "https://deno.land/x/nano_jsx@v0.0.34/components/img.ts": "82a9f830394a7d6cd9b789b48fe1e70bc64eb151c4b410a3da74347c06acdae0", + "https://deno.land/x/nano_jsx@v0.0.34/components/index.ts": "8855ee8302a9a19f38202d4a7ff5b17e22942600da02356bdfbc80c99c5c55f5", + "https://deno.land/x/nano_jsx@v0.0.34/components/link.ts": "0f0b1c57dc8c466203105062335e0d9ded89a34e75d08b1bbeece198d42021cb", + "https://deno.land/x/nano_jsx@v0.0.34/components/router.ts": "1feb8b6881641a18a3bdd937089b3f5a7b9f36948f8178a85acde7e4c9294a6d", + "https://deno.land/x/nano_jsx@v0.0.34/components/suspense.ts": "0711b7cdcd42b0b085972eca796d3ba7c436a736e1d2ce17db7e0cd1d3b928f5", + "https://deno.land/x/nano_jsx@v0.0.34/components/visible.ts": "f19487f7faff0bad38a5549f1efac1df351e83ee4a77ca5886412b439f4b6b53", + "https://deno.land/x/nano_jsx@v0.0.34/context.ts": "a65018beedf3e1863b96f9d99cf2d471c231a6ae0c77877a77754a398105f9fc", + "https://deno.land/x/nano_jsx@v0.0.34/core.ts": "d45b13ecc3a6739e22b30f48c9f021cb8373e2b462f39ac5b15389bdf3d692be", + "https://deno.land/x/nano_jsx@v0.0.34/customElementsMode.ts": "f5446d3c3afe803a7f97a3434d3970e662f5d0635db79b0e4010e2972ff66a6e", + "https://deno.land/x/nano_jsx@v0.0.34/fragment.ts": "9cfb0dcdcb02d5cc53f027b4b55609e4f9d6d9322b665292e572856f4b688569", + "https://deno.land/x/nano_jsx@v0.0.34/helpers.ts": "d904aa646534f1c0cf7c05a6c8e02231f906d962acb725c964aedbcf50216d85", + "https://deno.land/x/nano_jsx@v0.0.34/htm.ts": "d8d9cd4fb4ad4645bff3698c7eb96e7798022c5519d04e709ebde236edde156b", + "https://deno.land/x/nano_jsx@v0.0.34/htm/build.ts": "9d6b6eb407c0db2d1213a3f9c82efc66a2bec34c89976132ff13e3e095dcaaaf", + "https://deno.land/x/nano_jsx@v0.0.34/htm/constants.ts": "3f296f87f03bd0ba8d7673884a1f6c4c927a2774648eaa4fd3ca9e3c46c3f7b8", + "https://deno.land/x/nano_jsx@v0.0.34/htm/index.ts": "29912b9f7a760884fce79caca82649b9772cfa3c3272e0426a4ce377b67d70d5", + "https://deno.land/x/nano_jsx@v0.0.34/index.ts": "0f39c911a39c61cb39f9bd8a2481500126dcb1b2a826d5b4523dd47a08b6938d", + "https://deno.land/x/nano_jsx@v0.0.34/jsx.ts": "7d5b4d4a249fba1a42f2016f54f71ca049d96ff490e098db4a19b2a9b197b952", + "https://deno.land/x/nano_jsx@v0.0.34/lazy.ts": "f8b8a2b915daff1fb70704ffad5171c805f1e28778b5cd0f8c827780762776c4", + "https://deno.land/x/nano_jsx@v0.0.34/mod.ts": "3dda2bc0dbee9abd01c03acf43ab55a7854952afe0450245fc2ad12eb9bd9598", + "https://deno.land/x/nano_jsx@v0.0.34/regexDom.ts": "de82fd3110c5a367e3d4ba9b774cfef3baf995deff455edc7363551d79089c90", + "https://deno.land/x/nano_jsx@v0.0.34/ssr.ts": "8f77228a7ed13990deba0c1a69d7d3f2902c837b62d24f5b7a019f84c96ad234", + "https://deno.land/x/nano_jsx@v0.0.34/state.ts": "cfc6ca6eb5e65f4cd60717a0a96ce604053bacf6e0b8835afbe22327e9979a1b", + "https://deno.land/x/nano_jsx@v0.0.34/store.ts": "653e8c53d6ed4e410c76b1a7a044aa7cc71ff00fb3af9f3a94253591b5f4dcea", + "https://deno.land/x/nano_jsx@v0.0.34/types.ts": "fb338d7fa4422a92c442d14e073a2deb01d42b017fcd36013a1f6554e17c5449", + "https://deno.land/x/nano_jsx@v0.0.34/version.ts": "30412f1a0cdd968633a760c456d96e83196ee72ca66cfebe1e526d66c7758ebe", + "https://deno.land/x/nano_jsx@v0.0.34/withStyles.ts": "8aae4c8e79319fe991d49dd8ccc927c221786dfe58de640dba9d9885ce0dd4b7", + "https://deno.land/x/oak@v11.1.0/application.ts": "0a728331822b8e27727ceec48a8499657c3163fc48fd379a8a9578a75f3cdb62", + "https://deno.land/x/oak@v11.1.0/body.ts": "78402a4936accb80372c4944384658105604352d6783de7ff1e36b8832dd93c9", + "https://deno.land/x/oak@v11.1.0/buf_reader.ts": "7cf96aa0ac670b75098113cf88a291a68332cc45efa8a9698f064ac5b8098a0f", + "https://deno.land/x/oak@v11.1.0/content_disposition.ts": "8b8c3cb2fba7138cd5b7f82fc3b5ea39b33db924a824b28261659db7e164621e", + "https://deno.land/x/oak@v11.1.0/context.ts": "014d1ce40e62a7901411425541b0d5a08018968a330595bd686f8d00222a35bb", + "https://deno.land/x/oak@v11.1.0/cookies.ts": "d9f94b99f26c6169c6982ce12323c41a548d001bfc28f464264c22dc3dbf2181", + "https://deno.land/x/oak@v11.1.0/deps.ts": "b897b0f2bec99cd8b402b279b7f21de955d98cbd72835b6c912be5e11c26148b", + "https://deno.land/x/oak@v11.1.0/etag.ts": "19918f5e1964e3fe6c9fe524a88ffbf9900ce1dfe4146b187b2a86256bb6b663", + "https://deno.land/x/oak@v11.1.0/headers.ts": "f50fb05614432bda971021633129aa2e8737e0844e0f01c27a937997b4d8dd4f", + "https://deno.land/x/oak@v11.1.0/helpers.ts": "42212afa07a560b2958359cc19577417e89d9574d6579551a0af36ff7f00cc6e", + "https://deno.land/x/oak@v11.1.0/http_request.ts": "0831c828816fcb58a5aa8361c6865c4151f4c8b59fabcef2e2cd235bb28170c5", + "https://deno.land/x/oak@v11.1.0/http_server_flash.ts": "e312754acad26d3d70f243d657547e697921f67f0a2179dbec41a20a3228fd79", + "https://deno.land/x/oak@v11.1.0/http_server_native.ts": "549dffcd2db5cbb0e44ad50cf9c54956b42a10450b1ac66e1362e32a073c8c1b", + "https://deno.land/x/oak@v11.1.0/http_server_native_request.ts": "07910ea2ed51af6c4e69addf9015cdd8d2b5c9ee03fd4993e386834a129a9eb6", + "https://deno.land/x/oak@v11.1.0/isMediaType.ts": "62d638abcf837ece3a8f07a4b7ca59794135cb0d4b73194c7d5837efd4161005", + "https://deno.land/x/oak@v11.1.0/keyStack.ts": "fa0d5898fb8ba34de1c9cdcf4b2e8434952dc9931671858d33560368784a22ef", + "https://deno.land/x/oak@v11.1.0/mediaTyper.ts": "042b853fc8e9c3f6c628dd389e03ef481552bf07242efc3f8a1af042102a6105", + "https://deno.land/x/oak@v11.1.0/middleware.ts": "de14f045a2ddfe845d89b5d3140ff52cbcc6f3b3965391106ce04480f9786737", + "https://deno.land/x/oak@v11.1.0/middleware/proxy.ts": "b927232f97ec18af4185d7912e45b1191e3ffe24a9c875262ad524211b1274c9", + "https://deno.land/x/oak@v11.1.0/mod.ts": "de52855c8f626e30ba683fb265c0a0773ba2f5f117b3549b7d9c857edba58338", + "https://deno.land/x/oak@v11.1.0/multipart.ts": "98fe9f226de8c26a16d067027b69fb1e34ad8c4055767dd157907d06cea36f9a", + "https://deno.land/x/oak@v11.1.0/range.ts": "68a6df7ab3b868843e33f52deb94c3d4cab25cb9ef369691990c2ac15b04fafb", + "https://deno.land/x/oak@v11.1.0/request.ts": "5852ad36389b48e0428a6f3c90854d01f10d1b15949b56001e1e75c2a00ef0f9", + "https://deno.land/x/oak@v11.1.0/response.ts": "867d81f7eb0c65c7b8e0e0e9e145ededd5b6daa9ad922e6adc6a36a525f439a6", + "https://deno.land/x/oak@v11.1.0/router.ts": "187522a549f6c179ff01d321882a8bfacbfb7f3e24b004ec4534a3613c7f9b0e", + "https://deno.land/x/oak@v11.1.0/send.ts": "7ef2591792426d62add91536bb434566d4b224247ca343fdd63e486f9d4e9446", + "https://deno.land/x/oak@v11.1.0/server_sent_event.ts": "948b0fe4cb3fe38c7db15e476eb3b7671ef20e566d130e9f701d7c0146aa47dd", + "https://deno.land/x/oak@v11.1.0/structured_clone.ts": "ecf42598652b8082f37252cb873d6e257ad728e6fe73c6bd61f343d94501fbde", + "https://deno.land/x/oak@v11.1.0/testing.ts": "7612656efd2975f7a2e6848609f5971922dbec46b76372c5c623202fdd7b9a85", + "https://deno.land/x/oak@v11.1.0/types.d.ts": "41951a18c3bfdb11e40707cab75da078ba8a4907cd7d4e11d8536bc2db0dde05", + "https://deno.land/x/oak@v11.1.0/util.ts": "3af8c4ed04c6cc2bedbe66e562a77fc59c72df31c55a902a63885861ca1639d6", + "https://deno.land/x/path_to_regexp@v6.2.1/index.ts": "894060567837bae8fc9c5cbd4d0a05e9024672083d5883b525c031eea940e556", + "https://deno.land/x/wattpad@v0.0.2/mod.ts": "d54c086bf37daeca54270bc88c4de87d02d583a5dda607df3c3e3de2a857a0d4", + "https://deno.land/x/wattpad@v0.0.2/src/classes/Chapter.ts": "a45b2bdf70e04a58e05edfba6634e4089e85eda3c1551be05dcd0989648fc0a9", + "https://deno.land/x/wattpad@v0.0.2/src/classes/Search.ts": "3a7c05c449978c822448aa80f2a29d4fccc7040ade9aa0d848b9a8341a79b3fe", + "https://deno.land/x/wattpad@v0.0.2/src/classes/Story.ts": "b3fb3dfecb0cd533e614cab1440abf3716e02dd9485015df28bce4624e57cbcd", + "https://deno.land/x/wattpad@v0.0.2/src/classes/TagSearch.ts": "1783267b203879b9ce862541b6770918cda10d64830a5007ab7d75233838e6b5", + "https://deno.land/x/wattpad@v0.0.2/src/classes/Wattpad.ts": "8aca689c2f958fdecf3f7586563753fc4cddd783c5f0d7dadb8b17d5ba3bac91", + "https://deno.land/x/wattpad@v0.0.2/src/types.d.ts": "fe933b610694544ffd9ade8a94aa555c82abaedf293faf5aa61f6ab6d1ee44f8", + "https://deno.land/x/wattpad@v0.0.2/src/utils/http.ts": "9fc657974c7c5e91f09bb8af20197d59efab91a78ad4011080f4f0e6f442c31d", + "https://deno.land/x/wattpad@v0.0.3/mod.ts": "dbf3bb1b3e10f5707bc6879bdd62db6e0618fd1786a5bed3374c2f7ffe1a6d2b", + "https://deno.land/x/wattpad@v0.0.3/src/classes/Chapter.ts": "00b6097f5ffce2b44a24432fc62be324bf11a80327e2975eb115bc2e7410369c", + "https://deno.land/x/wattpad@v0.0.3/src/classes/Search.ts": "36126f10a147231aaf27ad9626a27f7e6f42b157cd89225f74cfc4f9a3b7051a", + "https://deno.land/x/wattpad@v0.0.3/src/classes/Story.ts": "e9c679f2201cf63a5f061cd535176d6c50569d3637c99cb2a3560e98ee923bbf", + "https://deno.land/x/wattpad@v0.0.3/src/classes/TagSearch.ts": "fd73b16e250a29f0b14c809cead6d22ff7703d415078956126787095b0d4ebf7", + "https://deno.land/x/wattpad@v0.0.3/src/classes/Wattpad.ts": "8aca689c2f958fdecf3f7586563753fc4cddd783c5f0d7dadb8b17d5ba3bac91", + "https://deno.land/x/wattpad@v0.0.3/src/types.d.ts": "fe933b610694544ffd9ade8a94aa555c82abaedf293faf5aa61f6ab6d1ee44f8", + "https://deno.land/x/wattpad@v0.0.3/src/utils/http.ts": "9fc657974c7c5e91f09bb8af20197d59efab91a78ad4011080f4f0e6f442c31d", + "https://deno.land/x/wattpad@v0.0.4/mod.ts": "3248de35fff8b8b15bf848e9fc5469776608142bd4543177fd8b292d6e7d09c9", + "https://deno.land/x/wattpad@v0.0.4/src/classes/Chapter.ts": "00b6097f5ffce2b44a24432fc62be324bf11a80327e2975eb115bc2e7410369c", + "https://deno.land/x/wattpad@v0.0.4/src/classes/Search.ts": "36126f10a147231aaf27ad9626a27f7e6f42b157cd89225f74cfc4f9a3b7051a", + "https://deno.land/x/wattpad@v0.0.4/src/classes/Story.ts": "e9c679f2201cf63a5f061cd535176d6c50569d3637c99cb2a3560e98ee923bbf", + "https://deno.land/x/wattpad@v0.0.4/src/classes/TagSearch.ts": "fd73b16e250a29f0b14c809cead6d22ff7703d415078956126787095b0d4ebf7", + "https://deno.land/x/wattpad@v0.0.4/src/classes/Wattpad.ts": "ce67ad71a4250232818473807da6a687f71772c9d142154a431b46b73201a11e", + "https://deno.land/x/wattpad@v0.0.4/src/types.d.ts": "fe933b610694544ffd9ade8a94aa555c82abaedf293faf5aa61f6ab6d1ee44f8", + "https://deno.land/x/wattpad@v0.0.4/src/utils/http.ts": "50e18486856ec16878f780af0a4cfe9850a69590de62d48f7ec5e74d602d20e7", + "https://raw.githubusercontent.com/kt3k/callsites/v1.0.0/mod.ts": "a5fdfa7916d03459fd4830ca526d493d5f4ce0ea91619905d524c9a3a5c3cd15", + "https://raw.githubusercontent.com/nomyTx/gas/bef3e8b8b51a9929b915b3e13df07290a37832ba/jsx.ts": "adf05a2478b48bc0c1e4e18db87c7c03d0894e3751be99571c3e63375471d5d3" + }, + "npm": { + "specifiers": { "@connorskees/grass": "@connorskees/grass@0.12.0" }, + "packages": { + "@connorskees/grass@0.12.0": { + "integrity": "sha512-nDICkb3SxivBAteLuUsosUk0EsB0qQW2hBtnkhFP0dP/yAV1zcrq4p38O12/Mw+Yt1DKTqQSyCZAoliaK/kw4g==", + "dependencies": {} + } + } + } +} diff --git a/index.tsx b/index.tsx new file mode 100644 index 0000000..3b44555 --- /dev/null +++ b/index.tsx @@ -0,0 +1,71 @@ +import { h } from "https://deno.land/x/corfu@v2.0.1/mod.ts"; + +import { Application, Router } from "https://deno.land/x/oak@v11.1.0/mod.ts"; +import config from "./config.ts"; + +const app = new Application(); +//print info on listen +app.addEventListener("listen", (event) => { + console.log( + `voltpad listening on http://${event.hostname.replace( + "::1", + "localhost" + )}:${event.port}` + ); +}); + +app.use(async (ctx) => { + if (ctx.request.url.pathname === "/") ctx.request.url.pathname = "/index"; + let mod; + try { + mod = await import( + "./routes" + + ctx.request.url.pathname + + ".tsx" + + `?update=${Date.now()}` + ); + } catch { + try { + return await ctx.send({ + root: `./static`, + index: `${ctx.request.url.pathname}` + }); + } catch { + mod = await import("./routes/404.tsx"); + } + } + let rizz; + try { + rizz = await mod.default(ctx.request.url.searchParams); + } catch (e) { + console.error(e); + mod = await import("./routes/500.tsx"); + rizz = await mod.default(); + } + ctx.response.body = "" + rizz; +}); + +//(attempt to) set mimetype +app.use(async (ctx, next) => { + await next(); + if (!ctx.response.headers.get("Content-Type")) { + switch (ctx.request.url.pathname.split(".").at(-1)) { + case "json": + ctx.response.headers.set("Content-Type", "application/json"); + break; + default: + ctx.response.headers.set("Content-Type", "text/html"); + } + } +}); + +app.use(async (ctx, next) => { + await next(); + const rt = ctx.response.headers.get("X-Response-Time"); + console.log(`${ctx.request.method} ${ctx.request.url} - ${rt}`); +}); + +await app.listen({ + hostname: config.serve.address, + port: config.serve.port +}); diff --git a/jsx.ts b/jsx.ts new file mode 100644 index 0000000..b481d11 --- /dev/null +++ b/jsx.ts @@ -0,0 +1 @@ +export * from "https://deno.land/x/corfu@v2.0.1/mod.ts"; diff --git a/oak.ts b/oak.ts new file mode 100644 index 0000000..82eb028 --- /dev/null +++ b/oak.ts @@ -0,0 +1 @@ +export * from "https://deno.land/x/oak@v11.1.0/mod.ts"; diff --git a/routes/404.tsx b/routes/404.tsx new file mode 100644 index 0000000..74bef58 --- /dev/null +++ b/routes/404.tsx @@ -0,0 +1,12 @@ +import { h } from "../jsx.ts"; + +import Base from "../templates/Base.tsx"; + +export default () => ( + +
+

404

+

Page not found.

+
+ +); diff --git a/routes/500.tsx b/routes/500.tsx new file mode 100644 index 0000000..4353395 --- /dev/null +++ b/routes/500.tsx @@ -0,0 +1,12 @@ +import { h } from "../jsx.ts"; + +import Base from "../templates/Base.tsx"; + +export default () => ( + +
+

500

+

Internal server error.

+
+ +); diff --git a/routes/index.tsx b/routes/index.tsx new file mode 100644 index 0000000..d043e03 --- /dev/null +++ b/routes/index.tsx @@ -0,0 +1,12 @@ +import { h } from "../jsx.ts"; + +import Base from "../templates/Base.tsx"; + +export default () => ( + +
+

Voltpad

+

A blazingly fast (🚀) Wattpad frontend

+
+ +); diff --git a/routes/search.tsx b/routes/search.tsx new file mode 100644 index 0000000..1026e04 --- /dev/null +++ b/routes/search.tsx @@ -0,0 +1,133 @@ +import { h } from "../jsx.ts"; +import watt, { watt as originalWatt } from "../wattpad.ts"; +import Base from "../templates/Base.tsx"; + +function search() { + console.log(document.getElementById("query")); +} + +export default async (params: URLSearchParams) => { + const res = []; + if (params.get("query") && params.get("type")) { + const search = originalWatt[ + params.get("type") === "tag" ? "tagSearch" : "search" + ]({ + tags: (params.get("query") as string).split(","), + query: params.get("query") as string, + isTitle: params.get("type") === "title", + limit: 20 + }); + await search.update(Number(params.get("page") ?? 0)); + for (let i = 0; i < search.results.length; i++) { + const rizz = await watt.getStory(search.results[i].id, false); + res.push( + + +
+

{rizz.name}

+

{rizz.storyJSON.description}

+
+
+ ); + } + } + return ( + + {/* TODO: impl autocomplete for tags? */} +
+
+ + + + + + + +
+ +
+ +
+ {res.join("")} + +
+ + ); +}; diff --git a/routes/story.tsx b/routes/story.tsx new file mode 100644 index 0000000..0b0cd2d --- /dev/null +++ b/routes/story.tsx @@ -0,0 +1,100 @@ +import { h } from "../jsx.ts"; + +import Story from "../templates/Story.tsx"; +import watt from "../wattpad.ts"; +import FourOhFour from "./404.tsx"; + +export default async (params: URLSearchParams) => { + if (!params.get("id")) return ; + + const story = await watt.getStory(params.get("id") as string); + + // chapters + if (params.get("chapter")) { + await story.chapters[Number(params.get("chapter") as string)].init(); + return ( + +
+ { + story.chapters[Number(params.get("chapter") as string)] + .html + } +
+ +
+ ); + } + // metadata + else { + return ( + +
+
+ +
+

{story.name}

+

{story.storyJSON.description}

+
+
+
+ {story.tags + .map((v) => ( +
+ + #{v} + +
+
+ )) + .join("")} +
+
+ + ); + } +}; diff --git a/static/android-chrome-192x192.png b/static/android-chrome-192x192.png new file mode 100644 index 0000000..5a01b16 Binary files /dev/null and b/static/android-chrome-192x192.png differ diff --git a/static/android-chrome-512x512.png b/static/android-chrome-512x512.png new file mode 100644 index 0000000..682933f Binary files /dev/null and b/static/android-chrome-512x512.png differ diff --git a/static/apple-touch-icon.png b/static/apple-touch-icon.png new file mode 100644 index 0000000..8b76383 Binary files /dev/null and b/static/apple-touch-icon.png differ diff --git a/static/browserconfig.xml b/static/browserconfig.xml new file mode 100644 index 0000000..f9c2e67 --- /dev/null +++ b/static/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #2b5797 + + + diff --git a/static/favicon-16x16.png b/static/favicon-16x16.png new file mode 100644 index 0000000..5312ad9 Binary files /dev/null and b/static/favicon-16x16.png differ diff --git a/static/favicon-32x32.png b/static/favicon-32x32.png new file mode 100644 index 0000000..3a62952 Binary files /dev/null and b/static/favicon-32x32.png differ diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000..f62dcb7 Binary files /dev/null and b/static/favicon.ico differ diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000..045690c Binary files /dev/null and b/static/favicon.png differ diff --git a/static/mstile-150x150.png b/static/mstile-150x150.png new file mode 100644 index 0000000..c1c7522 Binary files /dev/null and b/static/mstile-150x150.png differ diff --git a/static/safari-pinned-tab.svg b/static/safari-pinned-tab.svg new file mode 100644 index 0000000..8a91912 --- /dev/null +++ b/static/safari-pinned-tab.svg @@ -0,0 +1,36 @@ + + + + +Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + + + diff --git a/static/site.webmanifest b/static/site.webmanifest new file mode 100644 index 0000000..cec5a59 --- /dev/null +++ b/static/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "Voltpad", + "short_name": "Voltpad", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/templates/Base.tsx b/templates/Base.tsx new file mode 100644 index 0000000..961adf2 --- /dev/null +++ b/templates/Base.tsx @@ -0,0 +1,74 @@ +import sass from "https://deno.land/x/denosass@1.0.6/mod.ts"; +import { h, PropsWithChildren } from "../jsx.ts"; + +import Header from "../components/Header.tsx"; + +interface TemplateProps { + title: string; + description: string; + style?: string; + stylepath?: string; +} + +export default (props: PropsWithChildren) => ( + + + + + + {/* favicon stuff generated with https://realfavicongenerator.net */} + + + + + + + + + + + {props.title} | Voltpad + {(() => { + if (!props.style) props.style = ""; + if (props.stylepath) + props.style += Deno.readTextFileSync(props.stylepath); + else return
; + return ; + })()} + +
+
{props.children}
+ +); diff --git a/templates/Story.tsx b/templates/Story.tsx new file mode 100644 index 0000000..cfaf401 --- /dev/null +++ b/templates/Story.tsx @@ -0,0 +1,69 @@ +import sass from "https://deno.land/x/denosass@1.0.6/mod.ts"; +import { Story } from "../wattpad.ts"; +import { h, PropsWithChildren } from "../jsx.ts"; + +import Header from "../components/Header.tsx"; + +interface StoryProps { + story: Story; + style?: string; + stylepath?: string; +} + +export default (props: PropsWithChildren) => ( + + + + + + {/* favicon stuff generated with https://realfavicongenerator.net */} + + + + + + + + + + + {props.story.name} + {(() => { + if (!props.style) props.style = ""; + if (props.stylepath) + props.style += Deno.readTextFileSync(props.stylepath); + else return
; + return ; + })()} + +
({ + name: ch.name, + href: `/story?id=${ch.workID}&chapter=${i}` + }))} + >
+
{props.children}
+ +); diff --git a/types.d.ts b/types.d.ts new file mode 100644 index 0000000..aa3f8b5 --- /dev/null +++ b/types.d.ts @@ -0,0 +1,7 @@ +export interface Props { + [key: string]: any; +} + +export interface PropsWithChildren extends Props { + children: any; +} diff --git a/wattpad.ts b/wattpad.ts new file mode 100644 index 0000000..511deab --- /dev/null +++ b/wattpad.ts @@ -0,0 +1,59 @@ +export * from "https://deno.land/x/wattpad@v0.0.4/mod.ts"; +import Wattpad, { Story } from "https://deno.land/x/wattpad@v0.0.4/mod.ts"; +import config from "./config.ts"; + +const watt = new Wattpad(); +if (config.user) { + await watt.authenticate( + config.user.username, + config.user.password, + ); +} + +const cache: { + [k: string]: { + story: Story; + timestamp: Date; + }; +} = {}; + +// re-init oldest story in cache every 5 minutes +setInterval(() => { + const oldStory = Object.values(cache).sort((a, b) => + // @ts-expect-error 2363; javascript is a disgrace but it makes sorting dates easy so ¯\_(ツ)_/¯ + b.timestamp - a.timestamp + ).pop(); // teehee + if (!oldStory) return; + cache[oldStory.story.id].timestamp = new Date(); + cache[oldStory.story.id].story.init().then(async (_) => { + for ( + let i = 0; + i < cache[oldStory.story.id].story.chapters.length; + i++ + ) { + await cache[oldStory.story.id].story.chapters[i].init(); + } + }); +}, 300000); + +export { watt }; + +export default { + search: watt.search, + tagSearch: watt.tagSearch, + async getStory(id: string, initChapters = true): Promise { + if (!cache[id]) { + cache[id] = { + story: watt.getStory(id), + timestamp: new Date(), + }; + await cache[id].story.init(); + if (initChapters) { + for (let i = 0; i < cache[id].story.chapters.length; i++) { + await cache[id].story.chapters[i].init(); + } + } + } + return cache[id].story; + }, +};