initial commit

master
Drake 1 year ago
commit 317a0f972c

1
.gitignore vendored

@ -0,0 +1 @@
config.ts

@ -0,0 +1,6 @@
{
"deno.enable": true,
"deno.unstable": true,
"deno.importMap": "./import_map.json",
"editor.formatOnSave": true
}

@ -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.

@ -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

@ -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) => (
<header id={props.id} class="header">
{props.entries
.map((entry) => <a href={entry.href}>{entry.name}</a>)
.join("")}
</header>
);

@ -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;

@ -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;
}
}

@ -0,0 +1,12 @@
{
"fmt": {
"options": {
"indentWidth": 4
}
},
"compilerOptions": {
"jsxFactory": "h",
"jsxFragmentFactory": "Fragment",
"lib": ["dom", "deno.window"]
}
}

@ -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": {}
}
}
}
}

@ -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 = "<!DOCTYPE html>" + 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
});

@ -0,0 +1 @@
export * from "https://deno.land/x/corfu@v2.0.1/mod.ts";

@ -0,0 +1 @@
export * from "https://deno.land/x/oak@v11.1.0/mod.ts";

@ -0,0 +1,12 @@
import { h } from "../jsx.ts";
import Base from "../templates/Base.tsx";
export default () => (
<Base title="Home" description="The homepage." stylepath="css/index.scss">
<div style="text-align:center;">
<h1>404</h1>
<p>Page not found.</p>
</div>
</Base>
);

@ -0,0 +1,12 @@
import { h } from "../jsx.ts";
import Base from "../templates/Base.tsx";
export default () => (
<Base title="Home" description="The homepage." stylepath="css/index.scss">
<div style="text-align:center;">
<h1>500</h1>
<p>Internal server error.</p>
</div>
</Base>
);

@ -0,0 +1,12 @@
import { h } from "../jsx.ts";
import Base from "../templates/Base.tsx";
export default () => (
<Base title="Home" description="The homepage." stylepath="css/index.scss">
<div style="text-align: center;">
<h1>Voltpad</h1>
<p>A blazingly fast (🚀) Wattpad frontend</p>
</div>
</Base>
);

@ -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(
<a href={"/story?id=" + rizz.id} class="story">
<img src={rizz.storyJSON.cover} />
<div>
<h3>{rizz.name}</h3>
<p>{rizz.storyJSON.description}</p>
</div>
</a>
);
}
}
return (
<Base
title="Search"
description="The homepage."
stylepath="css/index.scss"
>
{/* TODO: impl autocomplete for tags? */}
<form
method="GET"
style="display:flex;flex-direction:column;align-items:center;justify-content:center;"
>
<div>
<input
id="query"
type="text"
name="query"
placeholder="Query"
style="margin-top: 0.5em;"
value={params.get("query") ?? ""}
autocomplete="off"
/>
<input
type="radio"
id="normal"
name="type"
value="text"
checked={
params.get("type") === "text" || !params.get("type")
}
/>
<label for="id">Text search</label>
<input
type="radio"
id="title"
name="type"
value="title"
checked={params.get("type") === "title"}
/>
<label for="title">Title search</label>
<input
type="radio"
id="tag"
name="type"
value="tag"
checked={params.get("type") === "tag"}
/>
<label for="tag">Tag search</label>
</div>
<input
style="margin-top:0.25em;"
type="submit"
value="Submit"
/>
</form>
<div id="stories" class="stories">
{res.join("")}
<div class="pagenav">
{Number(params.get("page") ?? 0) === 0 ? undefined : (
<a
href={(() => {
// total and utter jank
params.set(
"page",
(Number(params.get("page")) - 1).toString()
);
const strParams = params.toString();
params.set(
"page",
(Number(params.get("page")) + 1).toString()
);
return "/search?" + strParams.toString();
})()}
>
&lt;
</a>
)}
{params.get("query") && params.get("type") ? (
<div>&nbsp;|&nbsp;</div>
) : undefined}
{res.length !== 20 &&
(res.length as number) !== 19 ? undefined : (
<a
href={(() => {
const tmpParams = params;
tmpParams.set(
"page",
(Number(params.get("page")) + 1).toString()
);
return "/search?" + tmpParams.toString();
})()}
>
&gt;
</a>
)}
</div>
</div>
</Base>
);
};

@ -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 <FourOhFour />;
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 story={story} stylepath="css/index.scss">
<div style="margin-left: 1em; margin-right: 1em;">
{
story.chapters[Number(params.get("chapter") as string)]
.html
}
</div>
<div class="pagenav">
{Number(params.get("chapter") ?? 0) === 0 ? undefined : (
<a
href={(() => {
// total and utter jank
params.set(
"chapter",
(
Number(params.get("chapter")) - 1
).toString()
);
const strParams = params.toString();
params.set(
"chapter",
(
Number(params.get("chapter")) + 1
).toString()
);
return "/story?" + strParams.toString();
})()}
>
&lt;
</a>
)}
&nbsp;|&nbsp;
{story.chapters.length <
Number(params.get("chapter")) ? undefined : (
<a
href={(() => {
const tmpParams = params;
tmpParams.set(
"chapter",
(
Number(params.get("chapter")) + 1
).toString()
);
return "/story?" + tmpParams.toString();
})()}
>
&gt;
</a>
)}
</div>
</Story>
);
}
// metadata
else {
return (
<Story story={story} stylepath="css/index.scss">
<div style="display:flex;align-items:center;justify-content:center;flex-direction:column;">
<div class="story">
<img src={story.storyJSON.cover} />
<div>
<h3>{story.name}</h3>
<p>{story.storyJSON.description}</p>
</div>
</div>
<div style="display:flex;flex-wrap:wrap;align-items:center;justify-content:center;flex-direction:row;margin-top: 0.5em;text-align:center;">
{story.tags
.map((v) => (
<div>
<a
href={`/search?query=${v}&type=tag`}
style="background-color:darkgrey; border-radius: 0.3em; padding: 0.1em; margin-right: 0.5em;border: none;outline: none;text-decoration: none;"
>
#{v}
</a>
<div style="margin-top: 0.5em;" />
</div>
))
.join("")}
</div>
</div>
</Story>
);
}
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#2b5797</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

