aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2022-03-30 03:04:48 -0700
committerFuwn <[email protected]>2022-03-30 03:04:48 -0700
commit0495bd1837087a91a36036dbaab71c83c3acc197 (patch)
tree6f1744db3bf9a7eb07da70971f0b2aa39741a0b0
downloadlocus-0495bd1837087a91a36036dbaab71c83c3acc197.tar.xz
locus-0495bd1837087a91a36036dbaab71c83c3acc197.zip
feat: 0.0.0 :star:
-rw-r--r--.dockerignore11
-rw-r--r--.github/workflows/check.yaml35
-rw-r--r--.gitignore11
-rw-r--r--.license_template17
-rw-r--r--Cargo.toml51
-rw-r--r--Dockerfile41
-rw-r--r--LICENSE674
-rw-r--r--Makefile.toml69
-rw-r--r--build.rs22
-rw-r--r--content/meta/favicon.txt1
-rw-r--r--content/meta/robots.txt3
-rw-r--r--content/pages/blog/programming_languages/Golang.gmi53
-rw-r--r--content/pages/blog/programming_languages/OCaml.gmi10
-rw-r--r--content/pages/blog/programming_languages/Rust.gmi9
-rw-r--r--content/pages/contact.gmi14
-rw-r--r--content/pages/donate.gmi7
-rw-r--r--content/pages/gemini.gmi76
-rw-r--r--content/pages/gopher.gmi22
-rw-r--r--content/pages/index.gmi14
-rw-r--r--content/pages/interests.gmi33
-rw-r--r--content/pages/not_found.gmi9
-rw-r--r--content/pages/skills.gmi21
-rw-r--r--docker-compose.yaml7
-rw-r--r--rust-toolchain.toml2
-rw-r--r--rustfmt.toml30
-rw-r--r--src/constants.rs55
-rw-r--r--src/macros.rs68
-rw-r--r--src/main.rs155
-rw-r--r--src/modules.rs177
-rw-r--r--templates/main.hbs5
-rw-r--r--templates/partials/footer.hbs24
-rw-r--r--templates/partials/header.hbs10
-rw-r--r--yarte.toml2
33 files changed, 1738 insertions, 0 deletions
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..a248225
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,11 @@
+# Rust
+target/
+Cargo.lock
+
+# IDE
+.idea/
+
+# Development
+*.pem
+*.db
+.locus/
diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml
new file mode 100644
index 0000000..47f63a3
--- /dev/null
+++ b/.github/workflows/check.yaml
@@ -0,0 +1,35 @@
+name: Check ✅
+
+on:
+ workflow_dispatch:
+ push:
+ paths:
+ - "*"
+ pull_request:
+ paths:
+ - "*"
+
+env:
+ CARGO_TERM_COLOR: always
+
+jobs:
+ check:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout 🛒
+ uses: actions/checkout@v3
+
+ - name: Toolchain 🧰
+ uses: actions-rs/toolchain@v1
+ with:
+ profile: minimal
+ toolchain: nightly-2022-02-22
+ components: rustfmt, clippy
+ override: true
+
+ - name: Check ✅
+ uses: actions-rs/cargo@v1
+ continue-on-error: false
+ with:
+ command: check
+ args: --verbose
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a248225
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+# Rust
+target/
+Cargo.lock
+
+# IDE
+.idea/
+
+# Development
+*.pem
+*.db
+.locus/
diff --git a/.license_template b/.license_template
new file mode 100644
index 0000000..5bf1f90
--- /dev/null
+++ b/.license_template
@@ -0,0 +1,17 @@
+// This file is part of Locus <https://github.com/gemrest/locus>.
+// Copyright (C) {20\d{2}(-20\d{2})?} Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) {20\d{2}(-20\d{2})?} Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only \ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..115b80f
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,51 @@
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[package]
+name = "locus"
+version = "0.0.0"
+authors = ["Fuwn <[email protected]>"]
+edition = "2021"
+description = "Fuwn's Gemini Capsule"
+readme = "README.md"
+homepage = "https://github.com/gemrest/locus"
+repository = "https://github.com/gemrest/locus"
+license = "GPL-3.0-only"
+keywords = ["gemini"]
+categories = ["web-programming"]
+publish = false
+
+# Slower builds, faster executables
+[profile.release]
+opt-level = 3
+lto = "fat"
+codegen-units = 1
+
+[dependencies]
+# Gemini
+windmark = { version = "0.1.3", features = ["logger"] }
+
+# Loggging
+log = "0.4.16"
+pretty_env_logger = "0.4.0"
+
+# Tokio
+tokio = { version = "0.2.4", features = ["full"] }
+
+# Database
+pickledb = "0.4.1"
+
+# Templates
+yarte = "0.15.6"
+
+# RNG
+rand = "0.8.5"
+
+[build-dependencies]
+# Templates
+yarte = "0.15.6"
+
+# Environment Variables
+vergen = "7.0.0"
+
+# `Result`
+anyhow = "1.0.56"
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..66fad04
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,41 @@
+FROM rust:latest as builder
+
+RUN update-ca-certificates
+
+# ENV USER=locus
+# ENV UID=10001
+
+# RUN adduser \
+# --disabled-password \
+# --gecos "" \
+# --home "/nonexistent" \
+# --shell "/sbin/nologin" \
+# --no-create-home \
+# --uid "${UID}" \
+# "${USER}"
+
+WORKDIR /locus
+
+COPY ./ ./
+
+RUN cargo build --release
+
+RUN strip -s /locus/target/release/locus
+
+FROM debian:buster-slim
+
+RUN apt-get update && apt-get install -y libssl-dev
+
+COPY --from=builder /etc/passwd /etc/passwd
+COPY --from=builder /etc/group /etc/group
+
+WORKDIR /locus
+
+COPY --from=builder /locus/target/release/locus ./
+COPY --from=builder /locus/content ./content
+
+# USER locus:locus
+
+EXPOSE 1965
+
+CMD ["./locus"]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff --git a/Makefile.toml b/Makefile.toml
new file mode 100644
index 0000000..2269370
--- /dev/null
+++ b/Makefile.toml
@@ -0,0 +1,69 @@
+# ------------
+# | Wrappers |
+# ------------
+[tasks.fmt]
+command = "cargo"
+args = ["fmt"]
+private = true
+
+[tasks.check]
+command = "cargo"
+args = ["check"]
+private = true
+
+[tasks.clippy]
+command = "cargo"
+args = ["clippy"]
+private = true
+
+# -------------
+# | Executors |
+# -------------
+[tasks.checkf]
+dependencies = ["fmt", "check"]
+
+[tasks.checkfc]
+dependencies = ["fmt", "check", "clippy"]
+
+# openssl req -x509 -newkey rsa:4096 -keyout windmark_private.pem -out windmark_public.pem -days 365
+
+[tasks.genkey]
+command = "openssl"
+args = [
+ "req",
+ "-newkey",
+ "rsa:2048",
+ "-new",
+ "-nodes",
+ "-keyout",
+ "windmark_private.pem",
+ "-out",
+ "windmark_public.pem",
+ "-subj",
+ "/CN=fuwn.me"
+]
+
+[tasks.fixkey]
+command = "openssl"
+args = [
+ "x509",
+ "-req",
+ "-days",
+ "365",
+ "-in",
+ "windmark_public.pem",
+ "-signkey",
+ "windmark_private.pem",
+ "-out",
+ "windmark_pair.pem"
+]
+
+[tasks.run]
+dependencies = ["checkfc"]
+command = "cargo"
+args = ["run", "--", "{@}"]
+
+[tasks.docker-build]
+dependencies = ["checkfc"]
+command = "docker"
+args = ["build", "-t", "fuwn/locus", "."]
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..84c6abd
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,22 @@
+// This file is part of Locus <https://github.com/gemrest/locus>.
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only
+
+fn main() -> anyhow::Result<()> {
+ yarte::recompile::when_changed();
+ vergen::vergen(vergen::Config::default())
+}
diff --git a/content/meta/favicon.txt b/content/meta/favicon.txt
new file mode 100644
index 0000000..7cd8a0c
--- /dev/null
+++ b/content/meta/favicon.txt
@@ -0,0 +1 @@
+💾
diff --git a/content/meta/robots.txt b/content/meta/robots.txt
new file mode 100644
index 0000000..b37a224
--- /dev/null
+++ b/content/meta/robots.txt
@@ -0,0 +1,3 @@
+User-agent: *
+Disallow: /x
+Disallow: /proxy
diff --git a/content/pages/blog/programming_languages/Golang.gmi b/content/pages/blog/programming_languages/Golang.gmi
new file mode 100644
index 0000000..eb0a1e3
--- /dev/null
+++ b/content/pages/blog/programming_languages/Golang.gmi
@@ -0,0 +1,53 @@
+# GOLANG
+
+Author: Fuwn
+Created: 2021. 07. 19.
+Last Modified: 2021. 07. 20.
+
+Golang... Go is quite a funny language to me. I have a hard time taking it seriously, not because of the name, but because of the way it handles. Don't get me wrong, Go is a great tool to have under your belt, but it just feels very... "childish" ... to ME.
+
+Other than the weird chills I get whilst working with it (I just had to get that off my back, for the record), I think Go is a pretty nifty language. Go has the "I can do anything! just not very well..." [0] feeling to it, and it is very much true! I don't write software in Go because it "fast!" or "great on memory!", I write software in Go because it "fast! ...", "to write in!".
+
+> [0] Having the aformentioned quality to it is not particularly a bad thing, I think it actually benefits Go!
+
+Now, allow me to list some pros and cons that I have to say about Golang with some things to note while reading:
+
+These are ...
+
+* in no particular order
+* my opinions!
+* things that aren't explicitly advertised
+
+## PROS
+
+Reasons for anyone to learn or to use Go!
+
+* Fast enough: Not Rust fast, but not Python slow
+* Lots of resources (books, documentation, libraries, tutorials, et cetera)
+* Quite easy to pick up (having had prior experience with C-like programming languages)
+* Can do just about anything!
+
+## CONS
+
+Nitpicks, not deal-breakers!
+
+* Garbage collected: Not necessarily a hard-con, but contributes to more memory overhead (not as much as Node.js though)
+* Can be too simple at times
+* Creepy dependency management and "package manager": `$ go get ...` seems pre-mature and underdeveloped
+
+One thing you might see a lot when there is talk about Go is the claim that Go hasn't "found it's niche" or "it has no real purpose". To that I say; Go's niche is it's simplicity, it's ability to introduce someone into the compiled language space, and to develop software with speed.
+
+## WHO WOULD I RECOMMEND GO TO?
+
+People who...
+
+* don't have much time for boilerplate material
+* want to get into programming (or compiled languages)
+
+and dare I say it... anyone!
+
+## RESOURCES
+
+=> https://golang.org/ golang.org
+=> https://interpreterbook.com/ Writing An Interpreter In Go by Thorsten Ball
+=> https://compilerbook.com/ Writing A Compiler In Go by Thorsten Ball
diff --git a/content/pages/blog/programming_languages/OCaml.gmi b/content/pages/blog/programming_languages/OCaml.gmi
new file mode 100644
index 0000000..cad273e
--- /dev/null
+++ b/content/pages/blog/programming_languages/OCaml.gmi
@@ -0,0 +1,10 @@
+# OCAML
+
+Author: Fuwn
+Created: 2021. 07. 23.
+Last Modified: 2021. 07. 23.
+
+## RESOURCES
+
+=> https://www2.lib.uchicago.edu/keith/ocaml-class/why.html OCaml for the Skeptical
+=> https://softwareengineering.stackexchange.com/questions/62685/why-isnt-ocaml-more-popular Why isn't OCaml more popular?
diff --git a/content/pages/blog/programming_languages/Rust.gmi b/content/pages/blog/programming_languages/Rust.gmi
new file mode 100644
index 0000000..83317da
--- /dev/null
+++ b/content/pages/blog/programming_languages/Rust.gmi
@@ -0,0 +1,9 @@
+# RUST
+
+Author: Fuwn
+Created: 2021. 07. 23.
+Last Modified: 2021. 07. 23.
+
+## RESOURCES
+
+=> https://ceronman.com/2021/07/22/my-experience-crafting-an-interpreter-with-rust/ My experience crafting an interpreter with Rust
diff --git a/content/pages/contact.gmi b/content/pages/contact.gmi
new file mode 100644
index 0000000..6d8aa2d
--- /dev/null
+++ b/content/pages/contact.gmi
@@ -0,0 +1,14 @@
+# CONTACT
+
+=> https://github.com/Fuwn GitHub
+=> https://gitlab.com/Fuwn GitLab
+=> https://discord.com/users/fun#1337 Discord
+=> https://twitter.com/Fuwnr Twitter
+=> https://youtube.com/Fuwnr YouTube
+=> https://matrix.to/#/@fuwn:matrix.org Matrix
+
+## Email
+
+=> mailto:[email protected] [email protected] (I check this the most often)
diff --git a/content/pages/donate.gmi b/content/pages/donate.gmi
new file mode 100644
index 0000000..8c36121
--- /dev/null
+++ b/content/pages/donate.gmi
@@ -0,0 +1,7 @@
+# DONATE
+
+* Bitcoin: bc1qpcyqn63d8uz8q6msna9789sc5sstvp2rew5dgw
+* Monero: 43QPcYCm6BFfufsmN9RrXvM6bcdj3nDZc2stkDbSNpwgf3XQpqrSpadVosB3qtTAyg1T2NUSJ5E2miadhorH53pKF274wUB
+* Litecoin: ltc1qqwsg6wx49zjhlpypk0xe7q4kgclml3d8kx4hlz
+
+or through OpenAlias: fuwn.me
diff --git a/content/pages/gemini.gmi b/content/pages/gemini.gmi
new file mode 100644
index 0000000..6607ae9
--- /dev/null
+++ b/content/pages/gemini.gmi
@@ -0,0 +1,76 @@
+# GEMINI
+
+What is Gemini? I think DT from DistroTube explains it well:
+
+=> gemini://distro.tube distro.tube
+=> https://distrotube.com distrotube.com
+
+## WHY GEMINI?
+
+I have decided to move my personal websites -- and some other projects -- over to the Gemini protocol for a number of reasons (in no specific order):
+
+* Gemini-based capsules are easy to maintain
+* Gemini-based capsules are fun to maintain!
+* No tracking, ads, or any other unneeded fluff
+* The community: From the short experience I have had with the Gemini community, it has been awesome! I love to see the motivation and movement behind this project, it's really inspiring!
+* The development-sphere
+
+## RESOURCES
+
+### CLIENTS
+
+Amfora: A very nice, feature-rich, and easy-to-use CLI client for Gemini, my client of choice.
+
+=> https://github.com/makeworld-the-better-one/amfora Amfora
+
+Bollux: A fun little CLI client for Gemini written in Bash! I mostly use this for quick and dirty testing and development purposes.
+
+=> https://sr.ht/~acdw/bollux/ Bollux
+
+Elaho: An elegant IOS Gemini client.
+
+=> gemini://elaho.glv.one
+
+### PROXIES
+
+Capybara: A Gemini to HTTP proxy, simple and just works.
+
+=> https://github.com/fuwn/capybara Capybara
+
+Mozz.us and Vuples.one Portals: Great Gemini to HTTP proxies, simple and intuitive.
+
+=> https://portal.mozz.us portal.mozz.us
+=> https://proxy.vulpes.one proxy.vulpes.one
+
+Alternatively, you can also use Capybara's (the Gemini-to-HTTP proxy I use for this capsule) built in proxy at the following URL:
+
+=> https://fuwn.me/proxy/fuwn.me fuwn.me/proxy/fuwn.me
+
+Just replace the "fuwn.me" after "proxy/" with whatever Gemini capsule you would like to visit, but be warned; it is not as sophisticated as the aforementioned proxies above, but it gets the job done!
+
+### FRAMEWORKS & SERVERS
+
+Windmark: An elegant and highly performant async Gemini server framework, written by me! (Fuwn)
+
+Similar to Gig, but faster and written in Rust.
+
+=> https://github.com/gemrest/windmark
+
+Gig: A Golang framework for developing and deploying dynamic (or static) Gemini capsules.
+
+=> https://github.com/pitr/gig Gig
+
+Agate: A static Gemini server written in Rust! I'd recommend this to just about anyone!
+
+=> gemini://gem.limpet.net/agate Agate
+
+### CAPSULES
+
+=> gemini://gemini.circumlunar.space Project Gemini
+=> gemini://medusae.space medusae.space gemini directory
+=> gemini://gem.acdw.net acdw's gemini cottage
+=> gemini://gem.chriswere.uk Chris's gemini capsule
+=> gemini://gemini.barca.mi.it The Amazing Fnt400's Gemini Capsule
+=> gemini://hexdsl.co.uk The Home of HexDSL
+=> gemini://envs.net envs.net
+=> gemini://rawtext.club rawtext.club
diff --git a/content/pages/gopher.gmi b/content/pages/gopher.gmi
new file mode 100644
index 0000000..134f1c0
--- /dev/null
+++ b/content/pages/gopher.gmi
@@ -0,0 +1,22 @@
+# GOPHER
+
+## RESOURCES
+
+### CLIENTS
+
+phetch: Similar to Amfora over at Gemini in the aspect that it is a feature-rich and easy-to-use CLI client, once again, my client of choice.
+
+=> https://github.com/xvxx/phetch phetch
+
+Gopher: A straightforward Gopher client for IOS.
+
+=> gopher://forthworks.com/1/iOS/gopher
+
+### GOPHERHOLES
+
+=> gopher://bitreich.org/1/lawn The Gopher Lawn
+=> gopher://gopherpedia.com Gopherpedia
+=> gopher://gopher.floodgap.com/1/gopher Floodgap Systems
+=> gopher://forthworks.com/1/ ForthWorks
+=> gopher://sdf.org/1/ SDF
+=> gopher://hngopher.com/1/ Hacker News
diff --git a/content/pages/index.gmi b/content/pages/index.gmi
new file mode 100644
index 0000000..f7c65b8
--- /dev/null
+++ b/content/pages/index.gmi
@@ -0,0 +1,14 @@
+# FUWN.SPACE
+
+Ditch the web, use Gemini!
+
+## PROJECT GEMINI
+
+What is Gemini? If you want it quick and simple, DT from DistroTube explains it well:
+
+=> gemini://distro.tube distro.tube
+=> https://distrotube.com distrotube.com
+
+You can also read more into Gemini
+
+=> /gemini here!
diff --git a/content/pages/interests.gmi b/content/pages/interests.gmi
new file mode 100644
index 0000000..11b5b7c
--- /dev/null
+++ b/content/pages/interests.gmi
@@ -0,0 +1,33 @@
+# INTERESTS
+
+A collection of somethings that I think are pretty neat and am considering picking up sometime in the future.
+
+## PROGRAMMING LANGUAGES
+
+=> https://www.angelcode.com/angelscript/ AngelScript
+=> https://github.com/Hirrolot/metalang99 Metalang99
+=> https://www.purescript.org/ PureScript
+=> https://crystal-lang.org/ Crystal
+=> https://www.haskell.org/ Haskell
+=> https://cython.org/ Cython
+=> https://gradle.org/ Gradle
+=> https://kotlinlang.org/ Kotlin
+=> https://julialang.org/ Julia
+=> https://ocaml.org/ Ocaml
+=> https://www.scala-lang.org/ Scala
+=> https://dart.dev/ Dart
+=> https://www.ruby-lang.org/ Ruby
+=> https://silq.ethz.ch/ Silq
+=> https://nim-lang.org/ Nim
+=> https://ziglang.org/ Zig
+=> https://docs.microsoft.com/en-us/azure/quantum/overview-what-is-qsharp-and-qdk Q#
+=> https://dlang.org/ D
+=> https://vlang.io/ V
+
+## FRAMEWORKS
+
+=> https://flutter.dev/ Flutter
+=> https://svelte.dev/ Svelte
+=> https://amberframework.org/ Amber
+=> https://rubyonrails.org/ Rails
+=> https://haxe.org/ Haxe
diff --git a/content/pages/not_found.gmi b/content/pages/not_found.gmi
new file mode 100644
index 0000000..6d49669
--- /dev/null
+++ b/content/pages/not_found.gmi
@@ -0,0 +1,9 @@
+# ERROR 404
+
+The requested resource could not be found.
+
+> How did you get here?
+
+## TROUBLESHOOTING
+
+You can try refreshing the page, if that doesn't change anything; contact Fuwn!
diff --git a/content/pages/skills.gmi b/content/pages/skills.gmi
new file mode 100644
index 0000000..a1f5835
--- /dev/null
+++ b/content/pages/skills.gmi
@@ -0,0 +1,21 @@
+# SKILLS
+
+## TECH STACK MASTERY
+
+* C
+* C++
+* Go
+* Node.js (JavaScript, TypeScript): Discord.js, Angular, Express, Akairo, React, Nuxt, Vue, Svelte
+* Deno
+* Python
+* JVM (Java, Clojure): Bukkit, Spark, JDA
+* Rust: Serenity, Rocket, Actix, Tokio
+* PHP: FluxBB, MyBB
+
+## TOOLS, ACCESSORIES
+
+* Document Preparation: Markdown, Pandoc, LaTeX, ReST, Microsoft Word, LibreOffice Writer
+* Build Tools: CMake, GNU Make, Divina, Cargo, Ninja
+* Version Control: Git, Mercurial
+* Game Engines: Unity
+* Databases: PostgreSQL, SQLite, MongoDB, MySQL
diff --git a/docker-compose.yaml b/docker-compose.yaml
new file mode 100644
index 0000000..3da776b
--- /dev/null
+++ b/docker-compose.yaml
@@ -0,0 +1,7 @@
+services:
+ locus:
+ ports:
+ - "1965:1965"
+ volumes:
+ - "./.locus:/locus/.locus"
+ image: "fuwn/locus:latest"
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
new file mode 100644
index 0000000..22a9829
--- /dev/null
+++ b/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "nightly-2022-02-22"
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 100644
index 0000000..1dd4c90
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1,30 @@
+condense_wildcard_suffixes = true
+edition = "2021"
+enum_discrim_align_threshold = 20
+# error_on_line_overflow = true
+# error_on_unformatted = true
+fn_single_line = true
+force_multiline_blocks = true
+format_code_in_doc_comments = true
+format_macro_matchers = true
+format_strings = true
+imports_layout = "HorizontalVertical"
+license_template_path = ".license_template"
+max_width = 80
+match_arm_blocks = false
+imports_granularity = "Crate"
+newline_style = "Unix"
+normalize_comments = true
+normalize_doc_attributes = true
+reorder_impl_items = true
+group_imports = "StdExternalCrate"
+reorder_modules = true
+report_fixme = "Always"
+# report_todo = "Always"
+struct_field_align_threshold = 20
+struct_lit_single_line = false
+tab_spaces = 2
+use_field_init_shorthand = true
+use_try_shorthand = true
+where_single_line = true
+wrap_comments = true
diff --git a/src/constants.rs b/src/constants.rs
new file mode 100644
index 0000000..27c80bd
--- /dev/null
+++ b/src/constants.rs
@@ -0,0 +1,55 @@
+// This file is part of Locus <https://github.com/gemrest/locus>.
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only
+
+pub const QUOTES: &[&str] = &[
+ "That brain of mine is something more than merely mortal; as time will \
+ show. - Ada Lovelace",
+ "Forget this world and all its troubles and if possible its multitudinous \
+ Charlatans — everything in short but the Enchantress of Numbers. - Ada \
+ Lovelace",
+ "If you can't give me poetry, can't you give me poetical science? - Ada \
+ Lovelace",
+ "What I cannot create, I do not understand. - Richard P. Feynman",
+ "Know how to solve every problem that has been solved. - Richard P. Feynman",
+ "Teach principles, not formulas. - Richard P. Feynman",
+ "I learned very early the difference between knowing the name of something \
+ and knowing something. - Richard P. Feynman",
+ "Scientists are explorers. Philosophers are tourists. - Richard P. Feynman",
+ "If you thought that science was certain — Well, that is just an error on \
+ your part. - Richard P. Feynman",
+ "Talk is cheap, Show me the code. - Linus Torvalds",
+ "I like offending people, because I think people who get offended should be \
+ offended. - Linus Torvalds",
+ "Only wimps use tape backup. REAL men just upload their important stuff on \
+ ftp and let the rest of the world mirror it. - Linus Torvalds",
+ "Intelligence is the ability to avoid doing work, yet getting the work \
+ done. - Linus Torvalds",
+ "Programming is not a science. Programming is a craft. - Richard Stallman",
+ "I did write some code in Java once, but that was the island in Indonesia. \
+ - Richard Stallman",
+ "Free software' is a matter of liberty, not price. To understand the \
+ concept, you should think of 'free' as in 'free speech,' not as in 'free \
+ beer'. - Richard Stallman",
+ "You can use any editor you want, but remember that vi vi vi is the text \
+ editor of the beast. - Richard Stallman",
+ "Free software is software that respects your freedom and the social \
+ solidarity of your community. So it's free as in freedom. - Richard \
+ Stallman",
+ "Sharing is good, and with digital technology, sharing is easy. - Richard \
+ Stallman",
+];
diff --git a/src/macros.rs b/src/macros.rs
new file mode 100644
index 0000000..9104f39
--- /dev/null
+++ b/src/macros.rs
@@ -0,0 +1,68 @@
+// This file is part of Locus <https://github.com/gemrest/locus>.
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only
+
+#[macro_export]
+macro_rules! mount_page {
+ ($router:ident, $at:literal, $file:literal) => {
+ ($router).mount(
+ $at,
+ Box::new(|context| {
+ Response::Success(
+ Main {
+ body: include_str!(concat!("../content/pages/", $file, ".gmi"))
+ .into(),
+ hits: &crate::hits_from_route(context.url.path()),
+ quote: QUOTES.choose(&mut rand::thread_rng()).unwrap(),
+ commit: &format!("/tree/{}", env!("VERGEN_GIT_SHA")),
+ }
+ .to_string(),
+ )
+ }),
+ );
+ };
+}
+
+#[macro_export]
+macro_rules! mount_file {
+ ($router:ident, $at:literal, $file:literal) => {
+ ($router).mount(
+ $at,
+ Box::new(|_| {
+ Response::SuccessFile(include_bytes!(concat!(
+ "../content/meta/",
+ $file
+ )))
+ }),
+ );
+ };
+}
+
+#[macro_export]
+macro_rules! success {
+ ($body:expr, $context:ident) => {
+ Response::Success(
+ Main {
+ body: &$body,
+ hits: &crate::hits_from_route($context.url.path()),
+ quote: QUOTES.choose(&mut rand::thread_rng()).unwrap(),
+ commit: &format!("/tree/{}", env!("VERGEN_GIT_SHA")),
+ }
+ .to_string(),
+ )
+ };
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..e88fd9b
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,155 @@
+// This file is part of Locus <https://github.com/gemrest/locus>.
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only
+
+#![feature(once_cell)]
+#![deny(
+ warnings,
+ nonstandard_style,
+ unused,
+ future_incompatible,
+ rust_2018_idioms,
+ unsafe_code
+)]
+#![deny(clippy::all, clippy::nursery, clippy::pedantic)]
+#![recursion_limit = "128"]
+#![allow(clippy::cast_precision_loss)]
+
+mod constants;
+mod macros;
+mod modules;
+
+#[macro_use]
+extern crate log;
+
+use std::{lazy::SyncLazy, sync::Mutex};
+
+use constants::QUOTES;
+use pickledb::PickleDb;
+use rand::seq::SliceRandom;
+use tokio::time::Instant;
+use windmark::{Response, Router};
+use yarte::Template;
+
+static DATABASE: SyncLazy<Mutex<PickleDb>> = SyncLazy::new(|| {
+ Mutex::new({
+ if std::fs::File::open("locus.db").is_ok() {
+ PickleDb::load_json("locus.db", pickledb::PickleDbDumpPolicy::AutoDump)
+ .unwrap()
+ } else {
+ PickleDb::new_json("locus.db", pickledb::PickleDbDumpPolicy::AutoDump)
+ }
+ })
+});
+
+#[derive(Template)]
+#[template(path = "main")]
+struct Main<'a> {
+ body: &'a str,
+ hits: &'a i32,
+ quote: &'a str,
+ commit: &'a str,
+}
+
+fn hits_from_route(route: &str) -> i32 {
+ (*DATABASE.lock().unwrap()).get::<i32>(route).unwrap()
+}
+
+#[windmark::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+ std::env::set_var("RUST_LOG", "windmark,locus=trace");
+ pretty_env_logger::init();
+
+ let mut time_mount = Instant::now();
+ let mut router = Router::new();
+ let uptime = Instant::now();
+
+ router.set_private_key_file(".locus/locus_private.pem");
+ router.set_certificate_chain_file(".locus/locus_pair.pem");
+ router.set_pre_route_callback(Box::new(|stream, url, _| {
+ info!(
+ "accepted connection from {} to {}",
+ stream.peer_addr().unwrap().ip(),
+ url.to_string(),
+ );
+
+ let previous_database = (*DATABASE.lock().unwrap()).get::<i32>(url.path());
+
+ match previous_database {
+ None => {
+ (*DATABASE.lock().unwrap())
+ .set::<i32>(url.path(), &0)
+ .unwrap();
+ }
+ Some(_) => {}
+ }
+
+ let new_database = (*DATABASE.lock().unwrap()).get::<i32>(url.path());
+
+ (*DATABASE.lock().unwrap())
+ .set(url.path(), &(new_database.unwrap() + 1))
+ .unwrap();
+ }));
+ router.set_error_handler(Box::new(|_| {
+ Response::NotFound(
+ "The requested resource could not be found at this time. You can try \
+ refreshing the page, if that doesn't change anything; contact Fuwn! \
+ .into(),
+ )
+ }));
+ router.mount(
+ "/uptime",
+ Box::new(move |context| {
+ success!(
+ &format!("# UPTIME\n\n{} seconds", uptime.elapsed().as_secs()),
+ context
+ )
+ }),
+ );
+
+ info!(
+ "preliminary mounts took {}ms",
+ time_mount.elapsed().as_nanos() as f64 / 1_000_000.0
+ );
+ time_mount = Instant::now();
+
+ router.attach(modules::multi_blog);
+
+ info!(
+ "blog mounts took {}ms",
+ time_mount.elapsed().as_nanos() as f64 / 1_000_000.0
+ );
+ time_mount = Instant::now();
+
+ mount_file!(router, "/robots.txt", "robots.txt");
+ mount_file!(router, "/favicon.txt", "favicon.txt");
+ mount_page!(router, "/", "index");
+ mount_page!(router, "/contact", "contact");
+ mount_page!(router, "/donate", "donate");
+ mount_page!(router, "/gemini", "gemini");
+ mount_page!(router, "/gopher", "gopher");
+ mount_page!(router, "/interests", "interests");
+ mount_page!(router, "/skills", "skills");
+
+ info!(
+ "static mounts took {}ms",
+ time_mount.elapsed().as_nanos() as f64 / 1_000_000.0
+ );
+
+ router.run().await
+}
diff --git a/src/modules.rs b/src/modules.rs
new file mode 100644
index 0000000..0067266
--- /dev/null
+++ b/src/modules.rs
@@ -0,0 +1,177 @@
+// This file is part of Locus <https://github.com/gemrest/locus>.
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only
+
+use std::{
+ collections::HashMap,
+ fs::{self, read_dir},
+ io::Read,
+};
+
+use rand::seq::SliceRandom;
+use windmark::Response;
+
+use crate::{success, Main, QUOTES};
+
+#[allow(clippy::too_many_lines)]
+pub fn multi_blog(router: &mut windmark::Router) {
+ let paths = read_dir("content/pages/blog").unwrap();
+ let mut blogs: HashMap<String, HashMap<_, _>> = HashMap::new();
+
+ for path in paths {
+ let blog = path.unwrap().path().display().to_string();
+ let blog_paths = read_dir(&blog).unwrap();
+ let mut entries: HashMap<_, String> = HashMap::new();
+
+ blog_paths
+ .map(|e| e.unwrap().path().display().to_string())
+ .for_each(|file| {
+ let mut contents = String::new();
+
+ fs::File::open(&file)
+ .unwrap()
+ .read_to_string(&mut contents)
+ .unwrap();
+
+ entries.insert(
+ file.replace(&blog, "").replace(".gmi", "").replace(
+ {
+ #[cfg(windows)]
+ {
+ '\\'
+ }
+
+ #[cfg(unix)]
+ {
+ '/'
+ }
+ },
+ "",
+ ),
+ contents,
+ );
+ });
+
+ blogs.insert(
+ blog
+ .replace(
+ {
+ #[cfg(windows)]
+ {
+ "content/pages/blog\\"
+ }
+
+ #[cfg(unix)]
+ {
+ "content/pages/blog/"
+ }
+ },
+ "",
+ )
+ .split('_')
+ .map(|s| {
+ // https://gist.github.com/jpastuszek/2704f3c5a3864b05c48ee688d0fd21d7
+ let mut c = s.chars();
+
+ match c.next() {
+ None => String::new(),
+ Some(f) =>
+ f.to_uppercase()
+ .chain(c.flat_map(char::to_lowercase))
+ .collect(),
+ }
+ })
+ .collect::<Vec<_>>()
+ .join(" "),
+ entries,
+ );
+ }
+
+ let blog_clone = blogs.clone();
+
+ router.mount(
+ "/blog",
+ Box::new(move |context| {
+ success!(
+ &format!(
+ "# BLOGS ({})\n\n{}",
+ blog_clone.len(),
+ blog_clone
+ .iter()
+ .map(|(title, _)| title.clone())
+ .collect::<Vec<_>>()
+ .into_iter()
+ .map(|i| {
+ format!(
+ "=> {} {}",
+ format_args!("/blog/{}", i.replace(' ', "_").to_lowercase(),),
+ i
+ )
+ })
+ .collect::<Vec<_>>()
+ .join("\n")
+ ),
+ context
+ )
+ }),
+ );
+
+ for (blog, entries) in blogs {
+ let fixed_blog_name = blog.replace(' ', "_").to_lowercase();
+ let entries_clone = entries.clone();
+ let fixed_blog_name_clone = fixed_blog_name.clone();
+
+ router.mount(
+ &format!("/blog/{}", fixed_blog_name),
+ Box::new(move |context| {
+ success!(
+ &format!(
+ "# {} ({})\n\n{}",
+ blog.to_uppercase(),
+ entries_clone.len(),
+ entries_clone
+ .iter()
+ .map(|(title, _)| title.clone())
+ .collect::<Vec<_>>()
+ .into_iter()
+ .map(|i| {
+ format!(
+ "=> {} {}",
+ format_args!(
+ "/blog/{}/{}",
+ fixed_blog_name_clone,
+ i.to_lowercase()
+ ),
+ i
+ )
+ })
+ .collect::<Vec<_>>()
+ .join("\n")
+ ),
+ context
+ )
+ }),
+ );
+
+ for (title, contents) in entries {
+ router.mount(
+ &format!("/blog/{}/{}", fixed_blog_name, title.to_lowercase()),
+ Box::new(move |context| success!(contents, context)),
+ );
+ }
+ }
+}
diff --git a/templates/main.hbs b/templates/main.hbs
new file mode 100644
index 0000000..ef1743d
--- /dev/null
+++ b/templates/main.hbs
@@ -0,0 +1,5 @@
+{{> partials/header }}
+
+{{{ body }}}
+
+{{> partials/footer }}
diff --git a/templates/partials/footer.hbs b/templates/partials/footer.hbs
new file mode 100644
index 0000000..1d5a227
--- /dev/null
+++ b/templates/partials/footer.hbs
@@ -0,0 +1,24 @@
+## QUICK LINKS
+
+=> / Home
+=> /skills Skills
+=> /interests Interests
+=> /contact Contact
+=> /donate Donate
+=> /gemini Gemini
+=> /gopher Gopher
+=> /blog Blog
+
+## FOOTER
+
+> {{{ quote }}}
+
+Hits: {{ hits }}
+
+> Any and all opinions listed here are my own and not representative of my employers; past, present, and future.
+
+=> https://github.com/gemrest/locus{{{ commit }}} Source Code
+=> http://fuwnme4wbs5x36jjf2usedw2zscozwhazykhyfkjsmudtb7egs3mb7yd.onion Tor
+=> http://fuwn.i2p/?i2paddresshelper=farkjfnlz6grt55rupbabuhfkvhi7pivwdfwztgcxdklh3db3mfq.b32.i2p I2P
+
+Copyright (C) 2021-2021 Fuwn
diff --git a/templates/partials/header.hbs b/templates/partials/header.hbs
new file mode 100644
index 0000000..a52a042
--- /dev/null
+++ b/templates/partials/header.hbs
@@ -0,0 +1,10 @@
+```
+______
+| ___|
+| |_ _ ___ ___ __ ___ _ __ __ _ ___ ___
+| _| | | \ \ /\ / / '_ \ / __| '_ \ / _` |/ __/ _ \
+| | | |_| |\ V V /| | | |_\__ \ |_) | (_| | (_| __/
+\_| \__,_| \_/\_/ |_| |_(_)___/ .__/ \__,_|\___\___|
+ | |
+ |_|
+```
diff --git a/yarte.toml b/yarte.toml
new file mode 100644
index 0000000..69f4476
--- /dev/null
+++ b/yarte.toml
@@ -0,0 +1,2 @@
+[main]
+dir = "templates"