@ -0,0 +1,36 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M284 4886 c-88 -41 -134 -129 -134 -254 0 -71 22 -162 139 -577 35
-121 75 -269 91 -330 29 -111 34 -133 115 -435 43 -163 91 -354 160 -645 20
-82 42 -177 50 -210 8 -33 26 -123 40 -200 64 -366 77 -437 95 -530 25 -127
70 -366 105 -560 15 -82 47 -249 71 -370 24 -121 48 -258 54 -305 24 -199 135
-300 328 -300 60 0 88 5 129 24 146 68 216 208 179 357 -15 58 -15 72 -2 134
45 212 172 630 286 945 108 298 230 659 279 825 76 259 195 721 242 937 6 32
15 55 19 53 4 -3 10 -42 14 -87 9 -99 41 -373 61 -513 7 -55 19 -138 25 -185
7 -47 23 -150 36 -230 13 -80 30 -192 39 -250 8 -58 28 -190 44 -295 58 -377
112 -733 132 -864 27 -185 62 -350 110 -516 22 -77 44 -164 49 -194 18 -106
86 -192 188 -237 137 -62 284 -9 367 131 29 48 228 611 319 901 36 115 107
328 157 474 50 146 130 382 179 525 49 143 143 420 210 615 209 609 250 732
274 830 67 263 114 435 173 630 36 118 77 251 90 295 31 102 29 235 -5 301
-62 121 -205 167 -329 107 -64 -32 -99 -71 -149 -167 -66 -129 -138 -363 -179
-579 -52 -282 -106 -493 -230 -892 -14 -44 -50 -161 -80 -260 -63 -205 -79
-255 -165 -525 -34 -107 -75 -238 -91 -290 -70 -222 -362 -1100 -366 -1096 -4
4 -81 407 -128 676 -18 107 -56 321 -83 475 -62 348 -75 432 -107 670 -14 105
-27 201 -30 215 -2 14 -9 72 -15 130 -89 883 -151 1285 -221 1422 -54 106
-127 158 -221 158 -109 0 -195 -86 -303 -305 -101 -203 -197 -486 -294 -870
-22 -88 -43 -169 -46 -180 -78 -306 -244 -935 -275 -1040 -23 -77 -56 -192
-75 -255 -46 -159 -77 -256 -147 -465 -33 -99 -62 -186 -64 -194 -3 -8 -7 -12
-9 -9 -8 8 -50 230 -130 683 -8 44 -34 188 -59 320 -25 132 -50 267 -56 300
-38 203 -118 585 -155 740 -155 644 -277 1080 -336 1196 -25 50 -70 105 -110
134 -59 43 -176 48 -255 11z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@ -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"
}

@ -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<TemplateProps>) => (
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
{/* favicon stuff generated with https://realfavicongenerator.net */}
<link
rel="apple-touch-icon"
sizes="180x180"
href="/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/favicon-16x16.png"
/>
<link rel="manifest" href="/site.webmanifest" />
<link
rel="mask-icon"
href="/safari-pinned-tab.svg"
color="#5bbad5"
/>
<meta name="apple-mobile-web-app-title" content="Voltpad" />
<meta name="application-name" content="Voltpad" />
<meta name="msapplication-TileColor" content="#2b5797" />
<meta name="theme-color" content="#ffffff" />
<title>{props.title} | Voltpad</title>
{(() => {
if (!props.style) props.style = "";
if (props.stylepath)
props.style += Deno.readTextFileSync(props.stylepath);
else return <div></div>;
return <style>{sass(props.style).to_string()}</style>;
})()}
</head>
<Header
entries={[
{
name: "Home",
href: "/"
},
{
name: "Search",
href: "/search"
}
]}
></Header>
<div class="main">{props.children}</div>
</html>
);

@ -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<StoryProps>) => (
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
{/* favicon stuff generated with https://realfavicongenerator.net */}
<link
rel="apple-touch-icon"
sizes="180x180"
href="/apple-touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/favicon-16x16.png"
/>
<link rel="manifest" href="/site.webmanifest" />
<link
rel="mask-icon"
href="/safari-pinned-tab.svg"
color="#5bbad5"
/>
<meta name="apple-mobile-web-app-title" content="Voltpad" />
<meta name="application-name" content="Voltpad" />
<meta name="msapplication-TileColor" content="#2b5797" />
<meta name="theme-color" content="#ffffff" />
<title>{props.story.name}</title>
{(() => {
if (!props.style) props.style = "";
if (props.stylepath)
props.style += Deno.readTextFileSync(props.stylepath);
else return <div></div>;
return <style>{sass(props.style).to_string()}</style>;
})()}
</head>
<Header
id="storyHeader"
entries={props.story.chapters.map((ch, i) => ({
name: ch.name,
href: `/story?id=${ch.workID}&chapter=${i}`
}))}
></Header>
<div class="main">{props.children}</div>
</html>
);

7
types.d.ts vendored

@ -0,0 +1,7 @@
export interface Props {
[key: string]: any;
}
export interface PropsWithChildren extends Props {
children: any;
}

@ -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<Story> {
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;
},
};
Loading…
Cancel
Save