Compare commits
339 Commits
Author | SHA1 | Date |
---|---|---|
teddit | 4536a7f460 | |
artemislena | 4b2c1c4784 | |
teddit | ebb1b46af3 | |
teddit | 8194c065c9 | |
lostskunk_Donetsk | 227591acff | |
lostskunk_Donetsk | 0f4c5030cd | |
teddit | 5997517825 | |
sneednet | 59abc28178 | |
sneednet | 3f5acf0fce | |
teddit | 78973f2562 | |
teddit | a5b4bedfaa | |
x4 | 2bb2efaca9 | |
teddit | 5ad837373a | |
teddit | 242deb4e05 | |
teddit | 2f3e820fb4 | |
cypherhades | baa4fbd44e | |
ConcordOne | 8d800e490c | |
teddit | b0ce6c52a6 | |
teddit | e6ae8bf0c3 | |
teddit | 490556fc6a | |
No-Logs.com | d05ecf2af6 | |
No-Logs.com | 04980be0d0 | |
teddit | 0536dcd505 | |
Kyle David Rohland | ec882c6869 | |
Kyle David Rohland | 28bd75bdb5 | |
No-Logs.com | 6a2641664f | |
teddit | 50b112bfbc | |
teddit | a4558ce3ea | |
teddit | 6d8f27a09a | |
ppsn | 605e9064a1 | |
teddit | d574b42297 | |
No-Logs.com | 1fb2d45b06 | |
zaggynl | e6ccc292b5 | |
ppsn | 13e7a13c87 | |
ppsn | 76c57cc6aa | |
teddit | f73b9c2bea | |
ppsn | 809402937d | |
ppsn | 844b1d2056 | |
ppsn | f56ec2fb2f | |
ppsn | 8e5f270783 | |
teddit | a23e606bee | |
teddit | 5c147d0d82 | |
teddit | b9f108f675 | |
teddit | dbbb1ac6f7 | |
ppsn | 2ac1466231 | |
HexagonCDN | 298982dfff | |
Wibi | a02025a86f | |
teddit | 96a55fb2ce | |
teddit | 21ddd3b89f | |
teddit | 25e789fdad | |
teddit | 68aed7b9be | |
teddit | 9cb6a80c15 | |
teddit | 8c52544404 | |
teddit | 563be382d3 | |
The1029 | 596e8ef093 | |
Anshuman Kumar | 0969d694db | |
Anshuman Kumar | aa75cc239a | |
teddit | 079ea36d24 | |
teddit | d31c418816 | |
teddit | d11ddce9d2 | |
teddit | 572068aca4 | |
teddit | ea6ad7c8ec | |
Anshuman Kumar | ed0c0c7d28 | |
Anshuman Kumar | 9a328612c4 | |
dependabot[bot] | e28ddf2935 | |
Anshuman Kumar | b3b1cbbc95 | |
Anshuman Kumar | b6acf7542a | |
Anshuman Kumar | 2873e2aea5 | |
Anshuman Kumar | ab95c341c6 | |
Anshuman Kumar | f7f2d0beec | |
dependabot[bot] | f7cecfd465 | |
Anshuman Kumar | df20a9c7fe | |
dependabot[bot] | 0ea8b831c3 | |
dependabot[bot] | 625c86a2b2 | |
dependabot[bot] | a9c8f6b6ce | |
Anshuman Kumar | c71bf6ee48 | |
bradmurray | d96372b08a | |
NunoSempere | e59e57ca83 | |
NunoSempere | 494c7f5417 | |
CosmosDev | 2c5c9d7cde | |
CosmosDev | 54c658ff9b | |
CosmosDev | 3a51e9d165 | |
CosmosDev | baddb1aec2 | |
CosmosDev | eec2a24eb3 | |
CosmosDev | 0852396b6d | |
teddit | 22b63a3415 | |
Jean-Luc Tibaux | 50c369833b | |
Jean-Luc Tibaux | 45dc798eef | |
teddit | e2237f1b93 | |
teddit | ee7068a88c | |
kazuki | dc58122aa1 | |
kazuki | ba207e18c7 | |
kazuki | 4241490793 | |
Jean-Luc Tibaux | d70e6a4265 | |
teddit | bb06a47b1a | |
ltGuillaume | eb2131c2ff | |
teddit | 4c3c743536 | |
teddit | 66b11dc647 | |
Hygna | 83a8c48d9c | |
valere | ba3230be1a | |
valere | 0003bdcbb8 | |
teddit | 6fa109e6ff | |
teddit | a4b130af81 | |
teddit | 1ece7467dc | |
alan | bc3af7b609 | |
Austin Huang | 0cf3d6d6c9 | |
NunoSempere | 718d04c412 | |
NunoSempere | dcdfc28e00 | |
teddit | 27874a6766 | |
teddit | e5640ef5a3 | |
teddit | facab379ca | |
apmechev | e5d374f5f8 | |
Hygna | ba8ed2acb0 | |
teddit | ccfdff679e | |
Wibi | b66e4159d2 | |
Wibi | 738a7ba646 | |
teddit | 48b89a7a8c | |
teddit | 52bc1f4945 | |
teddit | 55b17e5141 | |
teddit | 90f0872d77 | |
artemislena | bccae3cce5 | |
artemislena | e5cc5c8d3b | |
teddit | 67b746c4df | |
technonerd | e120ecfca2 | |
technonerd | c515f351be | |
teddit | d85f0680ad | |
Moxie "The Cobra" Widulski | dbe25af3ac | |
Moxie "The Cobra" Widulski | e697729466 | |
teddit | cee89787ea | |
PrivacyTools | 163bfe8e4d | |
PrivacyTools | 09ac20dd6b | |
teddit | 07984ab36b | |
ConcordOne | baba8b7fab | |
ConcordOne | 0da38c783a | |
teddit | cbd0babf43 | |
teddit | 25fa819833 | |
dr460nf1r3 | 372f21328f | |
teddit | 5f1d50bc8c | |
apmechev | 18b26aa758 | |
teddit | 7ef04def16 | |
Abdelkarim Djelalda | f7082acc41 | |
Abdelkarim Djelalda | f33d78f6a4 | |
teddit | 74625f39b7 | |
teddit | 799bc837c7 | |
teddit | 07050c9cf6 | |
teddit | 2b22ffa105 | |
teddit | 02fd92ce2c | |
teddit | 8af3ec3591 | |
triallax | e29b41a728 | |
teddit | e3b2c663d9 | |
teddit | 842a7ca802 | |
teddit | 0863c841e4 | |
teddit | 84d0009984 | |
teddit | a0c74aa309 | |
teddit | 4663b3a78d | |
redmt | 4ff7152be1 | |
teddit | b1f65f31d8 | |
StevenNMeza | 231348e75e | |
teddit | 1fbef42a7c | |
redmt | 9fd891b474 | |
redmt | 0bf27cfd6c | |
redmt | fc56f0a833 | |
teddit | 1759724268 | |
teddit | 601e393dda | |
redmt | d8edffba1a | |
teddit | 270e9e5ceb | |
teddit | 28c3c60078 | |
teddit | 7f981f69ae | |
redmt | 1f6f5d621d | |
redmt | 53a5766de7 | |
redmt | a0fcdf101e | |
redmt | 55bd044b06 | |
redmt | b2dba3f723 | |
redmt | 8f57cb143b | |
redmt | 69a9b0e080 | |
redmt | afbad4ae3b | |
redmt | 20db540b5c | |
redmt | cfdfd4a2b1 | |
redmt | 555ff9068b | |
redmt | 2ff979bdda | |
redmt | 108f87a5e4 | |
teddit | b0d5377e21 | |
teddit | 0432c7484d | |
teddit | a63b5beb7e | |
teddit | 60d9b33825 | |
teddit | c9b2dbf750 | |
teddit | b797cef167 | |
teddit | 096c7218d4 | |
redmt | fb6673265e | |
redmt | 546fdb5d77 | |
redmt | d368acac29 | |
redmt | d6b2e0700a | |
redmt | 6c52664155 | |
redmt | 27ade36805 | |
redmt | 354180119f | |
teddit | 3855a618ee | |
teddit | 9e4ea80c7e | |
teddit | 1c9b125b70 | |
redmt | 7f8cc27ffb | |
redmt | 7a508c55ee | |
redmt | 05d7db481c | |
redmt | ae429bcbf9 | |
redmt | a73bd2e3ec | |
redmt | 9c8e72eccd | |
redmt | 0bf3ead82d | |
redmt | cc6c2a1cd6 | |
redmt | 6328e41bcf | |
redmt | 319fa35d5f | |
redmt | 064c97579e | |
redmt | 811348c1af | |
redmt | 2f51368ac6 | |
redmt | 932d7f07ee | |
redmt | 5ef61af67f | |
redmt | 04395734cf | |
redmt | 2a92f0a57d | |
redmt | 12790f7e8e | |
redmt | 22328e318c | |
redmt | 7ceb0e8b5d | |
redmt | 9553b94cc0 | |
teddit | 8ccc694d2f | |
teddit | e640e794db | |
teddit | 3612345fab | |
teddit | 1b6e1e5494 | |
teddit | 77917c8ea5 | |
analogue | 9b6dec1108 | |
analogue | 4bb02eaf03 | |
teddit | 09ca31701a | |
teddit | 925fe0565e | |
teddit | 86dab3b816 | |
triallax | 87bd0138c1 | |
Sam Therapy | 4626a0f9bf | |
analogue | ee7508b24a | |
teddit | a53a9fc3df | |
teddit | 5c8cbc8595 | |
triallax | 2b03532289 | |
StevenNMeza | a89ab7d1b5 | |
teddit | 2d69623bf1 | |
TheFrenchGhosty | 1baa654a54 | |
teddit | fa8f0ba02b | |
teddit | 8bcbe8d4ee | |
teddit | 6c84bdd1e3 | |
teddit | d71c88871c | |
sartateme | 274a8be24e | |
teddit | 3ef2f004ea | |
amrw | 063523ed4d | |
teddit | 7c7709e74f | |
teddit | eac2627114 | |
teddit | 265c33fcd2 | |
teddit | 01c41c7adf | |
teddit | 397a02c821 | |
teddit | 3ad64d5c87 | |
teddit | d315051a7b | |
teddit | d947182058 | |
teddit | e87b811883 | |
teddit | 446f388be2 | |
teddit | 791a80b337 | |
teddit | 301774ce8d | |
Austin Huang | 08437d8663 | |
Austin Huang | b5878ea031 | |
Austin Huang | c97fb5a517 | |
teddit | 1efe34c0ad | |
teddit | 7a9603f850 | |
teddit | 15256b1cd8 | |
teddit | bc274e9660 | |
teddit | ab44566561 | |
teddit | a411df0503 | |
Jean-Luc Tibaux | 849475925d | |
Jean-Luc Tibaux | dd45b2633a | |
nfusionz | fcc0fce890 | |
nfusionz | c1faeeb05c | |
teddit | 734ac6a817 | |
gawii0 | 2e030e2c4b | |
teddit | 010c934d60 | |
teddit | ab076d020f | |
gawii0 | 0d2de61444 | |
gawii0 | e870b9ea50 | |
gawii0 | e0bf08132d | |
gawii0 | aa3a854b6e | |
teddit | 8315ad3f16 | |
teddit | 4bf092e481 | |
TheFrenchGhosty | cadf67f488 | |
teddit | 992429818f | |
dominion | 2ea766e01a | |
dominion | fd3d96a8d3 | |
teddit | be28d7fdfa | |
TotalDarkness | 168d896e69 | |
teddit | 126eb5d0cc | |
Ming Di Leom | 0cf6a2228f | |
teddit | b476f9f2b6 | |
teddit | 0eb5ce1b6e | |
teddit | c9637524ec | |
teddit | 9783091216 | |
teddit | 08e9f90233 | |
teddit | 30d0000dca | |
teddit | d895e400ef | |
3nprob | 8bf7d4f792 | |
3nprob | 56a2f6b266 | |
teddit | 660e5681be | |
sethforprivacy | 631b63c6eb | |
teddit | 59bacc0fde | |
tacerus | a37d20f889 | |
teddit | f8e6d326ba | |
teddit | 998fa01a39 | |
TheFrenchGhosty | adf8258670 | |
TheFrenchGhosty | db63adcb7d | |
TheFrenchGhosty | 43f846c1e5 | |
TheFrenchGhosty | eb8e1f394b | |
teddit | 692d6164b3 | |
teddit | c34c32cc35 | |
teddit | a9f13741bb | |
teddit | 5a01338428 | |
teddit | c4d167c787 | |
teddit | d475407061 | |
teddit | 9d01c544d1 | |
arche_dev | d2feeac288 | |
teddit | 8bb949b2b3 | |
teddit | 9e515c4985 | |
teddit | 0707349a85 | |
teddit | cc9d9e5579 | |
teddit | 873e56a23b | |
teddit | a6b9599463 | |
teddit | 813fb3566c | |
teddit | 4cc8dd7bd5 | |
json | e1df2ea8ae | |
json | 6ced924bc8 | |
json | 6ff892767c | |
json | 153a50e60a | |
json | 0bf3e36c56 | |
json | 9bc3ff8d34 | |
json | 711f2450c7 | |
json | aae3e00ab1 | |
json | 1c7a3a8f5a | |
json | 5f5388da6f | |
json | d95642cf80 | |
json | 93f70533aa | |
json | f3cc837a01 | |
json | d1ef359435 | |
json | 7f347d13f7 | |
teddit | 6433afde09 |
|
@ -2,6 +2,12 @@ version: 2
|
||||||
updates:
|
updates:
|
||||||
# Maintain dependencies for GitHub Actions
|
# Maintain dependencies for GitHub Actions
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
|
||||||
|
# Maintain dependencies for npm
|
||||||
|
- package-ecosystem: "npm"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
|
@ -10,26 +10,26 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v2
|
||||||
-
|
-
|
||||||
name: Login to GitHub Container Registry
|
name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
-
|
-
|
||||||
name: Login to DockerHub
|
name: Login to DockerHub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
- name: "Checkout repository"
|
- name: "Checkout repository"
|
||||||
uses: "actions/checkout@v2"
|
uses: "actions/checkout@v3"
|
||||||
-
|
-
|
||||||
name: Build and push to Docker Hub and Github Packages Docker Registry
|
name: Build and push to Docker Hub and Github Packages Docker Registry
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
|
|
|
@ -9,26 +9,26 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v2
|
||||||
-
|
-
|
||||||
name: Login to GitHub Container Registry
|
name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
-
|
-
|
||||||
name: Login to DockerHub
|
name: Login to DockerHub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
- name: "Checkout repository"
|
- name: "Checkout repository"
|
||||||
uses: "actions/checkout@v2"
|
uses: "actions/checkout@v3"
|
||||||
-
|
-
|
||||||
name: Build and push to Docker Hub and Github Packages Docker Registry
|
name: Build and push to Docker Hub and Github Packages Docker Registry
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
node_modules/
|
node_modules/
|
||||||
*.log
|
*.log
|
||||||
config.js
|
config.js
|
||||||
|
.vscode/
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
# Use LTS Node.js base image
|
# Use LTS Node.js slim image
|
||||||
FROM node:14.17-alpine
|
FROM node:slim
|
||||||
|
|
||||||
# Video support dependency
|
# Video support dependency
|
||||||
RUN apk add ffmpeg
|
RUN apt-get update && apt-get install -y ffmpeg wget
|
||||||
|
|
||||||
# Install NPM dependencies and copy the project
|
# Install NPM dependencies and copy the project
|
||||||
WORKDIR /teddit
|
WORKDIR /teddit
|
||||||
|
@ -12,4 +12,6 @@ COPY config.js.template ./config.js
|
||||||
|
|
||||||
RUN find ./static/ -type d -exec chmod -R 777 {} \;
|
RUN find ./static/ -type d -exec chmod -R 777 {} \;
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
CMD npm start
|
CMD npm start
|
||||||
|
|
142
README.md
142
README.md
|
@ -1,5 +1,14 @@
|
||||||
# teddit
|
# teddit
|
||||||
|
|
||||||
|
## teddit is no more actively maintained!
|
||||||
|
|
||||||
|
[Due to Reddit's API changes](https://en.wikipedia.org/wiki/2023_Reddit_API_controversy), this project is no more actively maintained.
|
||||||
|
Feel free to fork the project if you like, or contribute to other alternative Reddit front-ends, such as Libreddit, which are trying to come up with circumventions.
|
||||||
|
|
||||||
|
This project is still maintained, but just not actively. You can create PRs, but don't expect them to be merged right away.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
[teddit.net](https://teddit.net)
|
[teddit.net](https://teddit.net)
|
||||||
|
|
||||||
A free and open source alternative Reddit front-end focused on privacy.
|
A free and open source alternative Reddit front-end focused on privacy.
|
||||||
|
@ -22,21 +31,37 @@ XMR: 832ogRwuoSs2JGYg7wJTqshidK7dErgNdfpenQ9dzMghNXQTJRby1xGbqC3gW3GAifRM9E84J91
|
||||||
|
|
||||||
Community instances:
|
Community instances:
|
||||||
|
|
||||||
| Instance | Onion Link | Notes |
|
| Instance | Onion Link | I2P | Notes |
|
||||||
|-|-|-|
|
|-|-|-|-|
|
||||||
| [teddit.ggc-project.de](https://teddit.ggc-project.de) | | |
|
| [teddit.ggc-project.de](https://teddit.ggc-project.de) | | | |
|
||||||
| [teddit.kavin.rocks](https://teddit.kavin.rocks) | [teddit4w6cmzmj5kimhfc...onion](http://teddit4w6cmzmj5kimhfcavs7yo5s7alszvsi2khqutqtlaanpcftfyd.onion/) | |
|
| [teddit.zaggy.nl](https://teddit.zaggy.nl) | | | |
|
||||||
| [teddit.zaggy.nl](https://teddit.zaggy.nl) | | |
|
| [teddit.tinfoil-hat.net](https://teddit.tinfoil-hat.net) | | | |
|
||||||
| [teddit.namazso.eu](https://teddit.namazso.eu) | | |
|
| [teddit.domain.glass](https://teddit.domain.glass) | | | |
|
||||||
| [teddit.nautolan.racing](https://teddit.nautolan.racing) | | |
|
| [snoo.ioens.is](https://snoo.ioens.is) | [snoo.ioensistjs7wd746...onion](http://snoo.ioensistjs7wd746zluwixvojbbkxhr37lepdvwtdfeav673o64iflqd.onion/) | | |
|
||||||
| [teddit.tinfoil-hat.net](https://teddit.tinfoil-hat.net) | | |
|
| [teddit.httpjames.space](https://teddit.httpjames.space) | | | |
|
||||||
| [teddit.domain.glass](https://teddit.domain.glass) | | |
|
| [teddit.xbdm.fun](https://teddit.xbdm.fun) | | | |
|
||||||
| [snoo.ioens.is](https://snoo.ioens.is) | [snoo.ioensistjs7wd746...onion](http://snoo.ioensistjs7wd746zluwixvojbbkxhr37lepdvwtdfeav673o64iflqd.onion/) | |
|
| | [ibarajztopxnuhabfu7f...onion](http://ibarajztopxnuhabfu7fg6gbudynxofbnmvis3ltj6lfx47b6fhrd5qd.onion) | [xugoqcf2pftm76vbznx4...i2p](http://xugoqcf2pftm76vbznx4xuhrzyb5b6zwpizpnw2hysexjdn5l2tq.b32.i2p) | Operated by [mdleom.com](https://mdleom.com/about/#Services) |
|
||||||
| [teddit.httpjames.space](https://teddit.httpjames.space) | | |
|
| [incogsnoo.com](https://incogsnoo.com) | [tedditfyn6idalzso5wam....onion](http://tedditfyn6idalzso5wam5qd3kdtxoljjhbrbbx34q2xkcisvshuytad.onion/) | [http://teddit.i2p](http://teddit.i2p) | |
|
||||||
| [ibarajztopxnuhabfu7f...onion](http://ibarajztopxnuhabfu7fg6gbudynxofbnmvis3ltj6lfx47b6fhrd5qd.onion) | | |
|
| [teddit.pussthecat.org](https://teddit.pussthecat.org) | | | Operated by [PussTheCat.org](https://pussthecat.org/) |
|
||||||
| [xugoqcf2pftm76vbznx4...i2p](http://xugoqcf2pftm76vbznx4xuhrzyb5b6zwpizpnw2hysexjdn5l2tq.b32.i2p) | | |
|
| [reddit.lol](https://reddit.lol) | [http://dawtyi5e2cfyfmoht...onion](http://dawtyi5e2cfyfmoht4izmczi42aa2zwh6wi34zwvc6rzf2acpxhrcrad.onion) | [http://vzeiwzi7ogwl3i...b32.i2p](http://vzeiwzi7ogwl3ijrfek4fbtwhvamxcpyqoc3s4vcgnhlp54s5clq.b32.i2p) | Operated by https://liberta.casa | |
|
||||||
| [teddit.alefvanoon.xyz](https://teddit.alefvanoon.xyz) | | |
|
| [teddit.sethforprivacy.com](https://teddit.sethforprivacy.com/) | [qtpvyiaqhmwccx...onion/](http://qtpvyiaqhmwccxwzsqubd23xhmmrt75tdyw35kp43w4hvamsgl3x27ad.onion/) | | For more similar hosted tools, see [blog.sethforprivacy.com](https://blog.sethforprivacy.com/about/#my-community-resources) |
|
||||||
| [incogsnoo.com](https://incogsnoo.com) | [tedditfyn6idalzso5wam....onion](tedditfyn6idalzso5wam5qd3kdtxoljjhbrbbx34q2xkcisvshuytad.onion/) | I2P: [http://teddit.i2p](http://teddit.i2p) |
|
| [teddit.adminforge.de](https://teddit.adminforge.de) | | | Operated by https://adminforge.de |
|
||||||
|
| [teddit.bus-hit.me](https://teddit.bus-hit.me) | | | Operated by https://bus-hit.me |
|
||||||
|
| [teddit.froth.zone](https://teddit.froth.zone) | | | |
|
||||||
|
| [rdt.trom.tf](https://rdt.trom.tf) | | | Part of the https://trom.tf project |
|
||||||
|
| [teddit.encrypted-data.xyz](https://teddit.encrypted-data.xyz) | | | |
|
||||||
|
| [i.opnxng.com](https://i.opnxng.com) | | | |
|
||||||
|
| [teddit.tokhmi.xyz](https://teddit.tokhmi.xyz) | | | |
|
||||||
|
| [teddit.garudalinux.org](https://teddit.garudalinux.org) | | | Managed by https://garudalinux.org |
|
||||||
|
| [teddit.privacytools.io](https://teddit.privacytools.io) | [jnuonmf2n36sfdmyksqq....onion](http://jnuonmf2n36sfdmyksqqqyab3w63cq4kx24olyjleh5z6zzfvyt7uqqd.onion) | | Part of [PrivacyTools.io](https://www.privacytools.io/) and hosted by [Privex](https://www.privex.io/) |
|
||||||
|
| [td.vern.cc](https://td.vern.cc) | [td.vernccvbvyi5qhfzyqen...onion](http://td.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion) | [td.vern.i2p](http://verncco2oaxjikammz4pi7umzp673cme6zuemx7yeeewspwrw3va.b32.i2p) | Operated by https://vern.cc |
|
||||||
|
| [teddit.rawbit.ninja](https://teddit.rawbit.ninja) | [yqu4yj5lju7bmlwpzpml...onion](http://yqu4yj5lju7bmlwpzpmltb5gsu6cw7nnbcxxx4iqemwa56nxjiggf4qd.onion) | | Operated by https://rawbit.ninja |
|
||||||
|
| [teddit.hostux.net](https://teddit.hostux.net) | | | Operated by https://hostux.net |
|
||||||
|
| [teddit.no-logs.com](https://teddit.no-logs.com/) | | | Operated by https://no-logs.com |
|
||||||
|
| [teddit.projectsegfau.lt](https://teddit.projectsegfau.lt) | [teddit.pjsfkvpxlinjamta...onion](http://teddit.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion) | | Maintained by Project Segfault Team (https://projectsegfau.lt/team) |
|
||||||
|
| [teddit.laserdisc.tokyo](https://teddit.laserdisc.tokyo) | | | |
|
||||||
|
| [t.sneed.network](https://t.sneed.network) | [t.sneed4fmhevap3ci4x...onion](http://t.sneed4fmhevap3ci4xhf4wgkf72lwk275lcgomnfgwniwmqvaxyluuid.onion/) | | Operated by [sneed.network](https://sneed.network) |
|
||||||
|
| | [teddit.skunky7dhv7no...onion](http://teddit.skunky7dhv7nohsoalpwe3sxfz3fbkad7r3wk632riye25vqm3meqead.onion/) | | Self-hosted, works only from 7-11 AM Moscow time to 10-12 PM, in Donetsk |
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Remove the Changelog section, because the CHANGELOG.md is not updated anymore
|
Remove the Changelog section, because the CHANGELOG.md is not updated anymore
|
||||||
|
@ -47,9 +72,55 @@ See ```CHANGELOG.md```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### Docker-compose method
|
### Docker-compose method (production)
|
||||||
|
|
||||||
```console
|
```docker
|
||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
teddit:
|
||||||
|
container_name: teddit
|
||||||
|
image: teddit/teddit:latest
|
||||||
|
environment:
|
||||||
|
- DOMAIN=teddit.net
|
||||||
|
- USE_HELMET=true
|
||||||
|
- USE_HELMET_HSTS=true
|
||||||
|
- TRUST_PROXY=true
|
||||||
|
- REDIS_HOST=teddit-redis
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8080:8080"
|
||||||
|
networks:
|
||||||
|
- teddit_net
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget" ,"--no-verbose", "--tries=1", "--spider", "http://localhost:8080/about"]
|
||||||
|
interval: 1m
|
||||||
|
timeout: 3s
|
||||||
|
depends_on:
|
||||||
|
- teddit-redis
|
||||||
|
|
||||||
|
teddit-redis:
|
||||||
|
container_name: teddit-redis
|
||||||
|
image: redis:6.2.5-alpine
|
||||||
|
command: redis-server
|
||||||
|
environment:
|
||||||
|
- REDIS_REPLICATION_MODE=master
|
||||||
|
networks:
|
||||||
|
- teddit_net
|
||||||
|
|
||||||
|
networks:
|
||||||
|
teddit_net:
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: This compose is made for a true "production" setup, and is made to be used to have teddit behind a reverse proxy, if you don't want that and prefer to directly access teddit via its port:
|
||||||
|
|
||||||
|
- Change `ports: - "127.0.0.1:8080:8080"` to `ports: - "8080:8080"`
|
||||||
|
- Remove `DOMAIN=teddit.net`, `USE_HELMET=true`, `USE_HELMET_HSTS=true`, `TRUST_PROXY=true`
|
||||||
|
|
||||||
|
|
||||||
|
### Docker-compose method (development)
|
||||||
|
|
||||||
|
```bash
|
||||||
git clone https://codeberg.org/teddit/teddit
|
git clone https://codeberg.org/teddit/teddit
|
||||||
cd teddit
|
cd teddit
|
||||||
docker-compose build
|
docker-compose build
|
||||||
|
@ -73,6 +144,7 @@ The following variables may be set to customize your deployment at runtime.
|
||||||
| flairs_enabled | Enables the rendering of user and link flairs on Teddit. Defaults to **true** |
|
| flairs_enabled | Enables the rendering of user and link flairs on Teddit. Defaults to **true** |
|
||||||
| highlight_controversial | Enables controversial comments to be indicated by a typographical dagger (†). Defaults to **true** |
|
| highlight_controversial | Enables controversial comments to be indicated by a typographical dagger (†). Defaults to **true** |
|
||||||
| api_enabled | Teddit API feature. Might increase loads significantly on your instance. Defaults to **true** |
|
| api_enabled | Teddit API feature. Might increase loads significantly on your instance. Defaults to **true** |
|
||||||
|
| api_force_https | Force HTTPS to Teddit API permalinks (see #285). Defaults to **false** |
|
||||||
| video_enabled | Enables video playback within Teddit. Defaults to **true** |
|
| video_enabled | Enables video playback within Teddit. Defaults to **true** |
|
||||||
| redis_enabled | Enables Redis caching. If disabled, does not allow for any caching of Reddit API calls. Defaults to **true** |
|
| redis_enabled | Enables Redis caching. If disabled, does not allow for any caching of Reddit API calls. Defaults to **true** |
|
||||||
| redis_db | Sets the redis DB name, if required |
|
| redis_db | Sets the redis DB name, if required |
|
||||||
|
@ -97,9 +169,9 @@ The following variables may be set to customize your deployment at runtime.
|
||||||
| post_comments_sort | Defines default sort preference. Options are *confidence* (default sorting option in Reddit), *top*, *new*, *controversal*, *old*, *random*, *qa*, *live*. Defaults to **confidence** |
|
| post_comments_sort | Defines default sort preference. Options are *confidence* (default sorting option in Reddit), *top*, *new*, *controversal*, *old*, *random*, *qa*, *live*. Defaults to **confidence** |
|
||||||
| reddit_app_id | If "use_reddit_oauth" config key is set to true, you have to obtain your Reddit app ID. For testing purposes it's okay to use this project's default app ID. Create your Reddit app here: https://old.reddit.com/prefs/apps/. Make sure to create an "installed app" type of app. Default is **ABfYqdDc9qPh1w** |
|
| reddit_app_id | If "use_reddit_oauth" config key is set to true, you have to obtain your Reddit app ID. For testing purposes it's okay to use this project's default app ID. Create your Reddit app here: https://old.reddit.com/prefs/apps/. Make sure to create an "installed app" type of app. Default is **ABfYqdDc9qPh1w** |
|
||||||
| domain_replacements | Replacements for domains in outgoing links. Tuples with regular expressions to match, and replacement values. This is in addition to user-level configuration of privacyDomains. Defaults to **[]** |
|
| domain_replacements | Replacements for domains in outgoing links. Tuples with regular expressions to match, and replacement values. This is in addition to user-level configuration of privacyDomains. Defaults to **[]** |
|
||||||
| cache_control | *Boolean* If true, teddit will automatically try to keep the size of the cache directory under ```config.cache_max_size```. Defaults to **true** |
|
| cache_control | *Boolean* If true, teddit will automatically remove all cached static files. Defaults to **true** |
|
||||||
| cache_max_size | In Megabytes (MB), how much can we cache media files to the disk? Default is 3000 MB (~3 GB). Note: This is not perfectly exact limit. Defaults to **3000** |
|
| cache_control_interval | How often the cache directory for static files is emptied (in hours). Default is every 24 hours. Requires cache_control to be true. Defaults to **24** |
|
||||||
| cache_control_interval | How often the size of the cache directory is checked. Default is every 30 minutes. Defaults to **1000 * 60 * 30** |
|
| suggested_subreddits | Array of suggested subreddits, which are displayed in the top bar (if the user doesn't have any subscriptions) and in the cleaned home page. Defaults to Reddit's default suggested subreddits. |
|
||||||
|
|
||||||
### Manual
|
### Manual
|
||||||
|
|
||||||
|
@ -107,13 +179,13 @@ The following variables may be set to customize your deployment at runtime.
|
||||||
|
|
||||||
1. (Optional) Install [redis-server](https://redis.io).
|
1. (Optional) Install [redis-server](https://redis.io).
|
||||||
|
|
||||||
Highly recommended – it works as a cache for Reddit API calls.
|
Highly recommended – it works as a cache for Reddit API calls.
|
||||||
|
|
||||||
1. (Optional) Install [ffmpeg](https://ffmpeg.org).
|
1. (Optional) Install [ffmpeg](https://ffmpeg.org).
|
||||||
|
|
||||||
It's needed if you want to support videos.
|
It's needed if you want to support videos.
|
||||||
|
|
||||||
```console
|
```bash
|
||||||
# Linux
|
# Linux
|
||||||
apt install redis-server ffmpeg
|
apt install redis-server ffmpeg
|
||||||
|
|
||||||
|
@ -123,7 +195,7 @@ The following variables may be set to customize your deployment at runtime.
|
||||||
|
|
||||||
1. Clone and set up the repository.
|
1. Clone and set up the repository.
|
||||||
|
|
||||||
```console
|
```bash
|
||||||
git clone https://codeberg.org/teddit/teddit
|
git clone https://codeberg.org/teddit/teddit
|
||||||
cd teddit
|
cd teddit
|
||||||
npm install --no-optional
|
npm install --no-optional
|
||||||
|
@ -132,4 +204,26 @@ The following variables may be set to customize your deployment at runtime.
|
||||||
npm start
|
npm start
|
||||||
```
|
```
|
||||||
|
|
||||||
Teddit should now be running at <http://localhost:8080>.
|
Teddit should now be running at <http://localhost:8080>.
|
||||||
|
|
||||||
|
You can also run teddit from a process manager like [pm2](https://www.npmjs.com/package/pm2):
|
||||||
|
|
||||||
|
```
|
||||||
|
## To run:
|
||||||
|
npm install pm2 -g
|
||||||
|
pm2 start app.js --name teddit
|
||||||
|
|
||||||
|
## To run on startup:
|
||||||
|
pm2 startup
|
||||||
|
pm2 save ## if using systemd, see below.
|
||||||
|
|
||||||
|
## To restart or stop
|
||||||
|
pm2 restart teddit
|
||||||
|
pm2 stop teddit
|
||||||
|
```
|
||||||
|
|
||||||
|
See also the [pm2 instructions for running a project on startup](https://pm2.keymetrics.io/docs/usage/startup/). In particular, if using systemd, see the section on how to modify the systemd init file so that it runs after your system connects to the network.
|
||||||
|
|
||||||
|
## Legal
|
||||||
|
|
||||||
|
Teddit does not host any content. All content shown on any Teddit instances is from Reddit™. Reddit is a trademark of Reddit Inc. Teddit is not affiliated with Reddit Inc. Any issues with content shown on any Teddit instances need to be reported to Reddit, not the instance host's internet provider or domain provider.
|
||||||
|
|
58
app.js
58
app.js
|
@ -12,41 +12,7 @@ const pug = require('pug');
|
||||||
const compression = require('compression');
|
const compression = require('compression');
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const cookieParser = require('cookie-parser');
|
const cookieParser = require('cookie-parser');
|
||||||
const r = require('redis');
|
const { redis } = require('./inc/redis');
|
||||||
|
|
||||||
const redis = (() => {
|
|
||||||
if (!config.redis_enabled) {
|
|
||||||
// Stub Redis if disabled
|
|
||||||
return {
|
|
||||||
get: (_, callback) => callback(null, null),
|
|
||||||
setex: (_, _1, _2, callback) => callback(null),
|
|
||||||
on: () => {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const redisOptions = {
|
|
||||||
host: '127.0.0.1',
|
|
||||||
port: 6379,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (config.redis_db) {
|
|
||||||
redisOptions.db = config.redis_db;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.redis_host) {
|
|
||||||
redisOptions.host = config.redis_host;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.redis_port && config.redis_port > 0) {
|
|
||||||
redisOptions.port = config.redis_port;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.redis_password) {
|
|
||||||
redisOptions.password = config.redis_password;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.createClient(redisOptions);
|
|
||||||
})();
|
|
||||||
|
|
||||||
const nodeFetch = require('node-fetch');
|
const nodeFetch = require('node-fetch');
|
||||||
const fetch = config.http_proxy
|
const fetch = config.http_proxy
|
||||||
|
@ -83,7 +49,7 @@ let https = null;
|
||||||
if (config.https_enabled) {
|
if (config.https_enabled) {
|
||||||
const privateKey = fs.readFileSync(`${config.cert_dir}/privkey.pem`, 'utf8');
|
const privateKey = fs.readFileSync(`${config.cert_dir}/privkey.pem`, 'utf8');
|
||||||
const certificate = fs.readFileSync(`${config.cert_dir}/cert.pem`, 'utf8');
|
const certificate = fs.readFileSync(`${config.cert_dir}/cert.pem`, 'utf8');
|
||||||
const ca = fs.readFileSync(`${config.cert_dir}/chain.pem`, 'utf8');
|
const ca = fs.readFileSync(`${config.cert_dir}/fullchain.pem`, 'utf8');
|
||||||
const credentials = {
|
const credentials = {
|
||||||
key: privateKey,
|
key: privateKey,
|
||||||
cert: certificate,
|
cert: certificate,
|
||||||
|
@ -140,6 +106,13 @@ app.use(express.static(`${__dirname}/static`));
|
||||||
app.set('views', './views');
|
app.set('views', './views');
|
||||||
app.set('view engine', 'pug');
|
app.set('view engine', 'pug');
|
||||||
|
|
||||||
|
if (config.redirect_http_to_https) {
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
if (req.secure) next();
|
||||||
|
else res.redirect(`https://${req.headers.host}${req.url}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const redditAPI = require('./inc/initRedditApi.js')(fetch);
|
const redditAPI = require('./inc/initRedditApi.js')(fetch);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -155,19 +128,6 @@ app.use('/', allRoutes);
|
||||||
// The old routes
|
// The old routes
|
||||||
//require('./routes')(app, redis, fetch, redditAPI);
|
//require('./routes')(app, redis, fetch, redditAPI);
|
||||||
|
|
||||||
if (config.redirect_http_to_https) {
|
|
||||||
app.use((req, res, next) => {
|
|
||||||
if (req.secure) next();
|
|
||||||
else res.redirect(`https://${req.headers.host}${req.url}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
redis.on('error', (error) => {
|
|
||||||
if (error) {
|
|
||||||
console.error(`Redis error: ${error}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const cacheControl = require('./cacheControl.js');
|
const cacheControl = require('./cacheControl.js');
|
||||||
cacheControl.removeCacheFiles();
|
cacheControl.removeCacheFiles();
|
||||||
|
|
||||||
|
|
|
@ -1,66 +1,32 @@
|
||||||
module.exports.removeCacheFiles = function() {
|
module.exports.removeCacheFiles = function() {
|
||||||
const fs = require('fs')
|
const config = require('./config');
|
||||||
const config = require('./config')
|
|
||||||
const pics = './static/pics'
|
async function deleteStatic() {
|
||||||
const flairs = './static/pics/flairs'
|
const fs = require('fs');
|
||||||
const icons = './static/pics/icons'
|
const pics = './static/pics/';
|
||||||
const thumbs = './static/pics/thumbs'
|
const vids = './static/vids/';
|
||||||
const vids = './static/vids'
|
|
||||||
let util = require('util')
|
fs.rmdir(pics, { recursive: true, force: true }, () => {
|
||||||
let spawn = require('child_process').spawn
|
fs.rmdir(vids, { recursive: true, force: true }, () => {
|
||||||
|
['pics/thumbs', 'pics/flairs', 'pics/icons', 'vids'].map((d) => `./static/${d}`)
|
||||||
let usage
|
.filter((d) => !fs.existsSync(d))
|
||||||
const limit = config.cache_max_size
|
.forEach((d) => fs.mkdirSync(d, { recursive: true }));
|
||||||
|
|
||||||
function getUsage() {
|
console.log('Cleared cached static media files. You can turn this off by setting the config.cache_control to false.');
|
||||||
return new Promise((resolve, reject) => {
|
});
|
||||||
let size = spawn('du', ['-sBM', './static/'])
|
});
|
||||||
size.stdout.on('data', function (data) {
|
|
||||||
data = data.toString()
|
|
||||||
let lines = data.split('\n')
|
|
||||||
if(lines) {
|
|
||||||
for(let i = lines.length; i >= 0; i--) {
|
|
||||||
if(lines[i] && lines[i].includes('./static/')) {
|
|
||||||
usage = parseInt(lines[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resolve(usage)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteFiles() {
|
if(config.cache_control) {
|
||||||
return new Promise(async (resolve, reject) => {
|
deleteStatic();
|
||||||
usage = await getUsage()
|
|
||||||
if(usage > limit) {
|
let hours = config.cache_control_interval;
|
||||||
const { exec } = require('child_process')
|
if (hours < 1 || hours > 10000 || isNaN(hours)) {
|
||||||
exec(`cd ${pics} && ls -1btr -Iflairs -Iicons -Ithumbs -I.gitignore | head -50 | xargs rm -f --`)
|
hours = 24;
|
||||||
exec(`cd ${flairs} && ls -1btr -I.gitignore | head -6 | xargs rm -f --`)
|
|
||||||
exec(`cd ${icons} && ls -1btr -I.gitignore | head -6 | xargs rm -f --`)
|
|
||||||
exec(`cd ${thumbs} && ls -1btr -I.gitignore | head -80 | xargs rm -f --`)
|
|
||||||
exec(`cd ${vids} && ls -1btr -I.gitignore | head -2 | xargs rm -f --`)
|
|
||||||
}
|
|
||||||
resolve(1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
usage = await getUsage()
|
|
||||||
if(usage > limit) {
|
|
||||||
console.log('Started removeCacheFiles()')
|
|
||||||
while(usage > limit) {
|
|
||||||
await deleteFiles()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(config.cache_control) {
|
|
||||||
main()
|
|
||||||
|
|
||||||
const interval_ms = config.cache_control_interval
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
main()
|
deleteStatic();
|
||||||
}, interval_ms)
|
}, 1000 * 60 * 60 * hours);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,13 @@ const config = {
|
||||||
use_reddit_oauth: process.env.USE_REDDIT_OAUTH === 'true' || false, // If false, teddit uses Reddit's public API. If true, you need to have your own Reddit app ID (enter the app ID to the "reddit_app_id" config key).
|
use_reddit_oauth: process.env.USE_REDDIT_OAUTH === 'true' || false, // If false, teddit uses Reddit's public API. If true, you need to have your own Reddit app ID (enter the app ID to the "reddit_app_id" config key).
|
||||||
cert_dir: process.env.CERT_DIR || '', // For example '/home/teddit/letsencrypt/live/teddit.net', if you are using https. No trailing slash.
|
cert_dir: process.env.CERT_DIR || '', // For example '/home/teddit/letsencrypt/live/teddit.net', if you are using https. No trailing slash.
|
||||||
theme: process.env.THEME || 'auto', // One of: 'dark', 'sepia', 'auto', ''. Auto theme uses browser's theme detection (Dark or White theme). White theme is set by the empty the option ('').
|
theme: process.env.THEME || 'auto', // One of: 'dark', 'sepia', 'auto', ''. Auto theme uses browser's theme detection (Dark or White theme). White theme is set by the empty the option ('').
|
||||||
flairs_enabled: process.env.FLAIRS_ENABLED !== 'true' || true, // Enables the rendering of user and link flairs on teddit
|
clean_homepage: !('CLEAN_HOMEPAGE' in process.env) || process.env.CLEAN_HOMEPAGE === 'true', // Allows the clean homepage to be used (similar to invidious), instead of the usual reddit-like frontpage
|
||||||
highlight_controversial: process.env.HIGHLIGHT_CONTROVERSIAL !== 'true' || true, // Enables controversial comments to be indicated by a typographical dagger (†)
|
flairs_enabled: !('FLAIRS_ENABLED' in process.env) || process.env.FLAIRS_ENABLED === 'true', // Enables the rendering of user and link flairs on teddit
|
||||||
api_enabled: process.env.API_ENABLED !== 'true' || true, // Teddit API feature. Might increase loads significantly on your instance.
|
highlight_controversial: !('HIGHLIGHT_CONTROVERSIAL' in process.env) || process.env.HIGHLIGHT_CONTROVERSIAL === 'true', // Enables controversial comments to be indicated by a typographical dagger (†)
|
||||||
video_enabled: process.env.VIDEO_ENABLED !== 'true' || true,
|
api_enabled: !('API_ENABLED' in process.env) || process.env.API_ENABLED === 'true', // Teddit API feature. Might increase loads significantly on your instance.
|
||||||
redis_enabled: process.env.REDIS_ENABLED !== 'true' || true, // If disabled, does not cache Reddit API calls
|
api_force_https: process.env.API_FORCE_HTTPS === 'true' || false, // Force HTTPS to Teddit API permalinks (see #285).
|
||||||
|
video_enabled: !('VIDEO_ENABLED' in process.env) || process.env.VIDEO_ENABLED === 'true',
|
||||||
|
redis_enabled: !('REDIS_ENABLED' in process.env) || process.env.REDIS_ENABLED === 'true', // If disabled, does not cache Reddit API calls
|
||||||
redis_db: process.env.REDIS_DB,
|
redis_db: process.env.REDIS_DB,
|
||||||
redis_host: process.env.REDIS_HOST || '127.0.0.1',
|
redis_host: process.env.REDIS_HOST || '127.0.0.1',
|
||||||
redis_password: process.env.REDIS_PASSWORD,
|
redis_password: process.env.REDIS_PASSWORD,
|
||||||
|
@ -18,23 +20,24 @@ const config = {
|
||||||
https_enabled: process.env.HTTPS_ENABLED === 'true' || false,
|
https_enabled: process.env.HTTPS_ENABLED === 'true' || false,
|
||||||
redirect_http_to_https: process.env.REDIRECT_HTTP_TO_HTTPS === 'true' || false,
|
redirect_http_to_https: process.env.REDIRECT_HTTP_TO_HTTPS === 'true' || false,
|
||||||
redirect_www: process.env.REDIRECT_WWW === 'true' || false,
|
redirect_www: process.env.REDIRECT_WWW === 'true' || false,
|
||||||
use_compression: process.env.USE_COMPRESSION !== 'true' || true,
|
use_compression: !('USE_COMPRESSION' in process.env) || process.env.USE_COMPRESSION === 'true',
|
||||||
use_view_cache: process.env.USE_VIEW_CACHE === 'true' || false,
|
use_view_cache: process.env.USE_VIEW_CACHE === 'true' || false,
|
||||||
use_helmet: process.env.USE_HELMET === 'true' || false, // Recommended to be true when using https
|
use_helmet: process.env.USE_HELMET === 'true' || false, // Recommended to be true when using https
|
||||||
use_helmet_hsts: process.env.USE_HELMET_HSTS === 'true' || false, // Recommended to be true when using https
|
use_helmet_hsts: process.env.USE_HELMET_HSTS === 'true' || false, // Recommended to be true when using https
|
||||||
trust_proxy: process.env.TRUST_PROXY === 'true' || false, // Enable trust_proxy if you are using reverse proxy like nginx
|
trust_proxy: process.env.TRUST_PROXY === 'true' || false, // Enable trust_proxy if you are using reverse proxy like nginx
|
||||||
trust_proxy_address: process.env.TRUST_PROXY_ADDRESS || '127.0.0.1',
|
trust_proxy_address: process.env.TRUST_PROXY_ADDRESS || '127.0.0.1',
|
||||||
http_proxy: process.env.HTTP_PROXY,
|
http_proxy: process.env.HTTP_PROXY,
|
||||||
nsfw_enabled: process.env.NSFW_ENABLED !== 'true' || true, // Enable NSFW (over 18) content. If false, a warning is shown to the user before opening any NSFW post. When the NFSW content is disabled, NSFW posts are hidden from subreddits and from user page feeds. Note: Users can set this to true or false from their preferences.
|
nsfw_enabled: !('NSFW_ENABLED' in process.env) || process.env.NSFW_ENABLED === 'true', // Enable NSFW (over 18) content. If false, a warning is shown to the user before opening any NSFW post. When the NFSW content is disabled, NSFW posts are hidden from subreddits and from user page feeds. Note: Users can set this to true or false from their preferences.
|
||||||
videos_muted: process.env.VIDEOS_MUTED !== 'true' || true, // Automatically mute all videos in posts
|
videos_muted: !('VIDEOS_MUTED' in process.env) || process.env.VIDEOS_MUTED === 'true', // Automatically mute all videos in posts
|
||||||
post_comments_sort: process.env.POST_COMMENTS_SORT || 'confidence', // "confidence" is the default sorting in Reddit. Must be one of: confidence, top, new, controversial, old, random, qa, live.
|
post_comments_sort: process.env.POST_COMMENTS_SORT || 'confidence', // "confidence" is the default sorting in Reddit. Must be one of: confidence, top, new, controversial, old, random, qa, live.
|
||||||
reddit_app_id: process.env.REDDIT_APP_ID || 'ABfYqdDc9qPh1w', // If "use_reddit_oauth" config key is set to true, you have to obtain your Reddit app ID. For testing purposes it's okay to use this project's default app ID. Create your Reddit app here: https://old.reddit.com/prefs/apps/. Make sure to create an "installed app" type of app.
|
reddit_app_id: process.env.REDDIT_APP_ID || 'ABfYqdDc9qPh1w', // If "use_reddit_oauth" config key is set to true, you have to obtain your Reddit app ID. For testing purposes it's okay to use this project's default app ID. Create your Reddit app here: https://old.reddit.com/prefs/apps/. Make sure to create an "installed app" type of app.
|
||||||
domain_replacements: process.env.DOMAIN_REPLACEMENTS
|
domain_replacements: process.env.DOMAIN_REPLACEMENTS
|
||||||
? (JSON.parse(process.env.DOMAIN_REPLACEMENTS).map(([p, r]) => [new RegExp(p, 'gm'), r]))
|
? (JSON.parse(process.env.DOMAIN_REPLACEMENTS).map(([p, r]) => [new RegExp(p, 'gm'), r]))
|
||||||
: [], // Replacements for domains in outgoing links. Tuples with regular expressions to match, and replacement values. This is in addition to user-level configuration of privacyDomains.
|
: [], // Replacements for domains in outgoing links. Tuples with regular expressions to match, and replacement values. This is in addition to user-level configuration of privacyDomains.
|
||||||
cache_control: process.env.CACHE_CONTROL !== 'true' || true, // If true, teddit will automatically try to keep the size of the cache directory (static) under config.cache_max_size. By default this is set to true.
|
cache_control: !('CACHE_CONTROL' in process.env) || process.env.CACHE_CONTROL === 'true', // If true, teddit will automatically remove all cached static files. By default this is set to true.
|
||||||
cache_max_size: process.env.CACHE_MAX_SIZE || 3000, // How much can we cache to the disk? Default is 3000 MB (~3 GB). Note: This is not perfectly exact limit.
|
cache_control_interval: process.env.CACHE_CONTROL_INTERVAL || 24, // How often the cache directory for static files is emptied (in hours). Requires cache_control to be true. Default is every 24 hours.
|
||||||
cache_control_interval: process.env.CACHE_CONTROL_INTERVAL || 1000 * 60 * 30, // How often the size of the cache directory (static/) is checked. Default is every 30 minutes.
|
show_upvoted_percentage: !('SHOW_UPVOTED_PERCENTAGE' in process.env) || process.env.SHOW_UPVOTED_PERCENTAGE === 'true',
|
||||||
|
show_upvotes: !('SHOW_UPVOTES' in process.env) || process.env.SHOW_UPVOTES === 'true', // If true, teddit will show number of upvotes in posts and points in comments.
|
||||||
post_media_max_heights: {
|
post_media_max_heights: {
|
||||||
/**
|
/**
|
||||||
* Sets the max-height value for images and videos in posts.
|
* Sets the max-height value for images and videos in posts.
|
||||||
|
@ -70,9 +73,39 @@ const config = {
|
||||||
initial_limit: 100, // This is the amount of page loads one IP address can make in one minute without getting limited.
|
initial_limit: 100, // This is the amount of page loads one IP address can make in one minute without getting limited.
|
||||||
limit_after_limited: 30 // When an IP is limited, this is the amount of page loads the IP can make in one minute.
|
limit_after_limited: 30 // When an IP is limited, this is the amount of page loads the IP can make in one minute.
|
||||||
},
|
},
|
||||||
valid_media_domains: ['preview.redd.it', 'external-preview.redd.it', 'i.redd.it', 'v.redd.it', 'a.thumbs.redditmedia.com', 'b.thumbs.redditmedia.com', 'emoji.redditmedia.com', 'styles.redditmedia.com', 'www.redditstatic.com', 'thumbs.gfycat.com', 'i.ytimg.com'],
|
valid_media_domains: process.env.VALID_MEDIA_DOMAINS
|
||||||
|
? JSON.parse(process.env.VALID_MEDIA_DOMAINS)
|
||||||
|
: ['preview.redd.it', 'external-preview.redd.it', 'i.redd.it', 'v.redd.it', 'a.thumbs.redditmedia.com', 'b.thumbs.redditmedia.com', 'emoji.redditmedia.com', 'styles.redditmedia.com', 'www.redditstatic.com', 'thumbs.gfycat.com', 'i.ytimg.com', 'i.imgur.com'],
|
||||||
valid_embed_video_domains: ['gfycat.com', 'youtube.com'],
|
valid_embed_video_domains: ['gfycat.com', 'youtube.com'],
|
||||||
reddit_api_error_text: `Seems like your instance is either blocked (e.g. due to API rate limiting), reddit is currently down, or your API key is expired and not renewd properly. This can also happen for other reasons.`
|
reddit_api_error_text: `Seems like your instance is either blocked (e.g. due to API rate limiting), reddit is currently down, or your API key is expired and not renewd properly. This can also happen for other reasons.`,
|
||||||
|
/**
|
||||||
|
* Here you can configure the suggested subreddits which are visible in the
|
||||||
|
* cleaned homepage, and in the top bar.
|
||||||
|
* You should keep at least 'All', and 'Saved'.
|
||||||
|
*
|
||||||
|
* If you set your configs with an environment variables for example with
|
||||||
|
* docker-compose.yml, your suggested_subreddits config could be something
|
||||||
|
* like this (note the quotes):
|
||||||
|
* - SUGGESTED_SUBREDDITS=["Popular", "All", "Saved", "selfhosted", "linux", "datahoarder", "Monero"]
|
||||||
|
* or
|
||||||
|
* - 'SUGGESTED_SUBREDDITS=["Popular", "All", "Saved", "selfhosted", "linux", "datahoarder", "Monero"]'
|
||||||
|
*/
|
||||||
|
suggested_subreddits: process.env.SUGGESTED_SUBREDDITS
|
||||||
|
? JSON.parse(process.env.SUGGESTED_SUBREDDITS)
|
||||||
|
:
|
||||||
|
['Popular', 'All', 'Saved', 'AskReddit', 'pics', 'news',
|
||||||
|
'worldnews', 'funny', 'tifu', 'videos', 'gaming', 'aww',
|
||||||
|
'todayilearned', 'gifs', 'Art', 'explainlikeimfive',
|
||||||
|
'movies', 'Jokes', 'TwoXChromosomes',
|
||||||
|
'mildlyinteresting', 'LifeProTips', 'askscience',
|
||||||
|
'IAmA', 'dataisbeautiful', 'books', 'science',
|
||||||
|
'Showerthoughts', 'gadgets', 'Futurology',
|
||||||
|
'nottheonion', 'history', 'sports', 'OldSchoolCool',
|
||||||
|
'GetMotivated', 'DIY', 'photoshopbattles', 'nosleep',
|
||||||
|
'Music', 'space', 'food', 'UpliftingNews', 'EarthPorn',
|
||||||
|
'Documentaries', 'InternetIsBeautiful',
|
||||||
|
'WritingPrompts', 'creepy', 'philosophy',
|
||||||
|
'announcements', 'listentothis', 'blog'],
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
||||||
|
|
|
@ -1,21 +1,16 @@
|
||||||
|
# This docker-compose file is made for development purpose and build from source, if you want to use teddit in production, the README contains a production-ready docker-compose setup.
|
||||||
|
|
||||||
version: "3.8"
|
version: "3.8"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
redis:
|
|
||||||
image: redis:6.2.5-alpine
|
teddit:
|
||||||
command: redis-server
|
container_name: teddit
|
||||||
environment:
|
|
||||||
- REDIS_REPLICATION_MODE=master
|
|
||||||
ports:
|
|
||||||
- "6379:6379"
|
|
||||||
networks:
|
|
||||||
- teddit_net
|
|
||||||
web:
|
|
||||||
build: .
|
build: .
|
||||||
environment:
|
environment:
|
||||||
- REDIS_HOST=redis
|
- REDIS_HOST=teddit-redis
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- "8080:8080"
|
||||||
networks:
|
networks:
|
||||||
- teddit_net
|
- teddit_net
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
@ -23,6 +18,16 @@ services:
|
||||||
interval: 1m
|
interval: 1m
|
||||||
timeout: 3s
|
timeout: 3s
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- teddit-redis
|
||||||
|
|
||||||
|
teddit-redis:
|
||||||
|
container_name: teddit-redis
|
||||||
|
image: redis:6.2.5-alpine
|
||||||
|
command: redis-server
|
||||||
|
environment:
|
||||||
|
- REDIS_REPLICATION_MODE=master
|
||||||
|
networks:
|
||||||
|
- teddit_net
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
teddit_net:
|
teddit_net:
|
||||||
|
|
118
inc/commons.js
118
inc/commons.js
|
@ -39,8 +39,10 @@ module.exports = function(request, fs) {
|
||||||
this.teddifyUrl = (url, user_preferences) => {
|
this.teddifyUrl = (url, user_preferences) => {
|
||||||
try {
|
try {
|
||||||
let u = new URL(url)
|
let u = new URL(url)
|
||||||
|
let domain_replaced = false
|
||||||
if(u.host === 'www.reddit.com' || u.host === 'reddit.com') {
|
if(u.host === 'www.reddit.com' || u.host === 'reddit.com') {
|
||||||
url = url.replace(u.host, config.domain)
|
url = url.replace(u.host, config.domain)
|
||||||
|
domain_replaced = true
|
||||||
if(u.pathname.startsWith('/gallery/'))
|
if(u.pathname.startsWith('/gallery/'))
|
||||||
url = url.replace('/gallery/', '/comments/')
|
url = url.replace('/gallery/', '/comments/')
|
||||||
}
|
}
|
||||||
|
@ -50,10 +52,15 @@ module.exports = function(request, fs) {
|
||||||
let file_ext = getFileExtension(url)
|
let file_ext = getFileExtension(url)
|
||||||
if(image_exts.includes(file_ext))
|
if(image_exts.includes(file_ext))
|
||||||
url = url.replace(`${u.host}/`, `${config.domain}/pics/w:null_`)
|
url = url.replace(`${u.host}/`, `${config.domain}/pics/w:null_`)
|
||||||
|
domain_replaced = true
|
||||||
if(video_exts.includes(file_ext) || !image_exts.includes(file_ext))
|
if(video_exts.includes(file_ext) || !image_exts.includes(file_ext))
|
||||||
url = url.replace(u.host, `${config.domain}/vids`) + '.mp4'
|
url = url.replace(u.host, `${config.domain}/vids`) + '.mp4'
|
||||||
|
domain_replaced = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(domain_replaced && !config.https_enabled) {
|
||||||
|
url = url.replace('https:', 'http:')
|
||||||
|
}
|
||||||
} catch(e) { }
|
} catch(e) { }
|
||||||
url = replaceDomains(url, user_preferences)
|
url = replaceDomains(url, user_preferences)
|
||||||
return url
|
return url
|
||||||
|
@ -182,28 +189,113 @@ module.exports = function(request, fs) {
|
||||||
|
|
||||||
this.replaceUserDomains = (str, user_preferences) => {
|
this.replaceUserDomains = (str, user_preferences) => {
|
||||||
|
|
||||||
let redditRegex = /([A-z.]+\.)?(reddit(\.com)|redd(\.it))/gm;
|
let redditRegex = /(?<=href=")(https?:\/\/)([A-z.]+\.)?(reddit(\.com)|redd(\.it))(?=.+")/gm;
|
||||||
let youtubeRegex = /([A-z.]+\.)?youtu(be\.com|\.be)/gm;
|
let youtubeRegex = /(?<=href=")(https?:\/\/)([A-z.]+\.)?youtu(be\.com|\.be)(?=.+")/gm;
|
||||||
let twitterRegex = /([A-z.]+\.)?twitter\.com/gm;
|
let twitterRegex = /(?<=href=")(https?:\/\/)(www\.)?twitter\.com(?=.+")/gm;
|
||||||
let instagramRegex = /([A-z.]+\.)?instagram.com/gm;
|
let instagramRegex = /(?<=href=")(https?:\/\/)(www+\.)?instagram.com(?=.+")/gm;
|
||||||
|
let quoraRegex = /(?<=href=")(https?:\/\/)([A-z.]+\.)?quora\.com(?=.+")/gm;
|
||||||
|
|
||||||
str = str.replace(redditRegex, config.domain)
|
/*
|
||||||
|
* regex pattern to replace imgur links (imgur.com, imgur.io, i.stack.imgur.com)
|
||||||
|
* source: https://github.com/libredirect/libredirect/blob/32c4a0211e3b721d46219c05cba93f1a42cf3773/src/config/config.json#L317
|
||||||
|
* license: GNU GPL v3 License -> https://github.com/libredirect/libredirect/blob/32c4a0211e3b721d46219c05cba93f1a42cf3773/LICENSE
|
||||||
|
*/
|
||||||
|
let imgurRegex = /(?<=href=")(https?:\/{2})([im]\.)?(stack\.)?imgur\.(com|io)(?=.+")/gm;
|
||||||
|
|
||||||
|
let protocol = config.https_enabled || config.api_force_https ? 'https://' : 'http://'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special handling for reddit media domains in comments hrefs or img srcs.
|
||||||
|
* For example a comment might have a direct links to images in i.redd.it:
|
||||||
|
* <a href="https://i.redd.it/hly9gyg9gjh81.png">Just refer to this </a>
|
||||||
|
* We want to rewrite these hrefs, but we also need to include the domain
|
||||||
|
* for our backend, so we know where to fetch the media from.
|
||||||
|
* That comment URL then becomes like this after rewriting it:
|
||||||
|
* <a href="https://teddit.net/hly9gyg9gjh81.png?teddit_proxy=i.redd.it">Just refer to this </a>
|
||||||
|
* And then in our backend, we check if we have a 'teddit_proxy' in the req
|
||||||
|
* query, and proceed to proxy if it does.
|
||||||
|
*/
|
||||||
|
const replacable_media_domains = ['i.redd.it', 'v.redd.it', 'external-preview.redd.it', 'preview.redd.it']
|
||||||
|
replacable_media_domains.forEach((domain) => {
|
||||||
|
if (str.includes(domain + "/")) {
|
||||||
|
const regex = new RegExp(`(?<=(href|src)=")(https?:\/\/)([A-z.]+\.)?(${domain})(.+?(?="))`, 'gm')
|
||||||
|
const hrefs = str.match(regex)
|
||||||
|
if (!hrefs) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
hrefs.forEach((url) => {
|
||||||
|
let original_url = url
|
||||||
|
const valid_exts = ['png', 'jpg', 'jpeg', 'mp4', 'gif', 'gifv']
|
||||||
|
const file_ext = getFileExtension(url)
|
||||||
|
if (valid_exts.includes(file_ext)) {
|
||||||
|
url = url.replace(domain, config.domain)
|
||||||
|
|
||||||
|
// append the domain info to the query, for teddit backend
|
||||||
|
let u = new URL(url)
|
||||||
|
if (u.search) {
|
||||||
|
url += '&teddit_proxy=' + domain
|
||||||
|
} else {
|
||||||
|
url += '?teddit_proxy=' + domain
|
||||||
|
}
|
||||||
|
|
||||||
|
// also replace the protocol for instances using http only
|
||||||
|
if (protocol === 'http://' && u.protocol === 'https:') {
|
||||||
|
url.replace('https://', protocol)
|
||||||
|
}
|
||||||
|
str = str.replace(original_url, url)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Continue the normal replace logic
|
||||||
|
|
||||||
|
str = str.replace(redditRegex, protocol + config.domain)
|
||||||
|
|
||||||
if(typeof(user_preferences) == 'undefined')
|
if(typeof(user_preferences) == 'undefined')
|
||||||
return str
|
return str
|
||||||
|
|
||||||
if(typeof(user_preferences.domain_youtube) != 'undefined')
|
if(typeof(user_preferences.domain_youtube) != 'undefined')
|
||||||
if(user_preferences.domain_youtube)
|
if(user_preferences.domain_youtube){
|
||||||
str = str.replace(youtubeRegex, user_preferences.domain_youtube)
|
if (!youtubeRegex.test(str)){
|
||||||
|
youtubeRegex = /(https?:\/\/)([A-z.]+\.)?youtu(be\.com|\.be)(?=.+)/gm;
|
||||||
|
}
|
||||||
|
str = str.replace(youtubeRegex, protocol + user_preferences.domain_youtube);
|
||||||
|
}
|
||||||
|
|
||||||
if(typeof(user_preferences.domain_twitter) != 'undefined')
|
if(typeof(user_preferences.domain_twitter) != 'undefined')
|
||||||
if(user_preferences.domain_twitter)
|
if(user_preferences.domain_twitter){
|
||||||
str = str.replace(twitterRegex, user_preferences.domain_twitter)
|
if (!twitterRegex.test(str)){
|
||||||
|
twitterRegex = /(https?:\/\/)(www\.)?twitter\.com(?=.)/gm;
|
||||||
if(typeof(user_preferences.domain_instagram) != 'undefined')
|
}
|
||||||
if(user_preferences.domain_instagram)
|
str = str.replace(twitterRegex, protocol + user_preferences.domain_twitter)
|
||||||
str = str.replace(instagramRegex, user_preferences.domain_instagram)
|
}
|
||||||
|
|
||||||
|
if(typeof(user_preferences.domain_instagram) != 'undefined'){
|
||||||
|
if(user_preferences.domain_instagram){
|
||||||
|
if (!instagramRegex.test(str)){
|
||||||
|
instagramRegex = /(https?:\/\/)(www+\.)?instagram.com(?=.)/gm;
|
||||||
|
}
|
||||||
|
str = str.replace(instagramRegex, protocol + user_preferences.domain_instagram);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(typeof(user_preferences.domain_quora) != 'undefined'){
|
||||||
|
if(user_preferences.domain_quora){
|
||||||
|
if (!quoraRegex.test(str)){
|
||||||
|
quoraRegex = /(https?:\/\/)([A-z.]+\.)?quora\.com(?=.)/gm;
|
||||||
|
}
|
||||||
|
str = str.replace(quoraRegex, protocol + user_preferences.domain_quora)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(typeof(user_preferences.domain_imgur) != 'undefined'){
|
||||||
|
if(user_preferences.domain_imgur){
|
||||||
|
if (!imgurRegex.test(str)){
|
||||||
|
imgurRegex = /(https?:\/{2})([im]\.)?(stack\.)?imgur\.(com|io)(?=.)/gm;
|
||||||
|
}
|
||||||
|
str = str.replace(imgurRegex, protocol + user_preferences.domain_imgur)
|
||||||
|
}
|
||||||
|
}
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,14 @@ module.exports = function() {
|
||||||
let comments_html
|
let comments_html
|
||||||
function commentAuthor(comment, classlist, submitter, moderator) {
|
function commentAuthor(comment, classlist, submitter, moderator) {
|
||||||
let classes = classlist.join(' ')
|
let classes = classlist.join(' ')
|
||||||
if (comment.author === '[deleted]')
|
if (comment.author === '[deleted]') {
|
||||||
return `<span class="${classes}">[deleted]</span>`
|
var reveddit_url = "https://www.reveddit.com" + post_url.substr(post_url.indexOf('/r/')) + comments.id
|
||||||
else
|
return `<span class="${classes}"><a href="${reveddit_url}" style='color: #cc6a6a !important;'>[deleted]</a></span>`
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
return `<a href="/u/${comment.author}" class="${classes}">${comment.author}</a>${submitter || ''}${moderator || ''}`
|
return `<a href="/u/${comment.author}" class="${classes}">${comment.author}</a>${submitter || ''}${moderator || ''}`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!user_preferences)
|
if(!user_preferences)
|
||||||
|
@ -115,6 +119,7 @@ module.exports = function() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let link = comments.parent_id.split('_')[1]
|
let link = comments.parent_id.split('_')[1]
|
||||||
|
link = post_url + link
|
||||||
comments_html = `
|
comments_html = `
|
||||||
<div class="load-more-comments">
|
<div class="load-more-comments">
|
||||||
<a href="${link}/#c">continue this thread</a>
|
<a href="${link}/#c">continue this thread</a>
|
||||||
|
@ -205,7 +210,7 @@ module.exports = function() {
|
||||||
}
|
}
|
||||||
comments_html += replies_html + '</details></div>'
|
comments_html += replies_html + '</details></div>'
|
||||||
} else {
|
} else {
|
||||||
if(comment.children.length > 0) {
|
if(comment.children.length > 0) {
|
||||||
let parent_id = comment.parent_id.split('_')[1]
|
let parent_id = comment.parent_id.split('_')[1]
|
||||||
let load_comms_href = parent_id
|
let load_comms_href = parent_id
|
||||||
|
|
||||||
|
@ -215,7 +220,8 @@ module.exports = function() {
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
} else {
|
} else {
|
||||||
let link = comment.parent_id.split('_')[1]
|
let link = comment.parent_id.split('_')[1]
|
||||||
|
link = post_url + link
|
||||||
comments_html = `
|
comments_html = `
|
||||||
<div class="load-more-comments">
|
<div class="load-more-comments">
|
||||||
<a href="${link}/#c">continue this thread</a>
|
<a href="${link}/#c">continue this thread</a>
|
||||||
|
|
|
@ -28,8 +28,14 @@ async function fromJson(data, user_preferences, subreddit_front) {
|
||||||
result.domain = data.domain
|
result.domain = data.domain
|
||||||
result.is_video = data.is_video
|
result.is_video = data.is_video
|
||||||
result.media = data.media
|
result.media = data.media
|
||||||
result.duration = data.is_video ? data.media.reddit_video ? data.media.reddit_video.duration : void 0 : void 0
|
result.duration = null
|
||||||
result.images = null
|
result.images = null
|
||||||
|
|
||||||
|
if(data.is_video && data.media) {
|
||||||
|
if(data.media.reddit_video) {
|
||||||
|
result.duration = data.media.reddit_video.duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Moderation attributes
|
// Moderation attributes
|
||||||
result.locked = data.locked
|
result.locked = data.locked
|
||||||
|
|
|
@ -30,7 +30,7 @@ module.exports = function(fetch) {
|
||||||
} else {
|
} else {
|
||||||
console.error(`Something went wrong while trying to get an access token from reddit API. ${result.status} – ${result.statusText}`)
|
console.error(`Something went wrong while trying to get an access token from reddit API. ${result.status} – ${result.statusText}`)
|
||||||
console.error(reddit_api_error_text)
|
console.error(reddit_api_error_text)
|
||||||
return res.render('index', { json: null, http_status_code: result.status })
|
return res.render('frontpage', { json: null, http_status_code: result.status, instance_config: config })
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.log(`Error while obtaining a reddit API key.`, error)
|
console.log(`Error while obtaining a reddit API key.`, error)
|
||||||
|
@ -66,14 +66,14 @@ module.exports = function(fetch) {
|
||||||
} else {
|
} else {
|
||||||
console.error(`Something went wrong while fetching data from reddit API. ${result.status} – ${result.statusText}`)
|
console.error(`Something went wrong while fetching data from reddit API. ${result.status} – ${result.statusText}`)
|
||||||
console.error(reddit_api_error_text)
|
console.error(reddit_api_error_text)
|
||||||
return res.render('index', { json: null, http_status_code: result.status })
|
return res.render('frontpage', { json: null, http_status_code: result.status, instance_config: config })
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.log(`Error while refreshing the reddit API key.`, error)
|
console.log(`Error while refreshing the reddit API key.`, error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.redditApiGETHeaders = function() {
|
this.redditApiGETHeaders = function() {
|
||||||
let cookies = '_options=%7B%22pref_quarantine_optin%22%3A%20true%7D'
|
let cookies = `edgebucket=; _options={%22pref_gated_sr_optin%22:true,%22pref_quarantine_optin%22:true}`
|
||||||
|
|
||||||
if(!config.use_reddit_oauth)
|
if(!config.use_reddit_oauth)
|
||||||
return { headers: { cookie: cookies }, method: 'GET' }
|
return { headers: { cookie: cookies }, method: 'GET' }
|
||||||
|
|
|
@ -1,155 +1,59 @@
|
||||||
module.exports = function(fetch) {
|
const compilePostComments = require('./compilePostComments.js')();
|
||||||
var compilePostComments = require('./compilePostComments.js')();
|
const procPostMedia = require('./processPostMedia.js')();
|
||||||
var procPostMedia = require('./processPostMedia.js')();
|
const config = require('../config');
|
||||||
this.processJsonPost = (json, parsed, user_preferences) => {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
(async () => {
|
|
||||||
if(!parsed) {
|
|
||||||
json = JSON.parse(json)
|
|
||||||
}
|
|
||||||
|
|
||||||
let post = json[0].data.children[0].data
|
async function processReplies(data, post_id, depth, user_preferences) {
|
||||||
let post_id = post.name
|
let return_replies = [];
|
||||||
let comments = json[1].data.children
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
let kind = data[i].kind;
|
||||||
|
let reply = data[i].data;
|
||||||
|
let obj = {};
|
||||||
|
if (kind !== 'more') {
|
||||||
|
obj = {
|
||||||
|
author: reply.author,
|
||||||
|
body_html: reply.body_html,
|
||||||
|
parent_id: reply.parent_id,
|
||||||
|
created: reply.created_utc,
|
||||||
|
edited: reply.edited,
|
||||||
|
score: reply.score,
|
||||||
|
ups: reply.ups,
|
||||||
|
id: reply.id,
|
||||||
|
permalink: teddifyUrl(reply.permalink),
|
||||||
|
stickied: reply.stickied,
|
||||||
|
distinguished: reply.distinguished,
|
||||||
|
score_hidden: reply.score_hidden,
|
||||||
|
edited: reply.edited,
|
||||||
|
replies: [],
|
||||||
|
depth: depth,
|
||||||
|
user_flair:
|
||||||
|
user_preferences.flairs != 'false'
|
||||||
|
? await formatUserFlair(reply)
|
||||||
|
: '',
|
||||||
|
controversiality:
|
||||||
|
user_preferences.highlight_controversial != 'false'
|
||||||
|
? reply.controversiality
|
||||||
|
: '',
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
obj = {
|
||||||
|
type: 'load_more',
|
||||||
|
count: reply.count,
|
||||||
|
id: reply.id,
|
||||||
|
parent_id: reply.parent_id,
|
||||||
|
post_id: post_id,
|
||||||
|
children: [],
|
||||||
|
depth: depth,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let obj = {
|
if (reply.replies && kind !== 'more') {
|
||||||
author: post.author,
|
if (reply.replies.data.children.length) {
|
||||||
created: post.created_utc,
|
for (var j = 0; j < reply.replies.data.children.length; j++) {
|
||||||
edited: post.edited,
|
let comment = reply.replies.data.children[j].data;
|
||||||
is_video: post.is_video,
|
let objct = {};
|
||||||
locked: post.locked,
|
|
||||||
link_flair_text: post.link_flair_text,
|
|
||||||
name: post_id,
|
|
||||||
num_comments: post.num_comments,
|
|
||||||
over_18: post.over_18,
|
|
||||||
permalink: teddifyUrl(post.permalink),
|
|
||||||
title: post.title,
|
|
||||||
url: teddifyUrl(post.url, user_preferences),
|
|
||||||
ups: post.ups,
|
|
||||||
id: post.id,
|
|
||||||
domain: post.domain,
|
|
||||||
contest_mode: post.contest_mode,
|
|
||||||
upvote_ratio: post.upvote_ratio,
|
|
||||||
comments: null,
|
|
||||||
has_media: false,
|
|
||||||
media: null,
|
|
||||||
images: null,
|
|
||||||
crosspost: false,
|
|
||||||
selftext: unescape(post.selftext_html),
|
|
||||||
poll_data: post.poll_data,
|
|
||||||
link_flair: (user_preferences.flairs != 'false' ? await formatLinkFlair(post) : ''),
|
|
||||||
user_flair: (user_preferences.flairs != 'false' ? await formatUserFlair(post) : '')
|
|
||||||
}
|
|
||||||
|
|
||||||
let valid_embed_video_domains = ['gfycat.com']
|
if (comment.author && comment.body_html) {
|
||||||
let has_gif = false
|
objct = {
|
||||||
let gif_to_mp4 = null
|
|
||||||
let reddit_video = null
|
|
||||||
let embed_video = false
|
|
||||||
|
|
||||||
if(post.media)
|
|
||||||
if(valid_embed_video_domains.includes(post.media.type))
|
|
||||||
embed_video = true
|
|
||||||
|
|
||||||
if(post.preview && !embed_video) {
|
|
||||||
if(post.preview.reddit_video_preview) {
|
|
||||||
if(post.preview.reddit_video_preview.is_gif) {
|
|
||||||
has_gif = true
|
|
||||||
gif_url = post.preview.reddit_video_preview.fallback_url
|
|
||||||
} else {
|
|
||||||
let file_ext = getFileExtension(post.preview.reddit_video_preview.fallback_url)
|
|
||||||
if(file_ext === 'mp4') {
|
|
||||||
post.media = true
|
|
||||||
reddit_video = post.preview.reddit_video_preview
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(post.preview.images) {
|
|
||||||
if(post.preview.images[0].source) {
|
|
||||||
let file_ext = getFileExtension(post.preview.images[0].source.url)
|
|
||||||
if(file_ext === 'gif') {
|
|
||||||
has_gif = true
|
|
||||||
let resolutions = post.preview.images[0].variants.mp4.resolutions
|
|
||||||
gif_to_mp4 = resolutions[resolutions.length - 1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
obj = await processPostMedia(obj, post, post.media, has_gif, reddit_video, gif_to_mp4)
|
|
||||||
|
|
||||||
if(post.crosspost_parent_list) {
|
|
||||||
post.crosspost = post.crosspost_parent_list[0]
|
|
||||||
}
|
|
||||||
if(post.crosspost) {
|
|
||||||
obj = await processPostMedia(obj, post.crosspost, post.crosspost.media, has_gif, reddit_video, gif_to_mp4)
|
|
||||||
obj.crosspost = {
|
|
||||||
author: post.crosspost.author,
|
|
||||||
created: post.crosspost.created_utc,
|
|
||||||
subreddit: post.crosspost.subreddit,
|
|
||||||
title: post.crosspost.title,
|
|
||||||
name: post.crosspost.name,
|
|
||||||
num_comments: post.crosspost.num_comments,
|
|
||||||
over_18: post.crosspost.over_18,
|
|
||||||
id: post.crosspost.id,
|
|
||||||
permalink: teddifyUrl(post.crosspost.permalink),
|
|
||||||
ups: post.crosspost.ups,
|
|
||||||
selftext: unescape(post.selftext_html),
|
|
||||||
selftext_crosspost: unescape(post.crosspost.selftext_html),
|
|
||||||
poll_data: post.poll_data,
|
|
||||||
is_crosspost: true,
|
|
||||||
user_flair: (user_preferences.flairs != 'false' ? await formatUserFlair(post) : '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(post.preview && !obj.has_media) {
|
|
||||||
obj.images = {
|
|
||||||
source: await downloadAndSave(post.preview.images[0].source.url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(obj.media) {
|
|
||||||
if(obj.media.source === 'external') {
|
|
||||||
if(post.preview) {
|
|
||||||
obj.images = {
|
|
||||||
source: await downloadAndSave(post.preview.images[0].source.url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(post.gallery_data) {
|
|
||||||
obj.gallery = true
|
|
||||||
obj.gallery_items = []
|
|
||||||
for(var i = 0; i < post.gallery_data.items.length; i++) {
|
|
||||||
let id = post.gallery_data.items[i].media_id
|
|
||||||
if(post.media_metadata[id]) {
|
|
||||||
if(post.media_metadata[id].p) {
|
|
||||||
if(post.media_metadata[id].p[0]) {
|
|
||||||
let item = { source: null, thumbnail: null, large: null }
|
|
||||||
if(post.media_metadata[id].s && post.media_metadata[id].p[0].u) {
|
|
||||||
item = {
|
|
||||||
type: post.media_metadata[id].e,
|
|
||||||
source: await downloadAndSave(post.media_metadata[id].s.u),
|
|
||||||
thumbnail: await downloadAndSave(post.media_metadata[id].p[0].u),
|
|
||||||
large: await downloadAndSave(post.media_metadata[id].p[post.media_metadata[id].p.length - 1].u),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
obj.gallery_items.push(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let comms = []
|
|
||||||
for(var i = 0; i < comments.length; i++) {
|
|
||||||
let comment = comments[i].data
|
|
||||||
let kind = comments[i].kind
|
|
||||||
let obj = {}
|
|
||||||
|
|
||||||
if(kind !== 'more') {
|
|
||||||
obj = {
|
|
||||||
author: comment.author,
|
author: comment.author,
|
||||||
body_html: comment.body_html,
|
body_html: comment.body_html,
|
||||||
parent_id: comment.parent_id,
|
parent_id: comment.parent_id,
|
||||||
|
@ -159,174 +63,478 @@ module.exports = function(fetch) {
|
||||||
ups: comment.ups,
|
ups: comment.ups,
|
||||||
id: comment.id,
|
id: comment.id,
|
||||||
permalink: teddifyUrl(comment.permalink),
|
permalink: teddifyUrl(comment.permalink),
|
||||||
stickied: comment.stickied,
|
|
||||||
distinguished: comment.distinguished,
|
|
||||||
score_hidden: comment.score_hidden,
|
score_hidden: comment.score_hidden,
|
||||||
edited: comment.edited,
|
distinguished: comment.distinguished,
|
||||||
|
distinguished: comment.edited,
|
||||||
replies: [],
|
replies: [],
|
||||||
depth: comment.depth,
|
depth: depth + 1,
|
||||||
user_flair: (user_preferences.flairs != 'false' ? await formatUserFlair(comment) : ''),
|
user_flair:
|
||||||
controversiality: (user_preferences.highlight_controversial != 'false' ? comment.controversiality : '')
|
user_preferences.flairs != 'false'
|
||||||
}
|
? await formatUserFlair(comment)
|
||||||
|
: '',
|
||||||
|
controversiality:
|
||||||
|
user_preferences.highlight_controversial != 'false'
|
||||||
|
? comment.controversiality
|
||||||
|
: '',
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
obj = {
|
objct = {
|
||||||
type: 'load_more',
|
type: 'load_more',
|
||||||
count: comment.count,
|
count: comment.count,
|
||||||
id: comment.id,
|
id: comment.id,
|
||||||
parent_id: comment.parent_id,
|
parent_id: comment.parent_id,
|
||||||
post_id: post.name,
|
post_id: post_id,
|
||||||
children: []
|
children: [],
|
||||||
}
|
depth: depth + 1,
|
||||||
}
|
};
|
||||||
|
if (comment.children) {
|
||||||
if(comment.replies && kind !== 'more') {
|
for (var k = 0; k < comment.children.length; k++) {
|
||||||
if(comment.replies.data) {
|
objct.children.push(comment.children[k]);
|
||||||
if(comment.replies.data.children.length > 0) {
|
|
||||||
obj.replies = await processReplies(comment.replies.data.children, post_id, 1, user_preferences)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(comment.children) {
|
if (comment.replies) {
|
||||||
for(var j = 0; j < comment.children.length; j++) {
|
if (comment.replies.data) {
|
||||||
obj.children.push(comment.children[j])
|
if (comment.replies.data.children.length > 0) {
|
||||||
|
objct.replies = await processReplies(
|
||||||
|
comment.replies.data.children,
|
||||||
|
post_id,
|
||||||
|
depth,
|
||||||
|
user_preferences
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
comms.push(obj)
|
obj.replies.push(objct);
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.comments = comms
|
|
||||||
|
|
||||||
resolve(obj)
|
|
||||||
})()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
this.finalizeJsonPost = async (processed_json, post_id, post_url, morechildren_ids, viewing_comment, user_preferences) => {
|
|
||||||
let comments_html = `<div class="comments">`
|
|
||||||
let comments = processed_json.comments
|
|
||||||
let last_known_depth = undefined
|
|
||||||
for(var i = 0; i < comments.length; i++) {
|
|
||||||
let next_comment = false
|
|
||||||
if(comments[i+1]) {
|
|
||||||
next_comment = comments[i+1]
|
|
||||||
}
|
}
|
||||||
if(comments[i].depth != undefined) {
|
|
||||||
last_known_depth = comments[i].depth
|
|
||||||
}
|
|
||||||
|
|
||||||
comments_html += await compilePostCommentsHtml(comments[i], next_comment, post_id, post_url, morechildren_ids, processed_json.author, viewing_comment, user_preferences, last_known_depth)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
comments_html += `</div>`
|
if (reply.children) {
|
||||||
|
for (var j = 0; j < reply.children.length; j++) {
|
||||||
delete processed_json['comments']
|
obj.children.push(reply.children[j]);
|
||||||
let post_data = processed_json
|
|
||||||
return { post_data: post_data, comments: comments_html }
|
|
||||||
}
|
|
||||||
|
|
||||||
this.processReplies = async (data, post_id, depth, user_preferences) => {
|
|
||||||
let return_replies = []
|
|
||||||
for(var i = 0; i < data.length; i++) {
|
|
||||||
let kind = data[i].kind
|
|
||||||
let reply = data[i].data
|
|
||||||
let obj = {}
|
|
||||||
if(kind !== 'more') {
|
|
||||||
obj = {
|
|
||||||
author: reply.author,
|
|
||||||
body_html: reply.body_html,
|
|
||||||
parent_id: reply.parent_id,
|
|
||||||
created: reply.created_utc,
|
|
||||||
edited: reply.edited,
|
|
||||||
score: reply.score,
|
|
||||||
ups: reply.ups,
|
|
||||||
id: reply.id,
|
|
||||||
permalink: teddifyUrl(reply.permalink),
|
|
||||||
stickied: reply.stickied,
|
|
||||||
distinguished: reply.distinguished,
|
|
||||||
score_hidden: reply.score_hidden,
|
|
||||||
edited: reply.edited,
|
|
||||||
replies: [],
|
|
||||||
depth: depth,
|
|
||||||
user_flair: (user_preferences.flairs != 'false' ? await formatUserFlair(reply) : ''),
|
|
||||||
controversiality: (user_preferences.highlight_controversial != 'false' ? reply.controversiality : '')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
obj = {
|
|
||||||
type: 'load_more',
|
|
||||||
count: reply.count,
|
|
||||||
id: reply.id,
|
|
||||||
parent_id: reply.parent_id,
|
|
||||||
post_id: post_id,
|
|
||||||
children: [],
|
|
||||||
depth: depth
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(reply.replies && kind !== 'more') {
|
|
||||||
if(reply.replies.data.children.length) {
|
|
||||||
for(var j = 0; j < reply.replies.data.children.length; j++) {
|
|
||||||
let comment = reply.replies.data.children[j].data
|
|
||||||
let objct = {}
|
|
||||||
|
|
||||||
if(comment.author && comment.body_html) {
|
|
||||||
objct = {
|
|
||||||
author: comment.author,
|
|
||||||
body_html: comment.body_html,
|
|
||||||
parent_id: comment.parent_id,
|
|
||||||
created: comment.created_utc,
|
|
||||||
edited: comment.edited,
|
|
||||||
score: comment.score,
|
|
||||||
ups: comment.ups,
|
|
||||||
id: comment.id,
|
|
||||||
permalink: teddifyUrl(comment.permalink),
|
|
||||||
score_hidden: comment.score_hidden,
|
|
||||||
distinguished: comment.distinguished,
|
|
||||||
distinguished: comment.edited,
|
|
||||||
replies: [],
|
|
||||||
depth: depth + 1,
|
|
||||||
user_flair: (user_preferences.flairs != 'false' ? await formatUserFlair(comment) : ''),
|
|
||||||
controversiality: (user_preferences.highlight_controversial != 'false' ? comment.controversiality : '')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
objct = {
|
|
||||||
type: 'load_more',
|
|
||||||
count: comment.count,
|
|
||||||
id: comment.id,
|
|
||||||
parent_id: comment.parent_id,
|
|
||||||
post_id: post_id,
|
|
||||||
children: [],
|
|
||||||
depth: depth + 1
|
|
||||||
}
|
|
||||||
if(comment.children) {
|
|
||||||
for(var k = 0; k < comment.children.length; k++) {
|
|
||||||
objct.children.push(comment.children[k])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(comment.replies) {
|
|
||||||
if(comment.replies.data) {
|
|
||||||
if(comment.replies.data.children.length > 0) {
|
|
||||||
objct.replies = await processReplies(comment.replies.data.children, post_id, depth, user_preferences)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
obj.replies.push(objct)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(reply.children) {
|
|
||||||
for(var j = 0; j < reply.children.length; j++) {
|
|
||||||
obj.children.push(reply.children[j])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return_replies.push(obj)
|
|
||||||
}
|
}
|
||||||
return return_replies
|
|
||||||
|
return_replies.push(obj);
|
||||||
}
|
}
|
||||||
|
return return_replies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function processJsonPost(json, parsed, user_preferences) {
|
||||||
|
if (!parsed) {
|
||||||
|
json = JSON.parse(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
let post = json[0].data.children[0].data;
|
||||||
|
let post_id = post.name;
|
||||||
|
let comments = json[1].data.children;
|
||||||
|
|
||||||
|
let obj = {
|
||||||
|
author: post.author,
|
||||||
|
created: post.created_utc,
|
||||||
|
edited: post.edited,
|
||||||
|
is_video: post.is_video,
|
||||||
|
locked: post.locked,
|
||||||
|
link_flair_text: post.link_flair_text,
|
||||||
|
name: post_id,
|
||||||
|
num_comments: post.num_comments,
|
||||||
|
over_18: post.over_18,
|
||||||
|
permalink: teddifyUrl(post.permalink),
|
||||||
|
title: post.title,
|
||||||
|
url: teddifyUrl(post.url, user_preferences),
|
||||||
|
ups: post.ups,
|
||||||
|
id: post.id,
|
||||||
|
domain: post.domain,
|
||||||
|
contest_mode: post.contest_mode,
|
||||||
|
upvote_ratio: post.upvote_ratio,
|
||||||
|
comments: null,
|
||||||
|
has_media: false,
|
||||||
|
media: null,
|
||||||
|
images: null,
|
||||||
|
crosspost: false,
|
||||||
|
selftext: unescape(post.selftext_html),
|
||||||
|
selftext_preview: post.selftext.substr(0, 120).replace(/\n/g, ' '),
|
||||||
|
poll_data: post.poll_data,
|
||||||
|
link_flair:
|
||||||
|
user_preferences.flairs != 'false' ? await formatLinkFlair(post) : '',
|
||||||
|
user_flair:
|
||||||
|
user_preferences.flairs != 'false' ? await formatUserFlair(post) : '',
|
||||||
|
};
|
||||||
|
|
||||||
|
let valid_embed_video_domains = ['gfycat.com'];
|
||||||
|
let has_gif = false;
|
||||||
|
let gif_to_mp4 = null;
|
||||||
|
let reddit_video = null;
|
||||||
|
let embed_video = false;
|
||||||
|
|
||||||
|
if (post.media)
|
||||||
|
if (valid_embed_video_domains.includes(post.media.type)) embed_video = true;
|
||||||
|
|
||||||
|
if (post.preview && !embed_video) {
|
||||||
|
if (post.preview.reddit_video_preview) {
|
||||||
|
if (post.preview.reddit_video_preview.is_gif) {
|
||||||
|
has_gif = true;
|
||||||
|
gif_url = post.preview.reddit_video_preview.fallback_url;
|
||||||
|
} else {
|
||||||
|
let file_ext = getFileExtension(
|
||||||
|
post.preview.reddit_video_preview.fallback_url
|
||||||
|
);
|
||||||
|
if (file_ext === 'mp4') {
|
||||||
|
post.media = true;
|
||||||
|
reddit_video = post.preview.reddit_video_preview;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (post.preview.images) {
|
||||||
|
if (post.preview.images[0].source) {
|
||||||
|
let file_ext = getFileExtension(post.preview.images[0].source.url);
|
||||||
|
if (file_ext === 'gif') {
|
||||||
|
has_gif = true;
|
||||||
|
let resolutions = post.preview.images[0].variants.mp4.resolutions;
|
||||||
|
gif_to_mp4 = resolutions[resolutions.length - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = await processPostMedia(
|
||||||
|
obj,
|
||||||
|
post,
|
||||||
|
post.media,
|
||||||
|
has_gif,
|
||||||
|
reddit_video,
|
||||||
|
gif_to_mp4
|
||||||
|
);
|
||||||
|
|
||||||
|
if (post.crosspost_parent_list) {
|
||||||
|
post.crosspost = post.crosspost_parent_list[0];
|
||||||
|
}
|
||||||
|
if (post.crosspost) {
|
||||||
|
obj = await processPostMedia(
|
||||||
|
obj,
|
||||||
|
post.crosspost,
|
||||||
|
post.crosspost.media,
|
||||||
|
has_gif,
|
||||||
|
reddit_video,
|
||||||
|
gif_to_mp4
|
||||||
|
);
|
||||||
|
obj.crosspost = {
|
||||||
|
author: post.crosspost.author,
|
||||||
|
created: post.crosspost.created_utc,
|
||||||
|
subreddit: post.crosspost.subreddit,
|
||||||
|
title: post.crosspost.title,
|
||||||
|
name: post.crosspost.name,
|
||||||
|
num_comments: post.crosspost.num_comments,
|
||||||
|
over_18: post.crosspost.over_18,
|
||||||
|
id: post.crosspost.id,
|
||||||
|
permalink: teddifyUrl(post.crosspost.permalink),
|
||||||
|
ups: post.crosspost.ups,
|
||||||
|
selftext: unescape(post.selftext_html),
|
||||||
|
selftext_crosspost: unescape(post.crosspost.selftext_html),
|
||||||
|
poll_data: post.poll_data,
|
||||||
|
is_crosspost: true,
|
||||||
|
user_flair:
|
||||||
|
user_preferences.flairs != 'false' ? await formatUserFlair(post) : '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (post.preview && !obj.has_media) {
|
||||||
|
obj.images = {
|
||||||
|
source: await downloadAndSave(post.preview.images[0].source.url),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.media) {
|
||||||
|
if (obj.media.source === 'external') {
|
||||||
|
if (post.preview) {
|
||||||
|
obj.images = {
|
||||||
|
source: await downloadAndSave(post.preview.images[0].source.url),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (post.gallery_data) {
|
||||||
|
obj.gallery = true;
|
||||||
|
obj.gallery_items = [];
|
||||||
|
for (var i = 0; i < post.gallery_data.items.length; i++) {
|
||||||
|
let id = post.gallery_data.items[i].media_id;
|
||||||
|
if (post.media_metadata) {
|
||||||
|
if (post.media_metadata[id]) {
|
||||||
|
if (post.media_metadata[id].p) {
|
||||||
|
if (post.media_metadata[id].p[0]) {
|
||||||
|
let item = { source: null, thumbnail: null, large: null };
|
||||||
|
if (post.media_metadata[id].s && post.media_metadata[id].p[0].u) {
|
||||||
|
item = {
|
||||||
|
type: post.media_metadata[id].e,
|
||||||
|
source: await downloadAndSave(post.media_metadata[id].s.u),
|
||||||
|
thumbnail: await downloadAndSave(
|
||||||
|
post.media_metadata[id].p[0].u
|
||||||
|
),
|
||||||
|
large: await downloadAndSave(
|
||||||
|
post.media_metadata[id].p[
|
||||||
|
post.media_metadata[id].p.length - 1
|
||||||
|
].u
|
||||||
|
),
|
||||||
|
caption: post.gallery_data.items[i].caption || false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
obj.gallery_items.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let comms = [];
|
||||||
|
for (var i = 0; i < comments.length; i++) {
|
||||||
|
let comment = comments[i].data;
|
||||||
|
let kind = comments[i].kind;
|
||||||
|
let obj = {};
|
||||||
|
|
||||||
|
if (kind !== 'more') {
|
||||||
|
obj = {
|
||||||
|
author: comment.author,
|
||||||
|
body_html: comment.body_html,
|
||||||
|
parent_id: comment.parent_id,
|
||||||
|
created: comment.created_utc,
|
||||||
|
edited: comment.edited,
|
||||||
|
score: comment.score,
|
||||||
|
ups: comment.ups,
|
||||||
|
id: comment.id,
|
||||||
|
permalink: teddifyUrl(comment.permalink),
|
||||||
|
stickied: comment.stickied,
|
||||||
|
distinguished: comment.distinguished,
|
||||||
|
score_hidden: comment.score_hidden,
|
||||||
|
edited: comment.edited,
|
||||||
|
replies: [],
|
||||||
|
depth: comment.depth,
|
||||||
|
user_flair:
|
||||||
|
user_preferences.flairs != 'false'
|
||||||
|
? await formatUserFlair(comment)
|
||||||
|
: '',
|
||||||
|
controversiality:
|
||||||
|
user_preferences.highlight_controversial != 'false'
|
||||||
|
? comment.controversiality
|
||||||
|
: '',
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
obj = {
|
||||||
|
type: 'load_more',
|
||||||
|
count: comment.count,
|
||||||
|
id: comment.id,
|
||||||
|
parent_id: comment.parent_id,
|
||||||
|
post_id: post.name,
|
||||||
|
children: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comment.replies && kind !== 'more') {
|
||||||
|
if (comment.replies.data) {
|
||||||
|
if (comment.replies.data.children.length > 0) {
|
||||||
|
obj.replies = await processReplies(
|
||||||
|
comment.replies.data.children,
|
||||||
|
post_id,
|
||||||
|
1,
|
||||||
|
user_preferences
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comment.children) {
|
||||||
|
for (var j = 0; j < comment.children.length; j++) {
|
||||||
|
obj.children.push(comment.children[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
comms.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.comments = comms;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function finalizeJsonPost(
|
||||||
|
processed_json,
|
||||||
|
post_id,
|
||||||
|
post_url,
|
||||||
|
morechildren_ids,
|
||||||
|
viewing_comment,
|
||||||
|
user_preferences
|
||||||
|
) {
|
||||||
|
let comments_html = `<div class="comments">`;
|
||||||
|
let comments = processed_json.comments;
|
||||||
|
let last_known_depth = undefined;
|
||||||
|
for (var i = 0; i < comments.length; i++) {
|
||||||
|
let next_comment = false;
|
||||||
|
if (comments[i + 1]) {
|
||||||
|
next_comment = comments[i + 1];
|
||||||
|
}
|
||||||
|
if (comments[i].depth != undefined) {
|
||||||
|
last_known_depth = comments[i].depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
comments_html += await compilePostCommentsHtml(
|
||||||
|
comments[i],
|
||||||
|
next_comment,
|
||||||
|
post_id,
|
||||||
|
post_url,
|
||||||
|
morechildren_ids,
|
||||||
|
processed_json.author,
|
||||||
|
viewing_comment,
|
||||||
|
user_preferences,
|
||||||
|
last_known_depth
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
comments_html += `</div>`;
|
||||||
|
|
||||||
|
delete processed_json['comments'];
|
||||||
|
let post_data = processed_json;
|
||||||
|
return { post_data: post_data, comments: comments_html };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processJsonPostList(posts, mode) {
|
||||||
|
let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http';
|
||||||
|
|
||||||
|
for (var i = 0; i < posts.length; i++) {
|
||||||
|
let link = posts[i];
|
||||||
|
let valid_reddit_self_domains = ['reddit.com'];
|
||||||
|
let is_self_link = false;
|
||||||
|
|
||||||
|
if (link.domain) {
|
||||||
|
let tld = link.domain.split('self.');
|
||||||
|
if (tld.length > 1) {
|
||||||
|
if (!tld[1].includes('.')) {
|
||||||
|
is_self_link = true;
|
||||||
|
link.url = teddifyUrl(link.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
config.valid_media_domains.includes(link.domain) ||
|
||||||
|
valid_reddit_self_domains.includes(link.domain)
|
||||||
|
) {
|
||||||
|
is_self_link = true;
|
||||||
|
link.url = teddifyUrl(link.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
link.permalink = `${protocol}://${config.domain}${link.permalink}`;
|
||||||
|
|
||||||
|
if (is_self_link) link.url = link.permalink;
|
||||||
|
|
||||||
|
if (link.images) {
|
||||||
|
if (link.images.thumb !== 'self') {
|
||||||
|
link.images.thumb = `${protocol}://${config.domain}${link.images.thumb}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === 'light') {
|
||||||
|
link.selftext_html = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return posts;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getPostItem(post_json, req, protocol) {
|
||||||
|
let thumbnail = '';
|
||||||
|
let post_image = '';
|
||||||
|
let is_self_link = false;
|
||||||
|
let valid_reddit_self_domains = ['reddit.com'];
|
||||||
|
|
||||||
|
if (post_json.domain) {
|
||||||
|
let tld = post_json.domain.split('self.');
|
||||||
|
if (tld.length > 1) {
|
||||||
|
if (!tld[1].includes('.')) {
|
||||||
|
is_self_link = true;
|
||||||
|
post_json.url = teddifyUrl(post_json.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
config.valid_media_domains.includes(post_json.domain) ||
|
||||||
|
valid_reddit_self_domains.includes(post_json.domain)
|
||||||
|
) {
|
||||||
|
is_self_link = true;
|
||||||
|
post_json.url = teddifyUrl(post_json.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (post_json.preview && post_json.thumbnail !== 'self') {
|
||||||
|
if (!post_json.url.startsWith('/r/') && isGif(post_json.url)) {
|
||||||
|
let s = await downloadAndSave(post_json.thumbnail, 'thumb_');
|
||||||
|
thumbnail = `${protocol}://${config.domain}${s}`;
|
||||||
|
} else {
|
||||||
|
if (post_json.preview.images[0].resolutions[0]) {
|
||||||
|
let s = await downloadAndSave(
|
||||||
|
post_json.preview.images[0].resolutions[0].url,
|
||||||
|
'thumb_'
|
||||||
|
);
|
||||||
|
thumbnail = `${protocol}://${config.domain}${s}`;
|
||||||
|
if (!isGif(post_json.url) && !post_json.post_hint.includes(':video')) {
|
||||||
|
s = await downloadAndSave(post_json.preview.images[0].source.url);
|
||||||
|
post_image = `${protocol}://${config.domain}${s}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
post_json.permalink = `${protocol}://${config.domain}${post_json.permalink}`;
|
||||||
|
|
||||||
|
if (is_self_link) post_json.url = post_json.permalink;
|
||||||
|
|
||||||
|
if (req.query.hasOwnProperty('full_thumbs')) {
|
||||||
|
if (!post_image) post_image = thumbnail;
|
||||||
|
|
||||||
|
thumbnail = post_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
let enclosure = '';
|
||||||
|
if (thumbnail != '') {
|
||||||
|
let mime = '';
|
||||||
|
let ext = thumbnail.split('.').pop();
|
||||||
|
if (ext === 'png') mime = 'image/png';
|
||||||
|
else mime = 'image/jpeg';
|
||||||
|
enclosure = `<enclosure length="0" type="${mime}" url="${thumbnail}" />`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let append_desc_html = `<br/><a href="${post_json.url}">[link]</a> <a href="${post_json.permalink}">[comments]</a>`;
|
||||||
|
|
||||||
|
return `
|
||||||
|
<item>
|
||||||
|
<title>${post_json.title}</title>
|
||||||
|
<author>${post_json.author}</author>
|
||||||
|
<created>${post_json.created}</created>
|
||||||
|
<pubDate>${new Date(
|
||||||
|
post_json.created_utc * 1000
|
||||||
|
).toGMTString()}</pubDate>
|
||||||
|
<domain>${post_json.domain}</domain>
|
||||||
|
<id>${post_json.id}</id>
|
||||||
|
<thumbnail>${thumbnail}</thumbnail>
|
||||||
|
${enclosure}
|
||||||
|
<link>${post_json.permalink}</link>
|
||||||
|
<url>${post_json.url}</url>
|
||||||
|
<description><![CDATA[${unescape(
|
||||||
|
post_json.selftext_html
|
||||||
|
)}${append_desc_html}]]></description>
|
||||||
|
<num_comments>${post_json.num_comments}</num_comments>
|
||||||
|
<ups>${post_json.ups}</ups>
|
||||||
|
<stickied>${post_json.stickied}</stickied>
|
||||||
|
<is_self_link>${is_self_link}</is_self_link>
|
||||||
|
</item>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
processReplies,
|
||||||
|
processJsonPost,
|
||||||
|
finalizeJsonPost,
|
||||||
|
processJsonPostList,
|
||||||
|
getPostItem
|
||||||
|
};
|
||||||
|
|
|
@ -1,83 +1,90 @@
|
||||||
module.exports = function() {
|
const config = require('../config');
|
||||||
const config = require('../config');
|
const link = require('./components/link');
|
||||||
const link = require('./components/link')
|
|
||||||
this.processJsonSubreddit = (json, from, subreddit_front, user_preferences, saved) => {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
(async () => {
|
|
||||||
if(from === 'redis') {
|
|
||||||
json = JSON.parse(json)
|
|
||||||
}
|
|
||||||
if(json.error) {
|
|
||||||
resolve({ error: true, error_data: json })
|
|
||||||
} else {
|
|
||||||
if(saved) {
|
|
||||||
let t = {
|
|
||||||
data: {
|
|
||||||
before: null,
|
|
||||||
after: null,
|
|
||||||
children: json
|
|
||||||
}
|
|
||||||
}
|
|
||||||
json = t
|
|
||||||
}
|
|
||||||
|
|
||||||
let before = json.data.before
|
|
||||||
let after = json.data.after
|
|
||||||
|
|
||||||
let ret = {
|
async function processJsonSubreddit(
|
||||||
info: {
|
json,
|
||||||
before: before,
|
from,
|
||||||
after: after
|
subreddit_front,
|
||||||
},
|
user_preferences,
|
||||||
links: []
|
saved
|
||||||
}
|
) {
|
||||||
|
if (from === 'redis') {
|
||||||
|
json = JSON.parse(json);
|
||||||
|
}
|
||||||
|
if (json.error) {
|
||||||
|
return { error: true, error_data: json };
|
||||||
|
} else {
|
||||||
|
if (saved) {
|
||||||
|
let t = {
|
||||||
|
data: {
|
||||||
|
before: null,
|
||||||
|
after: null,
|
||||||
|
children: json,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
json = t;
|
||||||
|
}
|
||||||
|
|
||||||
let children_len = json.data.children.length
|
let before = json.data.before;
|
||||||
|
let after = json.data.after;
|
||||||
|
|
||||||
for(var i = 0; i < children_len; i++) {
|
let ret = {
|
||||||
let data = json.data.children[i].data
|
info: {
|
||||||
|
before: before,
|
||||||
|
after: after,
|
||||||
|
},
|
||||||
|
links: [],
|
||||||
|
};
|
||||||
|
|
||||||
if(data.over_18)
|
let children_len = json.data.children.length;
|
||||||
if((config.nsfw_enabled === false && user_preferences.nsfw_enabled != 'true') || user_preferences.nsfw_enabled === 'false')
|
|
||||||
continue
|
|
||||||
|
|
||||||
/*
|
for (var i = 0; i < children_len; i++) {
|
||||||
// Todo: Remove this once the link component is done
|
let data = json.data.children[i].data;
|
||||||
// but keep it for now in case we need it later
|
|
||||||
let obj = {
|
|
||||||
author: data.author,
|
|
||||||
created: data.created_utc,
|
|
||||||
domain: data.domain,
|
|
||||||
id: data.id,
|
|
||||||
images: images,
|
|
||||||
is_video: data.is_video,
|
|
||||||
link_flair_text: data.link_flair_text,
|
|
||||||
locked: data.locked,
|
|
||||||
media: data.media,
|
|
||||||
selftext_html: data.selftext_html,
|
|
||||||
num_comments: data.num_comments,
|
|
||||||
over_18: data.over_18,
|
|
||||||
permalink: data.permalink,
|
|
||||||
score: data.score,
|
|
||||||
subreddit: data.subreddit,
|
|
||||||
title: data.title,
|
|
||||||
ups: data.ups,
|
|
||||||
upvote_ratio: data.upvote_ratio,
|
|
||||||
url: replaceDomains(data.url, user_preferences),
|
|
||||||
stickied: data.stickied,
|
|
||||||
is_self_link: is_self_link,
|
|
||||||
subreddit_front: subreddit_front,
|
|
||||||
link_flair: (user_preferences.flairs != 'false' ? await formatLinkFlair(data) : ''),
|
|
||||||
user_flair: (user_preferences.flairs != 'false' ? await formatUserFlair(data) : '')
|
|
||||||
} */
|
|
||||||
|
|
||||||
let obj = await link.fromJson(data, user_preferences, subreddit_front)
|
if (data.over_18)
|
||||||
|
if (
|
||||||
|
(config.nsfw_enabled === false &&
|
||||||
|
user_preferences.nsfw_enabled != 'true') ||
|
||||||
|
user_preferences.nsfw_enabled === 'false'
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
|
||||||
ret.links.push(obj)
|
/*
|
||||||
}
|
// Todo: Remove this once the link component is done
|
||||||
resolve(ret)
|
// but keep it for now in case we need it later
|
||||||
}
|
let obj = {
|
||||||
})()
|
author: data.author,
|
||||||
})
|
created: data.created_utc,
|
||||||
|
domain: data.domain,
|
||||||
|
id: data.id,
|
||||||
|
images: images,
|
||||||
|
is_video: data.is_video,
|
||||||
|
link_flair_text: data.link_flair_text,
|
||||||
|
locked: data.locked,
|
||||||
|
media: data.media,
|
||||||
|
selftext_html: data.selftext_html,
|
||||||
|
num_comments: data.num_comments,
|
||||||
|
over_18: data.over_18,
|
||||||
|
permalink: data.permalink,
|
||||||
|
score: data.score,
|
||||||
|
subreddit: data.subreddit,
|
||||||
|
title: data.title,
|
||||||
|
ups: data.ups,
|
||||||
|
upvote_ratio: data.upvote_ratio,
|
||||||
|
url: replaceDomains(data.url, user_preferences),
|
||||||
|
stickied: data.stickied,
|
||||||
|
is_self_link: is_self_link,
|
||||||
|
subreddit_front: subreddit_front,
|
||||||
|
link_flair: (user_preferences.flairs != 'false' ? await formatLinkFlair(data) : ''),
|
||||||
|
user_flair: (user_preferences.flairs != 'false' ? await formatUserFlair(data) : '')
|
||||||
|
} */
|
||||||
|
|
||||||
|
let obj = await link.fromJson(data, user_preferences, subreddit_front);
|
||||||
|
|
||||||
|
ret.links.push(obj);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = processJsonSubreddit;
|
||||||
|
|
|
@ -1,97 +1,138 @@
|
||||||
module.exports = function() {
|
const config = require('../config');
|
||||||
const config = require('../config');
|
const link = require('./components/link');
|
||||||
const link = require('./components/link')
|
|
||||||
this.processJsonUser = function(json, parsed, after, before, user_preferences, kind, post_type) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
(async () => {
|
|
||||||
if(!parsed) {
|
|
||||||
json = JSON.parse(json)
|
|
||||||
}
|
|
||||||
|
|
||||||
let about = json.about.data
|
async function processJsonUser(
|
||||||
let posts = []
|
json,
|
||||||
let view_more_posts = false
|
parsed,
|
||||||
let posts_limit = 25
|
after,
|
||||||
let user_front = false
|
before,
|
||||||
|
user_preferences,
|
||||||
if(json.overview.data.children.length > posts_limit) {
|
kind,
|
||||||
view_more_posts = true
|
post_type
|
||||||
} else {
|
) {
|
||||||
posts_limit = json.overview.data.children.length
|
if (!parsed) {
|
||||||
}
|
json = JSON.parse(json);
|
||||||
|
|
||||||
if(!after && !before) {
|
|
||||||
user_front = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if(json.overview.data.children) {
|
|
||||||
if(json.overview.data.children[posts_limit - 1]) {
|
|
||||||
after = json.overview.data.children[posts_limit - 1].data.name
|
|
||||||
}
|
|
||||||
if(json.overview.data.children[0]) {
|
|
||||||
before = json.overview.data.children[0].data.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(var i = 0; i < posts_limit; i++) {
|
|
||||||
let post = json.overview.data.children[i].data
|
|
||||||
let thumbnail = 'self'
|
|
||||||
let type = json.overview.data.children[i].kind
|
|
||||||
let obj
|
|
||||||
|
|
||||||
let post_id = post.permalink.split('/').slice(-2)[0] + '/'
|
|
||||||
let url = post.permalink.replace(post_id, '')
|
|
||||||
|
|
||||||
if(type !== kind && kind)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if(post.over_18)
|
|
||||||
if((config.nsfw_enabled === false && user_preferences.nsfw_enabled != 'true') || user_preferences.nsfw_enabled === 'false')
|
|
||||||
continue
|
|
||||||
|
|
||||||
if(type === 't3') {
|
|
||||||
obj = await link.fromJson(post, user_preferences)
|
|
||||||
obj.type = 't3'
|
|
||||||
}
|
|
||||||
if(type === 't1') {
|
|
||||||
obj = {
|
|
||||||
type: type,
|
|
||||||
subreddit: post.subreddit,
|
|
||||||
title: post.title,
|
|
||||||
created: post.created_utc,
|
|
||||||
subreddit_name_prefixed: post.subreddit_name_prefixed,
|
|
||||||
ups: post.ups,
|
|
||||||
url: replaceDomains(url, user_preferences),
|
|
||||||
edited: post.edited,
|
|
||||||
body_html: unescape(post.body_html),
|
|
||||||
num_comments: post.num_comments,
|
|
||||||
over_18: post.over_18,
|
|
||||||
permalink: post.permalink,
|
|
||||||
link_author: post.link_author,
|
|
||||||
link_title: post.link_title,
|
|
||||||
user_flair: (user_preferences.flairs != 'false' ? await formatUserFlair(post) : '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
posts.push(obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
let obj = {
|
|
||||||
username: about.name,
|
|
||||||
icon_img: await downloadAndSave(about.icon_img, "icon_"),
|
|
||||||
created: about.created_utc,
|
|
||||||
verified: about.verified,
|
|
||||||
link_karma: about.link_karma,
|
|
||||||
comment_karma: about.comment_karma,
|
|
||||||
view_more_posts: view_more_posts,
|
|
||||||
user_front: user_front,
|
|
||||||
post_type: post_type,
|
|
||||||
before: before,
|
|
||||||
after: after,
|
|
||||||
posts: posts
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(obj)
|
|
||||||
})()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateJson(json) {
|
||||||
|
const empty = {
|
||||||
|
username: '',
|
||||||
|
icon_img: '',
|
||||||
|
created: '',
|
||||||
|
verified: '',
|
||||||
|
link_karma: '',
|
||||||
|
comment_karma: '',
|
||||||
|
view_more_posts: '',
|
||||||
|
user_front: '',
|
||||||
|
post_type:'',
|
||||||
|
before: '',
|
||||||
|
after: '',
|
||||||
|
posts: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!json.overview) {
|
||||||
|
return { error: true, data: empty };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json.overview.data) {
|
||||||
|
return { error: true, data: empty };
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const validJson = validateJson(json);
|
||||||
|
if (validJson.error) {
|
||||||
|
return validJson.data
|
||||||
|
}
|
||||||
|
|
||||||
|
let about = json.about.data;
|
||||||
|
let posts = [];
|
||||||
|
let view_more_posts = false;
|
||||||
|
let posts_limit = 25;
|
||||||
|
let user_front = false;
|
||||||
|
|
||||||
|
if (json.overview.data.children.length > posts_limit) {
|
||||||
|
view_more_posts = true;
|
||||||
|
} else {
|
||||||
|
posts_limit = json.overview.data.children.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!after && !before) {
|
||||||
|
user_front = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.overview.data.children) {
|
||||||
|
if (json.overview.data.children[posts_limit - 1]) {
|
||||||
|
after = json.overview.data.children[posts_limit - 1].data.name;
|
||||||
|
}
|
||||||
|
if (json.overview.data.children[0]) {
|
||||||
|
before = json.overview.data.children[0].data.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < posts_limit; i++) {
|
||||||
|
let post = json.overview.data.children[i].data;
|
||||||
|
let thumbnail = 'self';
|
||||||
|
let type = json.overview.data.children[i].kind;
|
||||||
|
let obj;
|
||||||
|
|
||||||
|
let post_id = post.permalink.split('/').slice(-2)[0] + '/';
|
||||||
|
let url = post.permalink.replace(post_id, '');
|
||||||
|
|
||||||
|
if (type !== kind && kind) continue;
|
||||||
|
|
||||||
|
if (post.over_18)
|
||||||
|
if (
|
||||||
|
(config.nsfw_enabled === false &&
|
||||||
|
user_preferences.nsfw_enabled != 'true') ||
|
||||||
|
user_preferences.nsfw_enabled === 'false'
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (type === 't3') {
|
||||||
|
obj = await link.fromJson(post, user_preferences);
|
||||||
|
obj.type = 't3';
|
||||||
|
}
|
||||||
|
if (type === 't1') {
|
||||||
|
obj = {
|
||||||
|
type: type,
|
||||||
|
subreddit: post.subreddit,
|
||||||
|
title: post.title,
|
||||||
|
created: post.created_utc,
|
||||||
|
subreddit_name_prefixed: post.subreddit_name_prefixed,
|
||||||
|
ups: post.ups,
|
||||||
|
url: replaceDomains(url, user_preferences),
|
||||||
|
edited: post.edited,
|
||||||
|
body_html: unescape(post.body_html),
|
||||||
|
num_comments: post.num_comments,
|
||||||
|
over_18: post.over_18,
|
||||||
|
permalink: post.permalink,
|
||||||
|
link_author: post.link_author,
|
||||||
|
link_title: post.link_title,
|
||||||
|
user_flair:
|
||||||
|
user_preferences.flairs != 'false' ? await formatUserFlair(post) : '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
posts.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
let obj = {
|
||||||
|
username: about.name,
|
||||||
|
icon_img: await downloadAndSave(about.icon_img, 'icon_'),
|
||||||
|
created: about.created_utc,
|
||||||
|
verified: about.verified,
|
||||||
|
link_karma: about.link_karma,
|
||||||
|
comment_karma: about.comment_karma,
|
||||||
|
view_more_posts: view_more_posts,
|
||||||
|
user_front: user_front,
|
||||||
|
post_type: post_type,
|
||||||
|
before: before,
|
||||||
|
after: after,
|
||||||
|
posts: posts,
|
||||||
|
};
|
||||||
|
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = processJsonUser;
|
||||||
|
|
|
@ -1,54 +1,51 @@
|
||||||
module.exports = function() {
|
const config = require('../config');
|
||||||
const config = require('../config')
|
const { redisAsync } = require('./redis');
|
||||||
this.moreComments = (fetch, redis, post_url, comment_ids, id) => {
|
|
||||||
return new Promise(resolve => {
|
async function processMoreComments(fetch, redis, post_url, comment_ids, id) {
|
||||||
(async () => {
|
if (post_url) {
|
||||||
let key = `${post_url}:morechildren:comment_ids:${comment_ids}`
|
let key = `${post_url}:morechildren:comment_ids:${comment_ids}`
|
||||||
redis.get(key, (error, json) => {
|
|
||||||
if(error) {
|
try {
|
||||||
console.error(`Error getting the ${key} key from redis (moreComments()).`, error)
|
const cached = await redisAsync.get(key);
|
||||||
resolve(false)
|
|
||||||
|
if (cached !== null) {
|
||||||
|
return JSON.parse(cached);
|
||||||
|
}
|
||||||
|
let url = `https://oauth.reddit.com/api/morechildren?api_type=json&children=${comment_ids}&limit_children=false&link_id=t3_${id}`
|
||||||
|
const moreCommentsRequest = await fetch(url, redditApiGETHeaders());
|
||||||
|
|
||||||
|
if (moreCommentsRequest.ok) {
|
||||||
|
let response = await moreCommentsRequest.json();
|
||||||
|
|
||||||
|
if (response.json.data) {
|
||||||
|
if (response.json.data.things) {
|
||||||
|
let comments = response.json.data.things
|
||||||
|
await redisAsync.setex(
|
||||||
|
key,
|
||||||
|
config.setexs.posts,
|
||||||
|
JSON.stringify(comments)
|
||||||
|
);
|
||||||
|
console.log(`Fetched more comments.`);
|
||||||
|
|
||||||
|
return comments;
|
||||||
}
|
}
|
||||||
if(json) {
|
}
|
||||||
json = JSON.parse(json)
|
} else {
|
||||||
resolve(json)
|
console.error(
|
||||||
} else {
|
`Something went wrong while fetching data from Reddit:
|
||||||
let url = `https://oauth.reddit.com/api/morechildren?api_type=json&children=${comment_ids}&limit_children=false&link_id=t3_${id}`
|
${moreCommentsRequest.status} – ${moreCommentsRequest.statusText}`
|
||||||
fetch(encodeURI(url), redditApiGETHeaders())
|
);
|
||||||
.then(result => {
|
console.error(config.reddit_api_error_text);
|
||||||
if(result.status === 200) {
|
return null;
|
||||||
result.json()
|
}
|
||||||
.then(json => {
|
} catch (error) {
|
||||||
if(json.json.data) {
|
console.error('Error fetching more comments: ', error);
|
||||||
if(json.json.data.things) {
|
|
||||||
let comments = json.json.data.things
|
return null;
|
||||||
redis.setex(key, config.setexs.posts, JSON.stringify(comments), (error) => {
|
}
|
||||||
if(error) {
|
} else {
|
||||||
console.error(`Error setting the ${key} key to redis (moreComments()).`, error)
|
return null;
|
||||||
resolve(false)
|
|
||||||
} else {
|
|
||||||
console.log(`Fetched the JSON from Reddit (endpoint "morechildren") for URL: ${post_url}. (moreComments())`)
|
|
||||||
resolve(comments)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
resolve(false)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
resolve(false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
console.error(`Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText} (moreComments())`)
|
|
||||||
resolve(false)
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
console.log(`Error fetching the JSON from Reddit (endpoint "morechildren") with url: ${url}. (moreComments())`, error)
|
|
||||||
resolve(false)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = processMoreComments;
|
||||||
|
|
|
@ -92,12 +92,23 @@ module.exports = function() {
|
||||||
obj.has_media = true
|
obj.has_media = true
|
||||||
if(!gif_to_mp4) {
|
if(!gif_to_mp4) {
|
||||||
if(post.preview) {
|
if(post.preview) {
|
||||||
obj.media = {
|
if(post.preview.reddit_video_preview) {
|
||||||
source: await downloadAndSave(post.preview.reddit_video_preview.fallback_url),
|
const url = post.domain === 'i.imgur.com'
|
||||||
height: post.preview.reddit_video_preview.height,
|
? replaceDomains(post.url_overridden_by_dest.replace(/\.gifv$/, '.mp4'))
|
||||||
width: post.preview.reddit_video_preview.width,
|
: post.preview.reddit_video_preview.fallback_url;
|
||||||
duration: post.preview.reddit_video_preview.duration,
|
if(url) {
|
||||||
is_gif: true
|
obj.media = {
|
||||||
|
source: await downloadAndSave(url),
|
||||||
|
height: post.preview.reddit_video_preview.height,
|
||||||
|
width: post.preview.reddit_video_preview.width,
|
||||||
|
duration: post.preview.reddit_video_preview.duration,
|
||||||
|
is_gif: true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
obj.has_media = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
obj.has_media = false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
obj.has_media = false
|
obj.has_media = false
|
||||||
|
@ -119,12 +130,26 @@ module.exports = function() {
|
||||||
*/
|
*/
|
||||||
if(!post_media && !has_gif && !post.gallery_data && post.url != '') {
|
if(!post_media && !has_gif && !post.gallery_data && post.url != '') {
|
||||||
try {
|
try {
|
||||||
let u = new URL(post.url)
|
let url = replaceDomains(post.url)
|
||||||
|
const u = new URL(url)
|
||||||
if(config.valid_media_domains.includes(u.hostname)) {
|
if(config.valid_media_domains.includes(u.hostname)) {
|
||||||
let ext = u.pathname.split('.')[1]
|
const ext = u.pathname.split('.')[1]
|
||||||
if(ext === 'jpg' || ext === 'png') {
|
if(['jpg', 'png', 'jpeg', 'gif'].includes(ext)) {
|
||||||
obj.images = {
|
obj.images = {
|
||||||
source: await downloadAndSave(post.url)
|
source: await downloadAndSave(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(['gifv', 'mp4'].includes(ext)) {
|
||||||
|
if (obj.domain === 'i.imgur.com') {
|
||||||
|
url = url.replace(/\.gifv$/, '.mp4');
|
||||||
|
}
|
||||||
|
obj.has_media = true
|
||||||
|
obj.media = {
|
||||||
|
source: await downloadAndSave(url)
|
||||||
|
}
|
||||||
|
if (post.preview && post.preview.images) {
|
||||||
|
obj.media.height = post.preview.images[0].source.height;
|
||||||
|
obj.media.width = post.preview.images[0].source.width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,62 +1,70 @@
|
||||||
module.exports = function() {
|
const config = require('../config');
|
||||||
const config = require('../config');
|
const link = require('./components/link');
|
||||||
const link = require('./components/link')
|
|
||||||
this.processSearchResults = (json, parsed, after, before, user_preferences) => {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
(async () => {
|
|
||||||
if(!parsed) {
|
|
||||||
json = JSON.parse(json)
|
|
||||||
}
|
|
||||||
let posts = []
|
|
||||||
let search_firstpage = false
|
|
||||||
let before = json.data.before
|
|
||||||
let after = json.data.after
|
|
||||||
|
|
||||||
if(!after && !before) {
|
|
||||||
search_firstpage = true
|
|
||||||
}
|
|
||||||
|
|
||||||
let suggested_subreddits = false
|
|
||||||
if(json.suggested_subreddits) {
|
|
||||||
if(json.suggested_subreddits.data) {
|
|
||||||
if(json.suggested_subreddits.data.children.length > 0) {
|
|
||||||
suggested_subreddits = json.suggested_subreddits.data.children
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(json.data.children) {
|
|
||||||
let view_more_posts = false
|
|
||||||
let posts_limit = 25
|
|
||||||
|
|
||||||
if(json.data.children.length > posts_limit) {
|
async function processSearchResults(
|
||||||
view_more_posts = true
|
json,
|
||||||
} else {
|
parsed,
|
||||||
posts_limit = json.data.children.length
|
after,
|
||||||
}
|
before,
|
||||||
|
user_preferences
|
||||||
for(var i = 0; i < posts_limit; i++) {
|
) {
|
||||||
let post = json.data.children[i].data
|
if (!parsed) {
|
||||||
|
json = JSON.parse(json);
|
||||||
if(post.over_18)
|
|
||||||
if((config.nsfw_enabled === false && user_preferences.nsfw_enabled != 'true') || user_preferences.nsfw_enabled === 'false')
|
|
||||||
continue
|
|
||||||
|
|
||||||
let obj = await link.fromJson(post, user_preferences)
|
|
||||||
posts.push(obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let obj = {
|
|
||||||
search_firstpage: search_firstpage,
|
|
||||||
before: before,
|
|
||||||
after: after,
|
|
||||||
posts: posts,
|
|
||||||
suggested_subreddits: suggested_subreddits,
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(obj)
|
|
||||||
})()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
let posts = [];
|
||||||
|
let search_firstpage = false;
|
||||||
|
|
||||||
|
before = json.data.before;
|
||||||
|
after = json.data.after;
|
||||||
|
|
||||||
|
if (!after && !before) {
|
||||||
|
search_firstpage = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let suggested_subreddits = false;
|
||||||
|
if (json.suggested_subreddits) {
|
||||||
|
if (json.suggested_subreddits.data) {
|
||||||
|
if (json.suggested_subreddits.data.children.length > 0) {
|
||||||
|
suggested_subreddits = json.suggested_subreddits.data.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.data.children) {
|
||||||
|
let view_more_posts = false;
|
||||||
|
let posts_limit = 25;
|
||||||
|
|
||||||
|
if (json.data.children.length > posts_limit) {
|
||||||
|
view_more_posts = true;
|
||||||
|
} else {
|
||||||
|
posts_limit = json.data.children.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < posts_limit; i++) {
|
||||||
|
let post = json.data.children[i].data;
|
||||||
|
|
||||||
|
if (post.over_18)
|
||||||
|
if (
|
||||||
|
(config.nsfw_enabled === false &&
|
||||||
|
user_preferences.nsfw_enabled != 'true') ||
|
||||||
|
user_preferences.nsfw_enabled === 'false'
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let obj = await link.fromJson(post, user_preferences);
|
||||||
|
posts.push(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let obj = {
|
||||||
|
search_firstpage: search_firstpage,
|
||||||
|
before: before,
|
||||||
|
after: after,
|
||||||
|
posts: posts,
|
||||||
|
suggested_subreddits: suggested_subreddits,
|
||||||
|
};
|
||||||
|
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = processSearchResults;
|
||||||
|
|
|
@ -1,106 +1,78 @@
|
||||||
module.exports = function() {
|
const config = require('../config');
|
||||||
const config = require('../config')
|
const { redisAsync } = require('./redis');
|
||||||
this.processSubredditAbout = (subreddit, redis, fetch, RedditAPI) => {
|
|
||||||
return new Promise(resolve => {
|
function returnRelevantKeys(json) {
|
||||||
(async () => {
|
return {
|
||||||
if(subreddit && !subreddit.includes('+') && subreddit !== 'all') {
|
title: json.data.title,
|
||||||
function returnRelevantKeys(json) {
|
public_description_html: json.data.public_description_html,
|
||||||
return {
|
active_user_count: json.data.active_user_count,
|
||||||
title: json.data.title,
|
subscribers: json.data.subscribers,
|
||||||
public_description_html: json.data.public_description_html,
|
created_utc: json.data.created_utc,
|
||||||
active_user_count: json.data.active_user_count,
|
over18: json.data.over18,
|
||||||
subscribers: json.data.subscribers,
|
description_html: json.data.description_html,
|
||||||
created_utc: json.data.created_utc,
|
moderators: json.moderators,
|
||||||
over18: json.data.over18,
|
};
|
||||||
description_html: json.data.description_html,
|
}
|
||||||
moderators: json.moderators
|
|
||||||
}
|
async function processSubredditAbout(subreddit, redis, fetch, RedditAPI) {
|
||||||
}
|
if (subreddit && !subreddit.includes('+') && subreddit !== 'all') {
|
||||||
|
const key = `${subreddit}:sidebar`;
|
||||||
let key = `${subreddit}:sidebar`
|
|
||||||
redis.get(key, (error, json) => {
|
try {
|
||||||
if(error) {
|
const cached = await redisAsync.get(key);
|
||||||
console.error(`Error getting the ${subreddit}:sidebar key from redis.`, error)
|
|
||||||
resolve(null)
|
if (cached !== null) {
|
||||||
}
|
return returnRelevantKeys(JSON.parse(cached));
|
||||||
if(json) {
|
}
|
||||||
json = JSON.parse(json)
|
|
||||||
resolve(returnRelevantKeys(json))
|
let url = `https://reddit.com/r/${subreddit}/about.json`;
|
||||||
} else {
|
|
||||||
let url = `https://reddit.com/r/${subreddit}/about.json`
|
if (config.use_reddit_oauth) {
|
||||||
if(config.use_reddit_oauth) {
|
url = `https://oauth.reddit.com/r/${subreddit}/about`;
|
||||||
url = `https://oauth.reddit.com/r/${subreddit}/about`
|
}
|
||||||
}
|
|
||||||
fetch(encodeURI(url), redditApiGETHeaders())
|
const subredditAboutRequest = await fetch(url, redditApiGETHeaders());
|
||||||
.then(result => {
|
|
||||||
if(result.status === 200) {
|
if (subredditAboutRequest.ok) {
|
||||||
result.json()
|
let response = await subredditAboutRequest.json();
|
||||||
.then(json => {
|
response.moderators = [];
|
||||||
json.moderators = []
|
|
||||||
redis.setex(key, config.setexs.sidebar, JSON.stringify(json), (error) => {
|
await redisAsync.setex(
|
||||||
if(error) {
|
key,
|
||||||
console.error('Error setting the sidebar key to redis.', error)
|
config.setexs.sidebar,
|
||||||
return res.render('index', { json: null, user_preferences: req.cookies })
|
JSON.stringify(response)
|
||||||
} else {
|
);
|
||||||
console.log('Fetched the sidebar from reddit API.')
|
|
||||||
let moderators_url = `https://reddit.com/r/${subreddit}/about/moderators.json`
|
console.log(`Fetched sidebar for ${subreddit} from reddit API`);
|
||||||
if(config.use_reddit_oauth) {
|
|
||||||
moderators_url = `https://oauth.reddit.com/r/${subreddit}/about/moderators`
|
return returnRelevantKeys(response);
|
||||||
}
|
} else {
|
||||||
resolve(returnRelevantKeys(json))
|
console.error(
|
||||||
/*
|
`Something went wrong while fetching data from reddit API:
|
||||||
* The following code is commented out because Reddit doesn't
|
${subredditAboutRequest.status} – ${subredditAboutRequest.statusText}`
|
||||||
* anymore support fetching moderators for subreddits
|
);
|
||||||
* when not logged in.
|
console.error(config.reddit_api_error_text);
|
||||||
* This might change in the future though.
|
return null;
|
||||||
* https://codeberg.org/teddit/teddit/issues/207
|
}
|
||||||
*/
|
} catch (error) {
|
||||||
|
console.error('Error fetching the sidebar: ', error);
|
||||||
/*
|
|
||||||
fetch(encodeURI(moderators_url), redditApiGETHeaders())
|
return null;
|
||||||
.then(mod_result => {
|
}
|
||||||
if(mod_result.status === 200) {
|
} else {
|
||||||
mod_result.json()
|
return null;
|
||||||
.then(mod_json => {
|
|
||||||
json.moderators = mod_json
|
|
||||||
redis.setex(key, config.setexs.sidebar, JSON.stringify(json), (error) => {
|
|
||||||
if(error) {
|
|
||||||
console.error('Error setting the sidebar with moderators key to redis.', error)
|
|
||||||
return res.render('index', { json: null, user_preferences: req.cookies })
|
|
||||||
} else {
|
|
||||||
console.log('Fetched the moderators from reddit API.')
|
|
||||||
resolve(returnRelevantKeys(json))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
console.error(`Something went wrong while fetching moderators data from reddit API. ${mod_result.status} – ${mod_result.statusText}`)
|
|
||||||
console.error(config.reddit_api_error_text)
|
|
||||||
resolve(returnRelevantKeys(json))
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('Error fetching moderators.', error)
|
|
||||||
resolve(returnRelevantKeys(json))
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
console.error(`Something went wrong while fetching data from reddit API. ${result.status} – ${result.statusText}`)
|
|
||||||
console.error(config.reddit_api_error_text)
|
|
||||||
resolve(null)
|
|
||||||
}
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('Error fetching the sidebar.', error)
|
|
||||||
resolve(null)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
resolve(null)
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function processJsonSubredditAbout(json, parsed) {
|
||||||
|
if (!parsed) {
|
||||||
|
json = JSON.parse(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnRelevantKeys(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
processSubredditAbout,
|
||||||
|
processJsonSubredditAbout
|
||||||
|
};
|
||||||
|
|
|
@ -1,52 +1,58 @@
|
||||||
module.exports = function() {
|
const config = require('../config');
|
||||||
const config = require('../config');
|
|
||||||
this.processJsonSubredditsExplore = (json, from, subreddit_front, user_preferences) => {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
(async () => {
|
|
||||||
if(from === 'redis') {
|
|
||||||
json = JSON.parse(json)
|
|
||||||
}
|
|
||||||
if(json.error) {
|
|
||||||
resolve({ error: true, error_data: json })
|
|
||||||
} else {
|
|
||||||
let before = json.data.before
|
|
||||||
let after = json.data.after
|
|
||||||
|
|
||||||
let ret = {
|
async function processJsonSubredditsExplore(
|
||||||
info: {
|
json,
|
||||||
before: before,
|
from,
|
||||||
after: after
|
subreddit_front,
|
||||||
},
|
user_preferences
|
||||||
links: []
|
) {
|
||||||
}
|
if (from === 'redis') {
|
||||||
|
json = JSON.parse(json);
|
||||||
|
}
|
||||||
|
if (json.error) {
|
||||||
|
return { error: true, error_data: json };
|
||||||
|
} else {
|
||||||
|
let before = json.data.before;
|
||||||
|
let after = json.data.after;
|
||||||
|
|
||||||
let children_len = json.data.children.length
|
let ret = {
|
||||||
|
info: {
|
||||||
|
before: before,
|
||||||
|
after: after,
|
||||||
|
},
|
||||||
|
links: [],
|
||||||
|
};
|
||||||
|
|
||||||
for(var i = 0; i < children_len; i++) {
|
let children_len = json.data.children.length;
|
||||||
let data = json.data.children[i].data
|
|
||||||
|
for (var i = 0; i < children_len; i++) {
|
||||||
if(data.over_18)
|
let data = json.data.children[i].data;
|
||||||
if((config.nsfw_enabled === false && user_preferences.nsfw_enabled != 'true') || user_preferences.nsfw_enabled === 'false')
|
|
||||||
continue
|
if (data.over_18)
|
||||||
|
if (
|
||||||
let obj = {
|
(config.nsfw_enabled === false &&
|
||||||
created: data.created_utc,
|
user_preferences.nsfw_enabled != 'true') ||
|
||||||
id: data.id,
|
user_preferences.nsfw_enabled === 'false'
|
||||||
over_18: data.over_18,
|
)
|
||||||
display_name: data.display_name,
|
continue;
|
||||||
display_name_prefixed: data.display_name_prefixed,
|
|
||||||
public_description: data.public_description,
|
let obj = {
|
||||||
url: replaceDomains(data.url, user_preferences),
|
created: data.created_utc,
|
||||||
subscribers: data.subscribers,
|
id: data.id,
|
||||||
over_18: data.over18,
|
over_18: data.over_18,
|
||||||
title: data.title,
|
display_name: data.display_name,
|
||||||
subreddit_front: subreddit_front,
|
display_name_prefixed: data.display_name_prefixed,
|
||||||
}
|
public_description: data.public_description,
|
||||||
ret.links.push(obj)
|
url: replaceDomains(data.url, user_preferences),
|
||||||
}
|
subscribers: data.subscribers,
|
||||||
resolve(ret)
|
over_18: data.over18,
|
||||||
}
|
title: data.title,
|
||||||
})()
|
subreddit_front: subreddit_front,
|
||||||
})
|
};
|
||||||
|
ret.links.push(obj);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = processJsonSubredditsExplore;
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
const config = require('../config');
|
||||||
|
const { promisify } = require('util');
|
||||||
|
const r = require('redis');
|
||||||
|
|
||||||
|
const redisOptions = {
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: 6379,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (config.redis_db) {
|
||||||
|
redisOptions.db = config.redis_db;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.redis_host) {
|
||||||
|
redisOptions.host = config.redis_host;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.redis_port && config.redis_port > 0) {
|
||||||
|
redisOptions.port = config.redis_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.redis_password) {
|
||||||
|
redisOptions.password = config.redis_password;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stub Redis if disabled
|
||||||
|
const stub = {
|
||||||
|
get: (_, callback) => callback(null, null),
|
||||||
|
setex: (_, _1, _2, callback) => callback(null),
|
||||||
|
on: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const redisDisabled = !config.redis_enabled;
|
||||||
|
|
||||||
|
const redis = redisDisabled ? stub : r.createClient(redisOptions);
|
||||||
|
|
||||||
|
const redisAsync = {
|
||||||
|
get: promisify(redis.get).bind(redis),
|
||||||
|
setex: promisify(redis.setex).bind(redis),
|
||||||
|
};
|
||||||
|
|
||||||
|
redis.on('error', (error) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(`Redis error: ${error}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
redis,
|
||||||
|
redisAsync,
|
||||||
|
};
|
|
@ -0,0 +1,87 @@
|
||||||
|
const { processJsonPost, getPostItem } = require('../processJsonPost');
|
||||||
|
|
||||||
|
module.exports = function () {
|
||||||
|
const config = require('../../config');
|
||||||
|
this.handleTedditApiPost = async (
|
||||||
|
json,
|
||||||
|
req,
|
||||||
|
res,
|
||||||
|
from,
|
||||||
|
api_type,
|
||||||
|
api_target
|
||||||
|
) => {
|
||||||
|
if (!config.api_enabled) {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
let msg = {
|
||||||
|
info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.',
|
||||||
|
};
|
||||||
|
return res.end(JSON.stringify(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Teddit API request - post');
|
||||||
|
if (from === 'redis') json = JSON.parse(json);
|
||||||
|
|
||||||
|
if (api_type === 'rss') {
|
||||||
|
let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http';
|
||||||
|
let items = '';
|
||||||
|
|
||||||
|
let post = json[0].data.children[0].data;
|
||||||
|
let comments = json[1].data.children;
|
||||||
|
|
||||||
|
items += await getPostItem(post, req, protocol);
|
||||||
|
|
||||||
|
for (var i = 0; i < comments.length; i++) {
|
||||||
|
let comment = comments[i].data;
|
||||||
|
let kind = comments[i].kind;
|
||||||
|
|
||||||
|
let title = `/u/${comment.author} on ${post.title}`;
|
||||||
|
|
||||||
|
comment.permalink = `${protocol}://${config.domain}${comment.permalink}`;
|
||||||
|
|
||||||
|
if (kind !== 'more') {
|
||||||
|
items += `
|
||||||
|
<item>
|
||||||
|
<title>${title}</title>
|
||||||
|
<author>${comment.author}</author>
|
||||||
|
<created>${comment.created}</created>
|
||||||
|
<pubDate>${new Date(
|
||||||
|
comment.created_utc * 1000
|
||||||
|
).toGMTString()}</pubDate>
|
||||||
|
<id>${comment.id}</id>
|
||||||
|
<link>${comment.permalink}</link>
|
||||||
|
<description><![CDATA[${unescape(
|
||||||
|
comment.body_html
|
||||||
|
)}]]></description>
|
||||||
|
<ups>${comment.ups}</ups>
|
||||||
|
</item>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let xml_output = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
|
||||||
|
<channel>
|
||||||
|
<atom:link href="${post.permalink}?api&type=rss" rel="self" type="application/rss+xml" />
|
||||||
|
<title>${post.title}</title>
|
||||||
|
<link>${post.url}</link>
|
||||||
|
${items}
|
||||||
|
</channel>
|
||||||
|
</rss>`;
|
||||||
|
res.setHeader('Content-Type', 'application/rss+xml');
|
||||||
|
return res.end(xml_output);
|
||||||
|
} else {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
if (api_target === 'reddit') {
|
||||||
|
return res.end(JSON.stringify(json));
|
||||||
|
} else {
|
||||||
|
let processed_json = await processJsonPost(
|
||||||
|
json,
|
||||||
|
true,
|
||||||
|
req.cookies
|
||||||
|
);
|
||||||
|
|
||||||
|
return res.end(JSON.stringify(processed_json));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,114 +1,52 @@
|
||||||
module.exports = function() {
|
const processJsonSubreddit = require('../processJsonSubreddit');
|
||||||
const config = require('../../config')
|
const { processJsonSubredditAbout } = require('../processSubredditAbout');
|
||||||
this.handleTedditApiSubreddit = async (json, req, res, from, api_type, api_target, subreddit) => {
|
const processSearchResults = require('../processSearchResults.js');
|
||||||
if(!config.api_enabled) {
|
const { processJsonPostList, getPostItem } = require('../processJsonPost');
|
||||||
res.setHeader('Content-Type', 'application/json')
|
const processJsonSubredditsExplore = require('../processSubredditsExplore.js');
|
||||||
let msg = { info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.' }
|
|
||||||
return res.end(JSON.stringify(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Teddit API request - subreddit')
|
|
||||||
let _json = json // Keep the original json
|
|
||||||
if(from === 'redis')
|
|
||||||
json = JSON.parse(json)
|
|
||||||
|
|
||||||
if(api_type === 'rss') {
|
|
||||||
let protocol = (config.https_enabled ? 'https' : 'http')
|
|
||||||
let items = ''
|
|
||||||
for(var i = 0; i < json.data.children.length; i++) {
|
|
||||||
let link = json.data.children[i].data
|
|
||||||
let thumbnail = ''
|
|
||||||
let post_image = ''
|
|
||||||
let is_self_link = false
|
|
||||||
let valid_reddit_self_domains = ['reddit.com']
|
|
||||||
|
|
||||||
if(link.domain) {
|
module.exports = function () {
|
||||||
let tld = link.domain.split('self.')
|
const config = require('../../config');
|
||||||
if(tld.length > 1) {
|
this.handleTedditApiSubreddit = async (
|
||||||
if(!tld[1].includes('.')) {
|
json,
|
||||||
is_self_link = true
|
req,
|
||||||
link.url = teddifyUrl(link.url)
|
res,
|
||||||
}
|
from,
|
||||||
}
|
api_type,
|
||||||
if(config.valid_media_domains.includes(link.domain) || valid_reddit_self_domains.includes(link.domain)) {
|
api_target,
|
||||||
is_self_link = true
|
subreddit,
|
||||||
link.url = teddifyUrl(link.url)
|
mode
|
||||||
}
|
) => {
|
||||||
}
|
if (!config.api_enabled) {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
if(link.preview && link.thumbnail !== 'self') {
|
let msg = {
|
||||||
if(!link.url.startsWith('/r/') && isGif(link.url)) {
|
info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.',
|
||||||
let s = await downloadAndSave(link.thumbnail, 'thumb_')
|
};
|
||||||
thumbnail = `${protocol}://${config.domain}${s}`
|
return res.end(JSON.stringify(msg));
|
||||||
} else {
|
}
|
||||||
if(link.preview.images[0].resolutions[0]) {
|
|
||||||
let s = await downloadAndSave(link.preview.images[0].resolutions[0].url, 'thumb_')
|
console.log('Teddit API request - subreddit');
|
||||||
thumbnail = `${protocol}://${config.domain}${s}`
|
let _json = json; // Keep the original json
|
||||||
if(!isGif(link.url) && !link.post_hint.includes(':video')) {
|
if (from === 'redis') json = JSON.parse(json);
|
||||||
s = await downloadAndSave(link.preview.images[0].source.url)
|
|
||||||
post_image = `${protocol}://${config.domain}${s}`
|
if (api_type === 'rss') {
|
||||||
}
|
let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http';
|
||||||
}
|
let items = '';
|
||||||
}
|
|
||||||
}
|
for (var i = 0; i < json.data.children.length; i++) {
|
||||||
|
let post = json.data.children[i].data;
|
||||||
link.permalink = `${protocol}://${config.domain}${link.permalink}`
|
items += await getPostItem(post, req, protocol);
|
||||||
|
|
||||||
if(is_self_link)
|
|
||||||
link.url = link.permalink
|
|
||||||
|
|
||||||
if(req.query.hasOwnProperty('full_thumbs')) {
|
|
||||||
if(!post_image)
|
|
||||||
post_image = thumbnail
|
|
||||||
|
|
||||||
thumbnail = post_image
|
|
||||||
}
|
|
||||||
|
|
||||||
let enclosure = ''
|
|
||||||
if(thumbnail != '') {
|
|
||||||
let mime = ''
|
|
||||||
let ext = thumbnail.split('.').pop()
|
|
||||||
if(ext === 'png')
|
|
||||||
mime = 'image/png'
|
|
||||||
else
|
|
||||||
mime = 'image/jpeg'
|
|
||||||
enclosure = `<enclosure length="0" type="${mime}" url="${thumbnail}" />`
|
|
||||||
}
|
|
||||||
|
|
||||||
let append_desc_html = `<br/><a href="${link.url}">[link]</a> <a href="${link.permalink}">[comments]</a>`
|
|
||||||
|
|
||||||
items += `
|
|
||||||
<item>
|
|
||||||
<title>${link.title}</title>
|
|
||||||
<author>${link.author}</author>
|
|
||||||
<created>${link.created}</created>
|
|
||||||
<pubDate>${new Date(link.created_utc*1000).toGMTString()}</pubDate>
|
|
||||||
<domain>${link.domain}</domain>
|
|
||||||
<id>${link.id}</id>
|
|
||||||
<thumbnail>${thumbnail}</thumbnail>
|
|
||||||
${enclosure}
|
|
||||||
<link>${link.permalink}</link>
|
|
||||||
<url>${link.url}</url>
|
|
||||||
<description><![CDATA[${unescape(link.selftext_html)}${append_desc_html}]]></description>
|
|
||||||
<num_comments>${link.num_comments}</num_comments>
|
|
||||||
<ups>${link.ups}</ups>
|
|
||||||
<stickied>${link.stickied}</stickied>
|
|
||||||
<is_self_link>${is_self_link}</is_self_link>
|
|
||||||
</item>
|
|
||||||
`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let r_subreddit = '/r/' + subreddit
|
let r_subreddit = '/r/' + subreddit;
|
||||||
let title = r_subreddit
|
let title = r_subreddit;
|
||||||
let link = `${protocol}://${config.domain}${r_subreddit}`
|
let link = `${protocol}://${config.domain}${r_subreddit}`;
|
||||||
if(subreddit === '/') {
|
if (subreddit === '/') {
|
||||||
r_subreddit = 'frontpage'
|
r_subreddit = 'frontpage';
|
||||||
title = 'teddit frontpage'
|
title = 'teddit frontpage';
|
||||||
link = `${protocol}://${config.domain}`
|
link = `${protocol}://${config.domain}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
let xml_output =
|
let xml_output = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
`<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
|
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
|
||||||
<channel>
|
<channel>
|
||||||
<atom:link href="${link}/?api&type=rss" rel="self" type="application/rss+xml" />
|
<atom:link href="${link}/?api&type=rss" rel="self" type="application/rss+xml" />
|
||||||
|
@ -117,50 +55,203 @@ module.exports = function() {
|
||||||
<description>Subreddit feed for: ${r_subreddit}</description>
|
<description>Subreddit feed for: ${r_subreddit}</description>
|
||||||
${items}
|
${items}
|
||||||
</channel>
|
</channel>
|
||||||
</rss>`
|
</rss>`;
|
||||||
res.setHeader('Content-Type', 'application/rss+xml')
|
res.setHeader('Content-Type', 'application/rss+xml');
|
||||||
return res.end(xml_output)
|
return res.end(xml_output);
|
||||||
} else {
|
} else {
|
||||||
res.setHeader('Content-Type', 'application/json')
|
res.setHeader('Content-Type', 'application/json');
|
||||||
if(api_target === 'reddit') {
|
if (api_target === 'reddit') {
|
||||||
return res.end(JSON.stringify(json))
|
return res.end(JSON.stringify(json));
|
||||||
} else {
|
} else {
|
||||||
let processed_json = await processJsonSubreddit(_json, from, null, req.cookies)
|
let processed_json = await processJsonSubreddit(
|
||||||
|
_json,
|
||||||
let protocol = (config.https_enabled ? 'https' : 'http')
|
from,
|
||||||
for(var i = 0; i < processed_json.links.length; i++) {
|
null,
|
||||||
let link = processed_json.links[i]
|
req.cookies
|
||||||
let valid_reddit_self_domains = ['reddit.com']
|
);
|
||||||
let is_self_link = false
|
|
||||||
|
|
||||||
if(link.domain) {
|
await processJsonPostList(processed_json.links, mode);
|
||||||
let tld = link.domain.split('self.')
|
|
||||||
if(tld.length > 1) {
|
return res.end(JSON.stringify(processed_json));
|
||||||
if(!tld[1].includes('.')) {
|
}
|
||||||
is_self_link = true
|
|
||||||
link.url = teddifyUrl(link.url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(config.valid_media_domains.includes(link.domain) || valid_reddit_self_domains.includes(link.domain)) {
|
|
||||||
is_self_link = true
|
|
||||||
link.url = teddifyUrl(link.url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
link.permalink = `${protocol}://${config.domain}${link.permalink}`
|
|
||||||
|
|
||||||
if(is_self_link)
|
|
||||||
link.url = link.permalink
|
|
||||||
|
|
||||||
if(link.images) {
|
|
||||||
if(link.images.thumb !== 'self') {
|
|
||||||
link.images.thumb = `${protocol}://${config.domain}${link.images.thumb}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.end(JSON.stringify(processed_json))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
this.handleTedditApiSubredditAbout = async (
|
||||||
|
json,
|
||||||
|
res,
|
||||||
|
from,
|
||||||
|
api_target
|
||||||
|
) => {
|
||||||
|
if (!config.api_enabled) {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
let msg = {
|
||||||
|
info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.',
|
||||||
|
};
|
||||||
|
return res.end(JSON.stringify(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Teddit API request - subreddit about');
|
||||||
|
if (from === 'redis') json = JSON.parse(json);
|
||||||
|
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
|
||||||
|
if (api_target === 'reddit') {
|
||||||
|
return res.end(JSON.stringify(json));
|
||||||
|
} else {
|
||||||
|
let subreddit_about = await processJsonSubredditAbout(
|
||||||
|
json,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
return res.end(JSON.stringify(subreddit_about));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.handleTedditApiSubredditSearch = async (
|
||||||
|
json,
|
||||||
|
req,
|
||||||
|
res,
|
||||||
|
from,
|
||||||
|
api_type,
|
||||||
|
api_target,
|
||||||
|
subreddit,
|
||||||
|
query,
|
||||||
|
mode
|
||||||
|
) => {
|
||||||
|
if (!config.api_enabled) {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
let msg = {
|
||||||
|
info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.',
|
||||||
|
};
|
||||||
|
return res.end(JSON.stringify(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Teddit API request - subreddit search');
|
||||||
|
if (from === 'redis') json = JSON.parse(json);
|
||||||
|
|
||||||
|
if (api_type === 'rss') {
|
||||||
|
let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http';
|
||||||
|
let items = '';
|
||||||
|
|
||||||
|
for (var i = 0; i < json.data.children.length; i++) {
|
||||||
|
let post = json.data.children[i].data;
|
||||||
|
items += await getPostItem(post, req, protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
let r_subreddit = '/r/' + subreddit;
|
||||||
|
let title = `${query} - ${r_subreddit}`;
|
||||||
|
let link = `${protocol}://${config.domain}${r_subreddit}/search?q=${query}`;
|
||||||
|
|
||||||
|
let xml_output = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
|
||||||
|
<channel>
|
||||||
|
<atom:link href="${link}&api&type=rss" rel="self" type="application/rss+xml" />
|
||||||
|
<title>${title}</title>
|
||||||
|
<link>${link}</link>
|
||||||
|
<description>Results for: ${query} - ${r_subreddit}</description>
|
||||||
|
${items}
|
||||||
|
</channel>
|
||||||
|
</rss>`;
|
||||||
|
|
||||||
|
res.setHeader('Content-Type', 'application/rss+xml');
|
||||||
|
|
||||||
|
return res.end(xml_output);
|
||||||
|
} else {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
if (api_target === 'reddit') {
|
||||||
|
return res.end(JSON.stringify(json));
|
||||||
|
} else {
|
||||||
|
let processed_json = await processSearchResults(
|
||||||
|
json,
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
req.cookies
|
||||||
|
);
|
||||||
|
|
||||||
|
await processJsonPostList(processed_json.posts, mode);
|
||||||
|
|
||||||
|
return res.end(JSON.stringify(processed_json));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.handleTedditApiSubredditsExplore = async (
|
||||||
|
json,
|
||||||
|
req,
|
||||||
|
res,
|
||||||
|
from,
|
||||||
|
api_type,
|
||||||
|
api_target,
|
||||||
|
query
|
||||||
|
) => {
|
||||||
|
if (!config.api_enabled) {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
let msg = {
|
||||||
|
info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.',
|
||||||
|
};
|
||||||
|
return res.end(JSON.stringify(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Teddit API request - subreddit explore');
|
||||||
|
if (from === 'redis') json = JSON.parse(json);
|
||||||
|
|
||||||
|
if (api_type === 'rss') {
|
||||||
|
let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http';
|
||||||
|
let items = '';
|
||||||
|
|
||||||
|
let children_len = json.data.children.length;
|
||||||
|
|
||||||
|
for (var i = 0; i < children_len; i++) {
|
||||||
|
let data = json.data.children[i].data;
|
||||||
|
|
||||||
|
items += `
|
||||||
|
<item>
|
||||||
|
<title>${data.title}</title>
|
||||||
|
<created>${data.created}</created>
|
||||||
|
<pubDate>${new Date(
|
||||||
|
data.created_utc * 1000
|
||||||
|
).toGMTString()}</pubDate>
|
||||||
|
<id>${data.id}</id>
|
||||||
|
<name>${data.display_name}</name>
|
||||||
|
<name_prefixed>${data.display_name_prefixed}</name_prefixed>
|
||||||
|
<url>${replaceDomains(data.url, req.cookies)}</url>
|
||||||
|
<description><![CDATA[${unescape(
|
||||||
|
data.public_description_html
|
||||||
|
)}]]></description>
|
||||||
|
<subscribers>${data.subscribers}</subscribers>
|
||||||
|
<over_18>${data.over18}</over_18>
|
||||||
|
</item>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let title = `${query}`;
|
||||||
|
let link = `${protocol}://${config.domain}/subreddits/search?q=${query}`;
|
||||||
|
|
||||||
|
let xml_output = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
|
||||||
|
<channel>
|
||||||
|
<atom:link href="${link}&api&type=rss" rel="self" type="application/rss+xml" />
|
||||||
|
<title>${title}</title>
|
||||||
|
<link>${link}</link>
|
||||||
|
<description>Results for: ${query}</description>
|
||||||
|
${items}
|
||||||
|
</channel>
|
||||||
|
</rss>`;
|
||||||
|
res.setHeader('Content-Type', 'application/rss+xml');
|
||||||
|
return res.end(xml_output);
|
||||||
|
} else {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
if (api_target === 'reddit') {
|
||||||
|
return res.end(JSON.stringify(json));
|
||||||
|
} else {
|
||||||
|
let processed_json = await processJsonSubredditsExplore(
|
||||||
|
json,
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
req.cookies
|
||||||
|
);
|
||||||
|
|
||||||
|
return res.end(JSON.stringify(processed_json));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -1,74 +1,86 @@
|
||||||
module.exports = function() {
|
const processJsonUser = require('../processJsonUser');
|
||||||
const config = require('../../config')
|
|
||||||
this.handleTedditApiUser = async (json, req, res, from, api_type, api_target, user) => {
|
module.exports = function () {
|
||||||
if(!config.api_enabled) {
|
const config = require('../../config');
|
||||||
res.setHeader('Content-Type', 'application/json')
|
this.handleTedditApiUser = async (
|
||||||
let msg = { info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.' }
|
json,
|
||||||
return res.end(JSON.stringify(msg))
|
req,
|
||||||
|
res,
|
||||||
|
from,
|
||||||
|
api_type,
|
||||||
|
api_target,
|
||||||
|
user
|
||||||
|
) => {
|
||||||
|
if (!config.api_enabled) {
|
||||||
|
res.setHeader('Content-Type', 'application/json');
|
||||||
|
let msg = {
|
||||||
|
info: 'This instance do not support API requests. Please see https://codeberg.org/teddit/teddit#instances for instances that support API, or setup your own instance.',
|
||||||
|
};
|
||||||
|
return res.end(JSON.stringify(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Teddit API request - user')
|
console.log('Teddit API request - user');
|
||||||
let _json = json // Keep the original json
|
let _json = json; // Keep the original json
|
||||||
if(from === 'redis')
|
if (from === 'redis') json = JSON.parse(json);
|
||||||
json = JSON.parse(json)
|
|
||||||
|
let protocol = config.https_enabled || config.api_force_https ? 'https' : 'http';
|
||||||
let protocol = (config.https_enabled ? 'https' : 'http')
|
let link = `${protocol}://${config.domain}/user/${user}`;
|
||||||
let link = `${protocol}://${config.domain}/user/${user}`
|
|
||||||
|
if (api_type === 'rss') {
|
||||||
if(api_type === 'rss') {
|
let items = '';
|
||||||
let items = ''
|
let posts_limit = 25;
|
||||||
let posts_limit = 25
|
|
||||||
|
if (json.overview.data.children.length <= posts_limit) {
|
||||||
if(json.overview.data.children.length <= posts_limit) {
|
posts_limit = json.overview.data.children.length;
|
||||||
posts_limit = json.overview.data.children.length
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var i = 0; i < posts_limit; i++) {
|
for (var i = 0; i < posts_limit; i++) {
|
||||||
let post = json.overview.data.children[i].data
|
let post = json.overview.data.children[i].data;
|
||||||
let post_id = post.permalink.split('/').slice(-2)[0] + '/'
|
let post_id = post.permalink.split('/').slice(-2)[0] + '/';
|
||||||
let url = post.permalink.replace(post_id, '')
|
let url = post.permalink.replace(post_id, '');
|
||||||
let permalink = `${protocol}://${config.domain}${post.permalink}`
|
let permalink = `${protocol}://${config.domain}${post.permalink}`;
|
||||||
let comments_url = `${protocol}://${config.domain}${url}`
|
let comments_url = `${protocol}://${config.domain}${url}`;
|
||||||
let kind = json.overview.data.children[i].kind
|
let kind = json.overview.data.children[i].kind;
|
||||||
|
|
||||||
let t1_elements = ''
|
let t1_elements = '';
|
||||||
let t3_elements = ''
|
let t3_elements = '';
|
||||||
if(kind === 't1') {
|
if (kind === 't1') {
|
||||||
let append_desc_html = `<br/><a href="${permalink}">[link]</a> <a href="${comments_url}">[comments]</a>`
|
let append_desc_html = `<br/><a href="${permalink}">[link]</a> <a href="${comments_url}">[comments]</a>`;
|
||||||
t1_elements = `
|
t1_elements = `
|
||||||
<description><![CDATA[${unescape(post.body_html)}${append_desc_html}]]></description>
|
<description><![CDATA[${unescape(
|
||||||
|
post.body_html
|
||||||
|
)}${append_desc_html}]]></description>
|
||||||
<url>${comments_url}</url>
|
<url>${comments_url}</url>
|
||||||
`
|
`;
|
||||||
}
|
}
|
||||||
if(kind === 't3') {
|
if (kind === 't3') {
|
||||||
let s = await downloadAndSave(post.thumbnail, 'thumb_')
|
let s = await downloadAndSave(post.thumbnail, 'thumb_');
|
||||||
let thumbnail = ''
|
let thumbnail = '';
|
||||||
let enclosure = ''
|
let enclosure = '';
|
||||||
if(s !== 'self' && s != '') {
|
if (s !== 'self' && s != '') {
|
||||||
let img = `${protocol}://${config.domain}${s}`
|
let img = `${protocol}://${config.domain}${s}`;
|
||||||
thumbnail = `<thumbnail>${img}</thumbnail>`
|
thumbnail = `<thumbnail>${img}</thumbnail>`;
|
||||||
|
|
||||||
let mime = ''
|
let mime = '';
|
||||||
let ext = s.split('.').pop()
|
let ext = s.split('.').pop();
|
||||||
if(ext === 'png')
|
if (ext === 'png') mime = 'image/png';
|
||||||
mime = 'image/png'
|
else mime = 'image/jpeg';
|
||||||
else
|
enclosure = `<enclosure length="0" type="${mime}" url="${img}" />`;
|
||||||
mime = 'image/jpeg'
|
|
||||||
enclosure = `<enclosure length="0" type="${mime}" url="${img}" />`
|
|
||||||
}
|
}
|
||||||
let append_desc_html = `submitted by <a href="${protocol}://${config.domain}/u/${user}>/u/${user}</a> to <a href="${protocol}://${config.domain}/r/${post.subreddit}/">r/${post.subreddit}</a>`
|
let append_desc_html = `submitted by <a href="${protocol}://${config.domain}/u/${user}>/u/${user}</a> to <a href="${protocol}://${config.domain}/r/${post.subreddit}/">r/${post.subreddit}</a>`;
|
||||||
append_desc_html += `<br/><a href="${permalink}">[comments]</a>`
|
append_desc_html += `<br/><a href="${permalink}">[comments]</a>`;
|
||||||
t3_elements = `
|
t3_elements = `
|
||||||
<description><![CDATA[${unescape(post.selftext_html)}${append_desc_html}]]></description>
|
<description><![CDATA[${unescape(
|
||||||
|
post.selftext_html
|
||||||
|
)}${append_desc_html}]]></description>
|
||||||
${thumbnail}
|
${thumbnail}
|
||||||
${enclosure}
|
${enclosure}
|
||||||
`
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = post.title
|
let title = post.title;
|
||||||
if(!post.title)
|
if (!post.title) title = post.link_title;
|
||||||
title = post.link_title
|
|
||||||
|
|
||||||
items += `
|
items += `
|
||||||
<item>
|
<item>
|
||||||
<title>${title}</title>
|
<title>${title}</title>
|
||||||
|
@ -76,7 +88,9 @@ module.exports = function() {
|
||||||
<kind>${kind}</kind>
|
<kind>${kind}</kind>
|
||||||
<subreddit>${post.subreddit}</subreddit>
|
<subreddit>${post.subreddit}</subreddit>
|
||||||
<created>${post.created_utc}</created>
|
<created>${post.created_utc}</created>
|
||||||
<pubDate>${new Date(post.created_utc*1000).toGMTString()}</pubDate>
|
<pubDate>${new Date(
|
||||||
|
post.created_utc * 1000
|
||||||
|
).toGMTString()}</pubDate>
|
||||||
<ups>${post.ups}</ups>
|
<ups>${post.ups}</ups>
|
||||||
<link>${permalink}</link>
|
<link>${permalink}</link>
|
||||||
<edited>${post.edited}</edited>
|
<edited>${post.edited}</edited>
|
||||||
|
@ -85,11 +99,10 @@ module.exports = function() {
|
||||||
${t1_elements}
|
${t1_elements}
|
||||||
${t3_elements}
|
${t3_elements}
|
||||||
</item>
|
</item>
|
||||||
`
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
let xml_output =
|
let xml_output = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
`<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
|
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
|
||||||
<channel>
|
<channel>
|
||||||
<atom:link href="${link}/?api&type=rss" rel="self" type="application/rss+xml" />
|
<atom:link href="${link}/?api&type=rss" rel="self" type="application/rss+xml" />
|
||||||
|
@ -97,17 +110,23 @@ module.exports = function() {
|
||||||
<link>${link}</link>
|
<link>${link}</link>
|
||||||
${items}
|
${items}
|
||||||
</channel>
|
</channel>
|
||||||
</rss>`
|
</rss>`;
|
||||||
res.setHeader('Content-Type', 'application/rss+xml')
|
res.setHeader('Content-Type', 'application/rss+xml');
|
||||||
return res.end(xml_output)
|
return res.end(xml_output);
|
||||||
} else {
|
} else {
|
||||||
res.setHeader('Content-Type', 'application/json')
|
res.setHeader('Content-Type', 'application/json');
|
||||||
if(api_target === 'reddit') {
|
if (api_target === 'reddit') {
|
||||||
return res.end(JSON.stringify(json))
|
return res.end(JSON.stringify(json));
|
||||||
} else {
|
} else {
|
||||||
let processed_json = await processJsonUser(json, true, null, null, req.cookies)
|
let processed_json = await processJsonUser(
|
||||||
return res.end(JSON.stringify(processed_json))
|
json,
|
||||||
}
|
true,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
req.cookies
|
||||||
|
);
|
||||||
|
return res.end(JSON.stringify(processed_json));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"url": "https://teddit.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.ggc-project.de"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.zaggy.nl"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.tinfoil-hat.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.domain.glass"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://snoo.ioens.is",
|
||||||
|
"onion": "http://snoo.ioensistjs7wd746zluwixvojbbkxhr37lepdvwtdfeav673o64iflqd.onion"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.httpjames.space"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.xbdm.fun"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "",
|
||||||
|
"onion": "http://ibarajztopxnuhabfu7fg6gbudynxofbnmvis3ltj6lfx47b6fhrd5qd.onion",
|
||||||
|
"i2p": "http://xugoqcf2pftm76vbznx4xuhrzyb5b6zwpizpnw2hysexjdn5l2tq.b32.i2p",
|
||||||
|
"notes": "Operated by mdleom.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://incogsnoo.com",
|
||||||
|
"onion": "http://tedditfyn6idalzso5wam5qd3kdtxoljjhbrbbx34q2xkcisvshuytad.onion",
|
||||||
|
"i2p": "http://teddit.i2p"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.pussthecat.org",
|
||||||
|
"notes": "Operated by PussTheCat.org"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://reddit.lol",
|
||||||
|
"onion": "http://dawtyi5e2cfyfmoht4izmczi42aa2zwh6wi34zwvc6rzf2acpxhrcrad.onion",
|
||||||
|
"i2p": "http://vzeiwzi7ogwl3ijrfek4fbtwhvamxcpyqoc3s4vcgnhlp54s5clq.b32.i2p",
|
||||||
|
"notes": "Operated by https://liberta.casa"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.sethforprivacy.com",
|
||||||
|
"onion": "http://qtpvyiaqhmwccxwzsqubd23xhmmrt75tdyw35kp43w4hvamsgl3x27ad.onion",
|
||||||
|
"notes": "For more similar hosted tools, see blog.sethforprivacy.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.adminforge.de",
|
||||||
|
"notes": "Operated by https://adminforge.de"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.bus-hit.me",
|
||||||
|
"notes": "Operated by https://bus-hit.me"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.froth.zone"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://rdt.trom.tf/",
|
||||||
|
"notes": "Part of the https://trom.tf/ project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.encrypted-data.xyz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://i.opnxng.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.tokhmi.xyz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.garudalinux.org",
|
||||||
|
"notes": "Managed by https://garudalinux.org"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.privacytools.io",
|
||||||
|
"onion": "http://jnuonmf2n36sfdmyksqqqyab3w63cq4kx24olyjleh5z6zzfvyt7uqqd.onion",
|
||||||
|
"notes": "Part of: https://www.privacytools.io"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://td.vern.cc",
|
||||||
|
"onion": "http://td.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion",
|
||||||
|
"i2p": "http://verncco2oaxjikammz4pi7umzp673cme6zuemx7yeeewspwrw3va.b32.i2p",
|
||||||
|
"notes": "Operated by https://vern.cc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.rawbit.ninja",
|
||||||
|
"onion": "http://yqu4yj5lju7bmlwpzpmltb5gsu6cw7nnbcxxx4iqemwa56nxjiggf4qd.onion",
|
||||||
|
"notes": "Operated by https://rawbit.ninja"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.hostux.net",
|
||||||
|
"notes": "Managed by https://hostux.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.no-logs.com/",
|
||||||
|
"notes": "Managed by https://no-logs.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.projectsegfau.lt",
|
||||||
|
"onion": "http://teddit.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion",
|
||||||
|
"notes": "Maintained by Project Segfault Team (https://projectsegfau.lt/team)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://teddit.laserdisc.tokyo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://t.sneed.network",
|
||||||
|
"onion": "http://t.sneed4fmhevap3ci4xhf4wgkf72lwk275lcgomnfgwniwmqvaxyluuid.onion/",
|
||||||
|
"notes": "Operated by sneednet (https://sneed.network)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"onion": "http://teddit.skunky7dhv7nohsoalpwe3sxfz3fbkad7r3wk632riye25vqm3meqead.onion/",
|
||||||
|
"notes": "Self-hosted, works only from 7-11 AM Moscow time to 10-12 PM, in Donetsk"
|
||||||
|
}
|
||||||
|
]
|
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "teddit",
|
"name": "teddit",
|
||||||
"version": "0.4.0",
|
"version": "0.4.9",
|
||||||
"description": "A free and open source alternative Reddit front-end focused on privacy.",
|
"description": "A free and open source alternative Reddit front-end focused on privacy.",
|
||||||
"homepage": "https://teddit.net",
|
"homepage": "https://teddit.net",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
@ -20,19 +20,22 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"start": "node app.js"
|
"start": "node app.js",
|
||||||
|
"dev": "nodemon app.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"cookie-parser": "^1.4.5",
|
"cookie-parser": "^1.4.5",
|
||||||
"express": "^4.17.1",
|
"express": "^4.18.2",
|
||||||
"helmet": "^4.6.0",
|
"helmet": "^4.6.0",
|
||||||
"https-proxy-agent": "^5.0.0",
|
"https-proxy-agent": "^5.0.0",
|
||||||
"minizlib": "^2.1.2",
|
"minizlib": "^2.1.2",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.5",
|
||||||
"postman-request": "^2.88.1-postman.30",
|
"postman-request": "^2.88.1-postman.30",
|
||||||
"pug": "^3.0.2",
|
"pug": "^3.0.2",
|
||||||
"redis": "^3.1.2"
|
"redis": "^3.1.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {}
|
"devDependencies": {
|
||||||
|
"nodemon": "^3.0.1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,18 +2,25 @@ const config = require('../config');
|
||||||
const { redis, fetch } = require('../app');
|
const { redis, fetch } = require('../app');
|
||||||
const homeRoute = require('express').Router();
|
const homeRoute = require('express').Router();
|
||||||
|
|
||||||
const processUser = require('../inc/processJsonUser.js')();
|
const processJsonSubreddit = require('../inc/processJsonSubreddit.js');
|
||||||
const processPost = require('../inc/processJsonPost.js')();
|
|
||||||
const processAbout = require('../inc/processSubredditAbout.js')();
|
|
||||||
const tedditApiUser = require('../inc/teddit_api/handleUser.js')();
|
|
||||||
const processSearches = require('../inc/processSearchResults.js')();
|
|
||||||
const processSubreddit = require('../inc/processJsonSubreddit.js')();
|
|
||||||
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
||||||
const processMoreComments = require('../inc/processMoreComments.js')();
|
const processMoreComments = require('../inc/processMoreComments.js')();
|
||||||
const processSubredditsExplore =
|
|
||||||
require('../inc/processSubredditsExplore.js')();
|
|
||||||
|
|
||||||
homeRoute.get('/:sort?', async (req, res, next) => {
|
homeRoute.get('/', (req, res, next) => {
|
||||||
|
if (
|
||||||
|
(config.clean_homepage && req.cookies.prefer_frontpage !== 'true') ||
|
||||||
|
(!config.clean_homepage && req.cookies.prefer_frontpage == 'undefined')
|
||||||
|
) {
|
||||||
|
return res.render('homepage', {
|
||||||
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
homeRoute.get([`/:sort?`, '/frontpage'], async (req, res, next) => {
|
||||||
let past = req.query.t;
|
let past = req.query.t;
|
||||||
let before = req.query.before;
|
let before = req.query.before;
|
||||||
let after = req.query.after;
|
let after = req.query.after;
|
||||||
|
@ -25,26 +32,61 @@ homeRoute.get('/:sort?', async (req, res, next) => {
|
||||||
let proxyable =
|
let proxyable =
|
||||||
sortby.includes('.jpg') ||
|
sortby.includes('.jpg') ||
|
||||||
sortby.includes('.png') ||
|
sortby.includes('.png') ||
|
||||||
sortby.includes('.jpeg')
|
sortby.includes('.jpeg') ||
|
||||||
|
sortby.includes('.mp4') ||
|
||||||
|
sortby.includes('.gif') ||
|
||||||
|
sortby.includes('.gifv')
|
||||||
? true
|
? true
|
||||||
: false;
|
: false;
|
||||||
if (proxyable) {
|
if (proxyable) {
|
||||||
let params = new URLSearchParams(req.query).toString();
|
let media_url = '';
|
||||||
let image_url = `https://preview.redd.it/${sortby}?${params}`;
|
const replacable_media_domains = ['i.redd.it', 'v.redd.it', 'external-preview.redd.it', 'preview.redd.it']
|
||||||
let proxied_image = await downloadAndSave(image_url);
|
if (req.query.teddit_proxy) {
|
||||||
if (proxied_image) {
|
if (replacable_media_domains.includes(req.query.teddit_proxy)) {
|
||||||
return res.redirect(proxied_image);
|
let full_url = req.protocol + '://' + req.get('host') + req.originalUrl;
|
||||||
|
let u = new URL(full_url);
|
||||||
|
let filename = u.pathname || '';
|
||||||
|
let query = u.search || '';
|
||||||
|
if (query != '') {
|
||||||
|
let params = new URLSearchParams(query);
|
||||||
|
params.delete('teddit_proxy');
|
||||||
|
query = '?' + params.toString();
|
||||||
|
}
|
||||||
|
media_url = `https://${req.query.teddit_proxy}${filename}${query}`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let params = new URLSearchParams(req.query).toString();
|
||||||
|
media_url = `https://preview.redd.it/${sortby}?${params}`;
|
||||||
|
if (media_url.includes('teddit_proxy')) {
|
||||||
|
// if the URL includes teddit_proxy query param, remove everything after it
|
||||||
|
media_url = media_url.split('%3Fteddit_proxy')[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let proxied_media = await downloadAndSave(media_url);
|
||||||
|
if (proxied_media) {
|
||||||
|
return res.redirect(proxied_media);
|
||||||
} else {
|
} else {
|
||||||
return res.redirect('/');
|
return res.redirect('/');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let is_comment =
|
||||||
|
(sortby.length == 6 || sortby.length == 7) &&
|
||||||
|
sortby != "rising"
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
|
||||||
|
if (is_comment) {
|
||||||
|
return res.redirect('/comments/' + sortby);
|
||||||
|
}
|
||||||
|
|
||||||
let d = `&after=${after}`;
|
let d = `&after=${after}`;
|
||||||
if (before) {
|
if (before) {
|
||||||
d = `&before=${before}`;
|
d = `&before=${before}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sortby == '') {
|
if (sortby == '' || sortby == 'frontpage') {
|
||||||
sortby = 'hot';
|
sortby = 'hot';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,9 +141,10 @@ homeRoute.get('/:sort?', async (req, res, next) => {
|
||||||
redis.get(key, (error, json) => {
|
redis.get(key, (error, json) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error('Error getting the frontpage key from redis.', error);
|
console.error('Error getting the frontpage key from redis.', error);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
|
@ -115,7 +158,8 @@ homeRoute.get('/:sort?', async (req, res, next) => {
|
||||||
'redis',
|
'redis',
|
||||||
api_type,
|
api_type,
|
||||||
api_target,
|
api_target,
|
||||||
'/'
|
'/',
|
||||||
|
'full'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let processed_json = await processJsonSubreddit(
|
let processed_json = await processJsonSubreddit(
|
||||||
|
@ -124,12 +168,13 @@ homeRoute.get('/:sort?', async (req, res, next) => {
|
||||||
null,
|
null,
|
||||||
req.cookies
|
req.cookies
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: processed_json,
|
json: processed_json,
|
||||||
sortby: sortby,
|
sortby: sortby,
|
||||||
past: past,
|
past: past,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
redis_key: key,
|
redis_key: key,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -160,9 +205,10 @@ homeRoute.get('/:sort?', async (req, res, next) => {
|
||||||
'Error setting the frontpage key to redis.',
|
'Error setting the frontpage key to redis.',
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log('Fetched the frontpage from Reddit.');
|
console.log('Fetched the frontpage from Reddit.');
|
||||||
|
@ -175,7 +221,8 @@ homeRoute.get('/:sort?', async (req, res, next) => {
|
||||||
'from_online',
|
'from_online',
|
||||||
api_type,
|
api_type,
|
||||||
api_target,
|
api_target,
|
||||||
'/'
|
'/',
|
||||||
|
'full'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let processed_json = await processJsonSubreddit(
|
let processed_json = await processJsonSubreddit(
|
||||||
|
@ -184,12 +231,13 @@ homeRoute.get('/:sort?', async (req, res, next) => {
|
||||||
null,
|
null,
|
||||||
req.cookies
|
req.cookies
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: processed_json,
|
json: processed_json,
|
||||||
sortby: sortby,
|
sortby: sortby,
|
||||||
past: past,
|
past: past,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
redis_key: key,
|
redis_key: key,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -202,10 +250,11 @@ homeRoute.get('/:sort?', async (req, res, next) => {
|
||||||
`Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}`
|
`Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}`
|
||||||
);
|
);
|
||||||
console.error(config.reddit_api_error_text);
|
console.error(config.reddit_api_error_text);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -68,6 +68,10 @@ overridingRoutes.all('*', (req, res, next) => {
|
||||||
maxAge: 31536000,
|
maxAge: 31536000,
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
});
|
});
|
||||||
|
} else if (!req.cookies.show_upvoted_percentage) {
|
||||||
|
if (config.show_upvoted_percentage) {
|
||||||
|
req.cookies.show_upvoted_percentage = 'true';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let domainTwitter = req.query.domain_twitter;
|
let domainTwitter = req.query.domain_twitter;
|
||||||
|
@ -97,6 +101,24 @@ overridingRoutes.all('*', (req, res, next) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let domainQuora = req.query.domain_quora;
|
||||||
|
if (domainQuora) {
|
||||||
|
req.cookies.domain_quora = domainQuora;
|
||||||
|
res.cookie('domain_quora', domainQuora, {
|
||||||
|
maxAge: 31536000,
|
||||||
|
httpOnly: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let domainImgur = req.query.domain_imgur;
|
||||||
|
if (domainImgur) {
|
||||||
|
req.cookies.domain_imgur = domainImgur;
|
||||||
|
res.cookie('domain_imgur', domainImgur, {
|
||||||
|
maxAge: 31536000,
|
||||||
|
httpOnly: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let videosMuted = req.query.videos_muted;
|
let videosMuted = req.query.videos_muted;
|
||||||
if (videosMuted) {
|
if (videosMuted) {
|
||||||
req.cookies.videos_muted = videosMuted;
|
req.cookies.videos_muted = videosMuted;
|
||||||
|
|
|
@ -10,17 +10,24 @@ function resetPreferences(res) {
|
||||||
res.clearCookie('post_media_max_height');
|
res.clearCookie('post_media_max_height');
|
||||||
res.clearCookie('collapse_child_comments');
|
res.clearCookie('collapse_child_comments');
|
||||||
res.clearCookie('show_upvoted_percentage');
|
res.clearCookie('show_upvoted_percentage');
|
||||||
|
res.clearCookie('show_upvotes')
|
||||||
res.clearCookie('subbed_subreddits');
|
res.clearCookie('subbed_subreddits');
|
||||||
res.clearCookie('domain_twitter');
|
res.clearCookie('domain_twitter');
|
||||||
res.clearCookie('domain_youtube');
|
res.clearCookie('domain_youtube');
|
||||||
res.clearCookie('domain_instagram');
|
res.clearCookie('domain_instagram');
|
||||||
|
res.clearCookie('domain_quora');
|
||||||
|
res.clearCookie('domain_imgur');
|
||||||
res.clearCookie('videos_muted');
|
res.clearCookie('videos_muted');
|
||||||
|
res.clearCookie('prefer_frontpage');
|
||||||
|
res.clearCookie('show_large_gallery_images');
|
||||||
|
res.clearCookie('default_comment_sort');
|
||||||
}
|
}
|
||||||
|
|
||||||
preferenceRoutes.get('/preferences', (req, res, next) => {
|
preferenceRoutes.get('/preferences', (req, res, next) => {
|
||||||
return res.render('preferences', {
|
return res.render('preferences', {
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
instance_config: config,
|
instance_config: config,
|
||||||
|
comment_sort_values: ['best', 'top', 'new', 'controversial', 'old', 'qa'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -41,9 +48,10 @@ preferenceRoutes.get('/import_prefs/:key', (req, res, next) => {
|
||||||
`Error getting the preferences import key ${key} from redis.`,
|
`Error getting the preferences import key ${key} from redis.`,
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
|
@ -82,10 +90,16 @@ preferenceRoutes.post('/saveprefs', (req, res, next) => {
|
||||||
let post_media_max_height = req.body.post_media_max_height;
|
let post_media_max_height = req.body.post_media_max_height;
|
||||||
let collapse_child_comments = req.body.collapse_child_comments;
|
let collapse_child_comments = req.body.collapse_child_comments;
|
||||||
let show_upvoted_percentage = req.body.show_upvoted_percentage;
|
let show_upvoted_percentage = req.body.show_upvoted_percentage;
|
||||||
|
let show_upvotes = req.body.show_upvotes;
|
||||||
let domain_twitter = req.body.domain_twitter;
|
let domain_twitter = req.body.domain_twitter;
|
||||||
let domain_youtube = req.body.domain_youtube;
|
let domain_youtube = req.body.domain_youtube;
|
||||||
let domain_instagram = req.body.domain_instagram;
|
let domain_instagram = req.body.domain_instagram;
|
||||||
|
let domain_quora = req.body.domain_quora;
|
||||||
|
let domain_imgur = req.body.domain_imgur;
|
||||||
let videos_muted = req.body.videos_muted;
|
let videos_muted = req.body.videos_muted;
|
||||||
|
let prefer_frontpage = req.body.prefer_frontpage;
|
||||||
|
let show_large_gallery_images = req.body.show_large_gallery_images;
|
||||||
|
let default_comment_sort = req.body.default_comment_sort;
|
||||||
|
|
||||||
res.cookie('theme', theme, {
|
res.cookie('theme', theme, {
|
||||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||||
|
@ -136,6 +150,13 @@ preferenceRoutes.post('/saveprefs', (req, res, next) => {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (show_upvotes === 'on') show_upvotes = 'true';
|
||||||
|
else show_upvotes = 'false';
|
||||||
|
res.cookie('show_upvotes', show_upvotes, {
|
||||||
|
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||||
|
httpOnly: true,
|
||||||
|
});
|
||||||
|
|
||||||
if (videos_muted === 'on') videos_muted = 'true';
|
if (videos_muted === 'on') videos_muted = 'true';
|
||||||
else videos_muted = 'false';
|
else videos_muted = 'false';
|
||||||
res.cookie('videos_muted', videos_muted, {
|
res.cookie('videos_muted', videos_muted, {
|
||||||
|
@ -155,6 +176,33 @@ preferenceRoutes.post('/saveprefs', (req, res, next) => {
|
||||||
maxAge: 365 * 24 * 60 * 60 * 1000,
|
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
});
|
});
|
||||||
|
res.cookie('domain_quora', domain_quora, {
|
||||||
|
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||||
|
httpOnly: true,
|
||||||
|
});
|
||||||
|
res.cookie('domain_imgur', domain_imgur, {
|
||||||
|
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||||
|
httpOnly: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (prefer_frontpage === 'on') prefer_frontpage = 'true';
|
||||||
|
else prefer_frontpage = 'false';
|
||||||
|
res.cookie('prefer_frontpage', prefer_frontpage, {
|
||||||
|
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||||
|
httpOnly: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (show_large_gallery_images === 'on') show_large_gallery_images = 'true';
|
||||||
|
else show_large_gallery_images = 'false';
|
||||||
|
res.cookie('show_large_gallery_images', show_large_gallery_images, {
|
||||||
|
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||||
|
httpOnly: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
res.cookie('default_comment_sort', default_comment_sort, {
|
||||||
|
maxAge: 365 * 24 * 60 * 60 * 1000,
|
||||||
|
httpOnly: true,
|
||||||
|
});
|
||||||
|
|
||||||
return res.redirect('/preferences');
|
return res.redirect('/preferences');
|
||||||
});
|
});
|
||||||
|
@ -173,7 +221,7 @@ preferenceRoutes.post('/export_prefs', (req, res, next) => {
|
||||||
'Content-disposition',
|
'Content-disposition',
|
||||||
'attachment; filename=teddit_prefs.json'
|
'attachment; filename=teddit_prefs.json'
|
||||||
);
|
);
|
||||||
res.setHeader('Content-type', 'preferenceRouteslication/json');
|
res.setHeader('Content-type', 'application/json');
|
||||||
return res.send(export_data);
|
return res.send(export_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +252,7 @@ preferenceRoutes.post('/import_prefs', (req, res, next) => {
|
||||||
body = body.toString();
|
body = body.toString();
|
||||||
try {
|
try {
|
||||||
let json = body
|
let json = body
|
||||||
.split('Content-Type: preferenceRouteslication/json')[1]
|
.split('Content-Type: application/json')[1]
|
||||||
.trim()
|
.trim()
|
||||||
.split('--')[0];
|
.split('--')[0];
|
||||||
let prefs = JSON.parse(json);
|
let prefs = JSON.parse(json);
|
||||||
|
|
|
@ -2,16 +2,9 @@ const config = require('../config');
|
||||||
const { redis, fetch } = require('../app');
|
const { redis, fetch } = require('../app');
|
||||||
const saveRoutes = require('express').Router();
|
const saveRoutes = require('express').Router();
|
||||||
|
|
||||||
const processUser = require('../inc/processJsonUser.js')();
|
const processJsonSubreddit = require('../inc/processJsonSubreddit.js');
|
||||||
const processPost = require('../inc/processJsonPost.js')();
|
|
||||||
const processAbout = require('../inc/processSubredditAbout.js')();
|
|
||||||
const tedditApiUser = require('../inc/teddit_api/handleUser.js')();
|
|
||||||
const processSearches = require('../inc/processSearchResults.js')();
|
|
||||||
const processSubreddit = require('../inc/processJsonSubreddit.js')();
|
|
||||||
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
||||||
const processMoreComments = require('../inc/processMoreComments.js')();
|
const processMoreComments = require('../inc/processMoreComments.js')();
|
||||||
const processSubredditsExplore =
|
|
||||||
require('../inc/processSubredditsExplore.js')();
|
|
||||||
|
|
||||||
saveRoutes.get('/saved', (req, res, next) => {
|
saveRoutes.get('/saved', (req, res, next) => {
|
||||||
let saved = req.cookies.saved;
|
let saved = req.cookies.saved;
|
||||||
|
@ -20,6 +13,7 @@ saveRoutes.get('/saved', (req, res, next) => {
|
||||||
return res.render('saved', {
|
return res.render('saved', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +39,7 @@ saveRoutes.get('/saved', (req, res, next) => {
|
||||||
return res.render('saved', {
|
return res.render('saved', {
|
||||||
json: processed_json,
|
json: processed_json,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return res.render('subreddit', {
|
return res.render('subreddit', {
|
||||||
|
@ -52,6 +47,7 @@ saveRoutes.get('/saved', (req, res, next) => {
|
||||||
error: true,
|
error: true,
|
||||||
data: processed_json,
|
data: processed_json,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -221,9 +217,10 @@ saveRoutes.get(
|
||||||
'Error getting the short URL for post key from redis.',
|
'Error getting the short URL for post key from redis.',
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
|
@ -264,9 +261,10 @@ saveRoutes.get(
|
||||||
'Error setting the short URL for post key to redis.',
|
'Error setting the short URL for post key to redis.',
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -294,10 +292,11 @@ saveRoutes.get(
|
||||||
`Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}`
|
`Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}`
|
||||||
);
|
);
|
||||||
console.error(config.reddit_api_error_text);
|
console.error(config.reddit_api_error_text);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
const config = require('../config');
|
||||||
const searchRoute = require('express').Router();
|
const searchRoute = require('express').Router();
|
||||||
|
|
||||||
searchRoute.get('/search', (req, res, next) => {
|
searchRoute.get('/search', (req, res, next) => {
|
||||||
|
@ -14,6 +15,7 @@ searchRoute.get('/search', (req, res, next) => {
|
||||||
sortby: undefined,
|
sortby: undefined,
|
||||||
past: undefined,
|
past: undefined,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
|
const config = require('../config');
|
||||||
|
|
||||||
const staticRoutes = require('express').Router();
|
const staticRoutes = require('express').Router();
|
||||||
|
|
||||||
staticRoutes.get('/privacy', (req, res, next) => {
|
staticRoutes.get('/privacy', (req, res, next) => {
|
||||||
return res.render('privacypolicy', { user_preferences: req.cookies });
|
return res.render('privacypolicy', { user_preferences: req.cookies, instance_config: config });
|
||||||
});
|
});
|
||||||
|
|
||||||
staticRoutes.get('/about', (req, res, next) => {
|
staticRoutes.get('/about', (req, res, next) => {
|
||||||
return res.render('about', { user_preferences: req.cookies });
|
return res.render('about', { user_preferences: req.cookies, instance_config: config });
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = staticRoutes;
|
module.exports = staticRoutes;
|
||||||
|
|
|
@ -2,20 +2,32 @@ const config = require('../config');
|
||||||
const { redis, fetch, RedditAPI } = require('../app');
|
const { redis, fetch, RedditAPI } = require('../app');
|
||||||
const subredditRoutes = require('express').Router();
|
const subredditRoutes = require('express').Router();
|
||||||
|
|
||||||
const processUser = require('../inc/processJsonUser.js')();
|
const {
|
||||||
const processPost = require('../inc/processJsonPost.js')();
|
processJsonPost,
|
||||||
const processAbout = require('../inc/processSubredditAbout.js')();
|
finalizeJsonPost,
|
||||||
const tedditApiUser = require('../inc/teddit_api/handleUser.js')();
|
} = require('../inc/processJsonPost.js');
|
||||||
const processSearches = require('../inc/processSearchResults.js')();
|
const {
|
||||||
const processSubreddit = require('../inc/processJsonSubreddit.js')();
|
processSubredditAbout
|
||||||
|
} = require('../inc/processSubredditAbout.js');
|
||||||
|
const processSearchResults = require('../inc/processSearchResults.js');
|
||||||
|
const processJsonSubreddit = require('../inc/processJsonSubreddit.js');
|
||||||
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
||||||
const processMoreComments = require('../inc/processMoreComments.js')();
|
const tedditApiPost = require('../inc/teddit_api/handlePost.js')();
|
||||||
const processSubredditsExplore =
|
const processMoreComments = require('../inc/processMoreComments.js');
|
||||||
require('../inc/processSubredditsExplore.js')();
|
const processJsonSubredditsExplore = require('../inc/processSubredditsExplore.js');
|
||||||
|
|
||||||
subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
|
subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
|
||||||
let subreddit = req.params.subreddit;
|
let subreddit = req.params.subreddit;
|
||||||
let q = req.query.q;
|
let q = req.query.q;
|
||||||
|
let api_req = req.query.api;
|
||||||
|
let api_type = req.query.type;
|
||||||
|
let api_target = req.query.target;
|
||||||
|
let api_mode = req.query.mode;
|
||||||
|
|
||||||
|
if (req.query.hasOwnProperty('api')) api_req = true;
|
||||||
|
else api_req = false;
|
||||||
|
|
||||||
|
let raw_json = api_req && req.query.raw_json == '1' ? 1 : 0;
|
||||||
|
|
||||||
if (typeof q === 'undefined') {
|
if (typeof q === 'undefined') {
|
||||||
return res.render('search', {
|
return res.render('search', {
|
||||||
|
@ -28,6 +40,7 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
|
||||||
sortby: undefined,
|
sortby: undefined,
|
||||||
past: undefined,
|
past: undefined,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,44 +68,65 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
|
||||||
if (nsfw !== 'on') {
|
if (nsfw !== 'on') {
|
||||||
nsfw = 'off';
|
nsfw = 'off';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let count = '&count=25';
|
||||||
|
if (after == '') {
|
||||||
|
count = '';
|
||||||
|
}
|
||||||
|
|
||||||
let key = `search:${subreddit}:${q}:${restrict_sr}:${sortby}:${past}:${after}:${before}:${nsfw}`;
|
let key = `search:${subreddit}:${q}:${restrict_sr}:${sortby}:${past}:${after}:${before}:${nsfw}:raw_json:${raw_json}`;
|
||||||
redis.get(key, (error, json) => {
|
redis.get(key, (error, json) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error('Error getting the search key from redis.', error);
|
console.error('Error getting the search key from redis.', error);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
console.log('Got search key from redis.');
|
console.log('Got search key from redis.');
|
||||||
(async () => {
|
(async () => {
|
||||||
let processed_json = await processSearchResults(
|
if (api_req) {
|
||||||
json,
|
return handleTedditApiSubredditSearch(
|
||||||
false,
|
json,
|
||||||
after,
|
req,
|
||||||
before,
|
res,
|
||||||
req.cookies
|
'redis',
|
||||||
);
|
api_type,
|
||||||
return res.render('search', {
|
api_target,
|
||||||
json: processed_json,
|
subreddit,
|
||||||
no_query: false,
|
q,
|
||||||
q: q,
|
api_mode
|
||||||
restrict_sr: restrict_sr,
|
);
|
||||||
nsfw: nsfw,
|
} else {
|
||||||
subreddit: subreddit,
|
let processed_json = await processSearchResults(
|
||||||
sortby: sortby,
|
json,
|
||||||
past: past,
|
false,
|
||||||
user_preferences: req.cookies,
|
after,
|
||||||
});
|
before,
|
||||||
|
req.cookies
|
||||||
|
);
|
||||||
|
return res.render('search', {
|
||||||
|
json: processed_json,
|
||||||
|
no_query: false,
|
||||||
|
q: q,
|
||||||
|
restrict_sr: restrict_sr,
|
||||||
|
nsfw: nsfw,
|
||||||
|
subreddit: subreddit,
|
||||||
|
sortby: sortby,
|
||||||
|
past: past,
|
||||||
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
|
});
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
} else {
|
} else {
|
||||||
let url = '';
|
let url = '';
|
||||||
if (config.use_reddit_oauth)
|
if (config.use_reddit_oauth)
|
||||||
url = `https://oauth.reddit.com/r/${subreddit}/search?api_type=json&q=${q}&restrict_sr=${restrict_sr}&include_over_18=${nsfw}&sort=${sortby}&t=${past}${d}`;
|
url = `https://oauth.reddit.com/r/${subreddit}/search?api_type=json&q=${q}&restrict_sr=${restrict_sr}&include_over_18=${nsfw}&sort=${sortby}&t=${past}${count}${d}&raw_json=${raw_json}`;
|
||||||
else
|
else
|
||||||
url = `https://reddit.com/r/${subreddit}/search.json?api_type=json&q=${q}&restrict_sr=${restrict_sr}&include_over_18=${nsfw}&sort=${sortby}&t=${past}${d}`;
|
url = `https://reddit.com/r/${subreddit}/search.json?api_type=json&q=${q}&restrict_sr=${restrict_sr}&include_over_18=${nsfw}&sort=${sortby}&t=${past}${count}${d}&raw_json=${raw_json}`;
|
||||||
fetch(encodeURI(url), redditApiGETHeaders())
|
fetch(encodeURI(url), redditApiGETHeaders())
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result.status === 200) {
|
if (result.status === 200) {
|
||||||
|
@ -121,31 +155,47 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
|
||||||
'Error setting the searches key to redis.',
|
'Error setting the searches key to redis.',
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log('Fetched search results from Reddit.');
|
console.log('Fetched search results from Reddit.');
|
||||||
(async () => {
|
(async () => {
|
||||||
let processed_json = await processSearchResults(
|
if (api_req) {
|
||||||
json,
|
return handleTedditApiSubredditSearch(
|
||||||
true,
|
json,
|
||||||
after,
|
req,
|
||||||
before,
|
res,
|
||||||
req.cookies
|
'from_online',
|
||||||
);
|
api_type,
|
||||||
return res.render('search', {
|
api_target,
|
||||||
no_query: false,
|
subreddit,
|
||||||
json: processed_json,
|
q,
|
||||||
q: q,
|
api_mode
|
||||||
restrict_sr: restrict_sr,
|
);
|
||||||
nsfw: nsfw,
|
} else {
|
||||||
subreddit: subreddit,
|
let processed_json = await processSearchResults(
|
||||||
sortby: sortby,
|
json,
|
||||||
past: past,
|
true,
|
||||||
user_preferences: req.cookies,
|
after,
|
||||||
});
|
before,
|
||||||
|
req.cookies
|
||||||
|
);
|
||||||
|
return res.render('search', {
|
||||||
|
no_query: false,
|
||||||
|
json: processed_json,
|
||||||
|
q: q,
|
||||||
|
restrict_sr: restrict_sr,
|
||||||
|
nsfw: nsfw,
|
||||||
|
subreddit: subreddit,
|
||||||
|
sortby: sortby,
|
||||||
|
past: past,
|
||||||
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
|
});
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,10 +207,11 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
|
||||||
`Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}`
|
`Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}`
|
||||||
);
|
);
|
||||||
console.error(config.reddit_api_error_text);
|
console.error(config.reddit_api_error_text);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -171,6 +222,107 @@ subredditRoutes.get('/r/:subreddit/search', (req, res, next) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
subredditRoutes.get('/r/:subreddit/about', (req, res, next) => {
|
||||||
|
let subreddit = req.params.subreddit;
|
||||||
|
let api_type = req.query.type;
|
||||||
|
let api_target = req.query.target;
|
||||||
|
let api_mode = req.query.mode;
|
||||||
|
|
||||||
|
if (!req.query.hasOwnProperty('api')) {
|
||||||
|
console.log(`This route is only available via the API.`, req.originalUrl);
|
||||||
|
return res.redirect(`/r/${subreddit}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let raw_json = req.query.raw_json == '1' ? 1 : 0;
|
||||||
|
|
||||||
|
let key = `about:${subreddit.toLowerCase()}:raw_json:${raw_json}`;
|
||||||
|
redis.get(key, (error, json) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(`Error getting the about key from redis.`, error);
|
||||||
|
return res.render('frontpage', {
|
||||||
|
json: null,
|
||||||
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (json) {
|
||||||
|
console.log(`Got about key from redis.`);
|
||||||
|
(async () => {
|
||||||
|
return handleTedditApiSubredditAbout(
|
||||||
|
json,
|
||||||
|
res,
|
||||||
|
'redis',
|
||||||
|
api_target
|
||||||
|
);
|
||||||
|
})();
|
||||||
|
} else {
|
||||||
|
let url = '';
|
||||||
|
if (config.use_reddit_oauth)
|
||||||
|
url = `https://oauth.reddit.com/r/${subreddit}/about.json?api_type=json&raw_json=${raw_json}`;
|
||||||
|
else
|
||||||
|
url = `https://reddit.com/r/${subreddit}/about.json?api_type=json&raw_json=${raw_json}`;
|
||||||
|
fetch(encodeURI(url), redditApiGETHeaders())
|
||||||
|
.then((result) => {
|
||||||
|
if (result.status === 200) {
|
||||||
|
result.json().then((json) => {
|
||||||
|
redis.setex(
|
||||||
|
key,
|
||||||
|
config.setexs.subreddit,
|
||||||
|
JSON.stringify(json),
|
||||||
|
(error) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(
|
||||||
|
`Error setting the about key to redis.`,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
return res.render('subreddit', {
|
||||||
|
json: null,
|
||||||
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
`Fetched the JSON from reddit.com/r/${subreddit}/about.`
|
||||||
|
);
|
||||||
|
(async () => {
|
||||||
|
return handleTedditApiSubredditAbout(
|
||||||
|
json,
|
||||||
|
res,
|
||||||
|
'from_online',
|
||||||
|
api_target
|
||||||
|
);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (result.status === 404) {
|
||||||
|
console.log('404 – Subreddit not found');
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
`Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}`
|
||||||
|
);
|
||||||
|
console.error(config.reddit_api_error_text);
|
||||||
|
}
|
||||||
|
return res.render('frontpage', {
|
||||||
|
json: null,
|
||||||
|
http_status_code: result.status,
|
||||||
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(
|
||||||
|
`Error fetching the JSON file from reddit.com/r/${subreddit}/about.`,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
subredditRoutes.get(
|
subredditRoutes.get(
|
||||||
'/r/:subreddit/wiki/:page?/:sub_page?',
|
'/r/:subreddit/wiki/:page?/:sub_page?',
|
||||||
(req, res, next) => {
|
(req, res, next) => {
|
||||||
|
@ -201,9 +353,10 @@ subredditRoutes.get(
|
||||||
`Error getting the ${subreddit} wiki key from redis.`,
|
`Error getting the ${subreddit} wiki key from redis.`,
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
|
@ -216,6 +369,7 @@ subredditRoutes.get(
|
||||||
: formatWikipagelisting(json, subreddit),
|
: formatWikipagelisting(json, subreddit),
|
||||||
subreddit: subreddit,
|
subreddit: subreddit,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let url = '';
|
let url = '';
|
||||||
|
@ -240,6 +394,7 @@ subredditRoutes.get(
|
||||||
return res.render('subreddit', {
|
return res.render('subreddit', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -252,6 +407,7 @@ subredditRoutes.get(
|
||||||
: formatWikipagelisting(json, subreddit),
|
: formatWikipagelisting(json, subreddit),
|
||||||
subreddit: subreddit,
|
subreddit: subreddit,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,10 +422,11 @@ subredditRoutes.get(
|
||||||
);
|
);
|
||||||
console.error(config.reddit_api_error_text);
|
console.error(config.reddit_api_error_text);
|
||||||
}
|
}
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -323,6 +480,7 @@ subredditRoutes.get('/r/random', (req, res, next) => {
|
||||||
return res.render('subreddit', {
|
return res.render('subreddit', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -334,9 +492,10 @@ subredditRoutes.get('/r/random', (req, res, next) => {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
console.error(`Fetching random subreddit failed.`, json);
|
console.error(`Fetching random subreddit failed.`, json);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -349,10 +508,11 @@ subredditRoutes.get('/r/random', (req, res, next) => {
|
||||||
);
|
);
|
||||||
console.error(config.reddit_api_error_text);
|
console.error(config.reddit_api_error_text);
|
||||||
}
|
}
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -373,6 +533,7 @@ subredditRoutes.get('/r/:subreddit/:sort?', (req, res, next) => {
|
||||||
let api_req = req.query.api;
|
let api_req = req.query.api;
|
||||||
let api_type = req.query.type;
|
let api_type = req.query.type;
|
||||||
let api_target = req.query.target;
|
let api_target = req.query.target;
|
||||||
|
let api_mode = req.query.mode;
|
||||||
|
|
||||||
if (req.query.hasOwnProperty('api')) api_req = true;
|
if (req.query.hasOwnProperty('api')) api_req = true;
|
||||||
else api_req = false;
|
else api_req = false;
|
||||||
|
@ -414,9 +575,10 @@ subredditRoutes.get('/r/:subreddit/:sort?', (req, res, next) => {
|
||||||
redis.get(key, (error, json) => {
|
redis.get(key, (error, json) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error(`Error getting the ${subreddit} key from redis.`, error);
|
console.error(`Error getting the ${subreddit} key from redis.`, error);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
|
@ -430,7 +592,8 @@ subredditRoutes.get('/r/:subreddit/:sort?', (req, res, next) => {
|
||||||
'redis',
|
'redis',
|
||||||
api_type,
|
api_type,
|
||||||
api_target,
|
api_target,
|
||||||
subreddit
|
subreddit,
|
||||||
|
api_mode
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let processed_json = await processJsonSubreddit(
|
let processed_json = await processJsonSubreddit(
|
||||||
|
@ -458,6 +621,7 @@ subredditRoutes.get('/r/:subreddit/:sort?', (req, res, next) => {
|
||||||
redis_key: key,
|
redis_key: key,
|
||||||
after: req.query.after,
|
after: req.query.after,
|
||||||
before: req.query.before,
|
before: req.query.before,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return res.render('subreddit', {
|
return res.render('subreddit', {
|
||||||
|
@ -465,6 +629,7 @@ subredditRoutes.get('/r/:subreddit/:sort?', (req, res, next) => {
|
||||||
error: true,
|
error: true,
|
||||||
data: processed_json,
|
data: processed_json,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,6 +657,7 @@ subredditRoutes.get('/r/:subreddit/:sort?', (req, res, next) => {
|
||||||
return res.render('subreddit', {
|
return res.render('subreddit', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -506,7 +672,8 @@ subredditRoutes.get('/r/:subreddit/:sort?', (req, res, next) => {
|
||||||
'from_online',
|
'from_online',
|
||||||
api_type,
|
api_type,
|
||||||
api_target,
|
api_target,
|
||||||
subreddit
|
subreddit,
|
||||||
|
api_mode
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let processed_json = await processJsonSubreddit(
|
let processed_json = await processJsonSubreddit(
|
||||||
|
@ -533,6 +700,7 @@ subredditRoutes.get('/r/:subreddit/:sort?', (req, res, next) => {
|
||||||
redis_key: key,
|
redis_key: key,
|
||||||
after: req.query.after,
|
after: req.query.after,
|
||||||
before: req.query.before,
|
before: req.query.before,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -549,10 +717,11 @@ subredditRoutes.get('/r/:subreddit/:sort?', (req, res, next) => {
|
||||||
);
|
);
|
||||||
console.error(config.reddit_api_error_text);
|
console.error(config.reddit_api_error_text);
|
||||||
}
|
}
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -572,17 +741,30 @@ subredditRoutes.get(
|
||||||
let subreddit = req.params.subreddit;
|
let subreddit = req.params.subreddit;
|
||||||
let id = req.params.id;
|
let id = req.params.id;
|
||||||
let snippet = encodeURIComponent(req.params.snippet);
|
let snippet = encodeURIComponent(req.params.snippet);
|
||||||
let sortby = req.query.sort;
|
let sortby = req.query.sort || req.cookies.default_comment_sort;
|
||||||
let comment_id = '';
|
let comment_id = '';
|
||||||
let viewing_comment = false;
|
let viewing_comment = false;
|
||||||
let comment_ids = req.query.comment_ids;
|
let comment_ids = req.query.comment_ids;
|
||||||
let context = parseInt(req.query.context);
|
let context = parseInt(req.query.context);
|
||||||
|
let api_req = req.query.api;
|
||||||
|
let api_type = req.query.type;
|
||||||
|
let api_target = req.query.target;
|
||||||
|
|
||||||
|
if (req.query.hasOwnProperty('api')) api_req = true;
|
||||||
|
else api_req = false;
|
||||||
|
|
||||||
|
let raw_json = api_req && req.query.raw_json == '1' ? 1 : 0;
|
||||||
|
|
||||||
if (req.params.comment_id) {
|
if (req.params.comment_id) {
|
||||||
comment_id = `${req.params.comment_id}/`;
|
comment_id = `${req.params.comment_id}/`;
|
||||||
viewing_comment = true;
|
viewing_comment = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sortby === 'best') {
|
||||||
|
// in Reddit the sorting "best" is the label, but the actual key "confidence"
|
||||||
|
sortby = 'confidence';
|
||||||
|
}
|
||||||
|
|
||||||
if (!sortby) {
|
if (!sortby) {
|
||||||
sortby = config.post_comments_sort;
|
sortby = config.post_comments_sort;
|
||||||
}
|
}
|
||||||
|
@ -604,7 +786,7 @@ subredditRoutes.get(
|
||||||
|
|
||||||
let comments_url = `/r/${subreddit}/comments/${id}/${snippet}/${comment_id}`;
|
let comments_url = `/r/${subreddit}/comments/${id}/${snippet}/${comment_id}`;
|
||||||
let post_url = `/r/${subreddit}/comments/${id}/${snippet}/`;
|
let post_url = `/r/${subreddit}/comments/${id}/${snippet}/`;
|
||||||
let comments_key = `${comments_url}:sort:${sortby}`;
|
let comments_key = `${comments_url}:sort:${sortby}:raw_json:${raw_json}`;
|
||||||
|
|
||||||
redis.get(comments_key, (error, json) => {
|
redis.get(comments_key, (error, json) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -612,64 +794,77 @@ subredditRoutes.get(
|
||||||
`Error getting the ${comments_url} key from redis.`,
|
`Error getting the ${comments_url} key from redis.`,
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
post: null,
|
post: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
console.log(`Got ${comments_url} key from redis.`);
|
console.log(`Got ${comments_url} key from redis.`);
|
||||||
(async () => {
|
(async () => {
|
||||||
let parsed = false;
|
if (api_req) {
|
||||||
let more_comments = null;
|
return handleTedditApiPost(
|
||||||
if (comment_ids) {
|
json,
|
||||||
let key = `${post_url}:morechildren:comment_ids:${comment_ids}`;
|
req,
|
||||||
more_comments = await moreComments(
|
res,
|
||||||
fetch,
|
'redis',
|
||||||
redis,
|
api_type,
|
||||||
post_url,
|
api_target
|
||||||
comment_ids,
|
|
||||||
id
|
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
let parsed = false;
|
||||||
|
let more_comments = null;
|
||||||
|
if (comment_ids) {
|
||||||
|
let key = `${post_url}:morechildren:comment_ids:${comment_ids}`;
|
||||||
|
more_comments = await processMoreComments(
|
||||||
|
fetch,
|
||||||
|
redis,
|
||||||
|
post_url,
|
||||||
|
comment_ids,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
|
||||||
if (more_comments === false) {
|
if (more_comments === false) {
|
||||||
return res.redirect(post_url);
|
return res.redirect(post_url);
|
||||||
} else {
|
} else {
|
||||||
json = JSON.parse(json);
|
json = JSON.parse(json);
|
||||||
json[1].data.children = more_comments;
|
json[1].data.children = more_comments;
|
||||||
parsed = true;
|
parsed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let processed_json = await processJsonPost(json, parsed, req.cookies);
|
let processed_json = await processJsonPost(json, parsed, req.cookies);
|
||||||
let finalized_json = await finalizeJsonPost(
|
let finalized_json = await finalizeJsonPost(
|
||||||
processed_json,
|
processed_json,
|
||||||
id,
|
id,
|
||||||
post_url,
|
post_url,
|
||||||
more_comments,
|
more_comments,
|
||||||
viewing_comment,
|
viewing_comment,
|
||||||
req.cookies
|
req.cookies
|
||||||
);
|
);
|
||||||
return res.render('post', {
|
return res.render('post', {
|
||||||
post: finalized_json.post_data,
|
post: finalized_json.post_data,
|
||||||
comments: finalized_json.comments,
|
comments: finalized_json.comments,
|
||||||
viewing_comment: viewing_comment,
|
viewing_comment: viewing_comment,
|
||||||
post_url: post_url,
|
post_url: post_url,
|
||||||
subreddit: subreddit,
|
subreddit: subreddit,
|
||||||
sortby: sortby,
|
sortby: sortby,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
instance_nsfw_enabled: config.nsfw_enabled,
|
instance_nsfw_enabled: config.nsfw_enabled,
|
||||||
instance_videos_muted: config.videos_muted,
|
instance_videos_muted: config.videos_muted,
|
||||||
post_media_max_heights: config.post_media_max_heights,
|
post_media_max_heights: config.post_media_max_heights,
|
||||||
redis_key: comments_key,
|
redis_key: comments_key,
|
||||||
});
|
instance_config: config,
|
||||||
|
});
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
} else {
|
} else {
|
||||||
let url = '';
|
let url = '';
|
||||||
if (config.use_reddit_oauth)
|
if (config.use_reddit_oauth)
|
||||||
url = `https://oauth.reddit.com${comments_url}?api_type=json&sort=${sortby}&context=${context}`;
|
url = `https://oauth.reddit.com${comments_url}?api_type=json&sort=${sortby}&context=${context}&raw_json=${raw_json}`;
|
||||||
else
|
else
|
||||||
url = `https://reddit.com${comments_url}.json?api_type=json&sort=${sortby}&context=${context}`;
|
url = `https://reddit.com${comments_url}.json?api_type=json&sort=${sortby}&context=${context}&raw_json=${raw_json}`;
|
||||||
|
|
||||||
fetch(encodeURI(url), redditApiGETHeaders())
|
fetch(encodeURI(url), redditApiGETHeaders())
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
|
@ -688,55 +883,69 @@ subredditRoutes.get(
|
||||||
return res.render('post', {
|
return res.render('post', {
|
||||||
post: null,
|
post: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
`Fetched the JSON from reddit.com${comments_url}.`
|
`Fetched the JSON from reddit.com${comments_url}.`
|
||||||
);
|
);
|
||||||
(async () => {
|
(async () => {
|
||||||
let more_comments = null;
|
if (api_req) {
|
||||||
if (comment_ids) {
|
return handleTedditApiPost(
|
||||||
let key = `${post_url}:morechildren:comment_ids:${comment_ids}`;
|
json,
|
||||||
more_comments = await moreComments(
|
req,
|
||||||
fetch,
|
res,
|
||||||
redis,
|
'from_online',
|
||||||
post_url,
|
api_type,
|
||||||
comment_ids,
|
api_target
|
||||||
id
|
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
let more_comments = null;
|
||||||
|
if (comment_ids) {
|
||||||
|
let key = `${post_url}:morechildren:comment_ids:${comment_ids}`;
|
||||||
|
more_comments = await processMoreComments(
|
||||||
|
fetch,
|
||||||
|
redis,
|
||||||
|
post_url,
|
||||||
|
comment_ids,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
|
||||||
if (more_comments === false) {
|
if (more_comments === false) {
|
||||||
return res.redirect(post_url);
|
return res.redirect(post_url);
|
||||||
} else {
|
} else {
|
||||||
json[1].data.children = more_comments;
|
json[1].data.children = more_comments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let processed_json = await processJsonPost(
|
let processed_json = await processJsonPost(
|
||||||
json,
|
json,
|
||||||
true,
|
true,
|
||||||
req.cookies
|
req.cookies
|
||||||
);
|
);
|
||||||
let finalized_json = await finalizeJsonPost(
|
let finalized_json = await finalizeJsonPost(
|
||||||
processed_json,
|
processed_json,
|
||||||
id,
|
id,
|
||||||
post_url,
|
post_url,
|
||||||
more_comments,
|
more_comments,
|
||||||
viewing_comment
|
viewing_comment,
|
||||||
);
|
req.cookies
|
||||||
return res.render('post', {
|
);
|
||||||
post: finalized_json.post_data,
|
return res.render('post', {
|
||||||
comments: finalized_json.comments,
|
post: finalized_json.post_data,
|
||||||
viewing_comment: viewing_comment,
|
comments: finalized_json.comments,
|
||||||
post_url: post_url,
|
viewing_comment: viewing_comment,
|
||||||
subreddit: subreddit,
|
post_url: post_url,
|
||||||
sortby: sortby,
|
subreddit: subreddit,
|
||||||
user_preferences: req.cookies,
|
sortby: sortby,
|
||||||
instance_nsfw_enabled: config.nsfw_enabled,
|
user_preferences: req.cookies,
|
||||||
instance_videos_muted: config.videos_muted,
|
instance_nsfw_enabled: config.nsfw_enabled,
|
||||||
post_media_max_heights: config.post_media_max_heights,
|
instance_videos_muted: config.videos_muted,
|
||||||
redis_key: comments_key,
|
post_media_max_heights: config.post_media_max_heights,
|
||||||
});
|
redis_key: comments_key,
|
||||||
|
instance_config: config,
|
||||||
|
});
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -751,11 +960,12 @@ subredditRoutes.get(
|
||||||
);
|
);
|
||||||
console.error(config.reddit_api_error_text);
|
console.error(config.reddit_api_error_text);
|
||||||
}
|
}
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
http_statustext: result.statusText,
|
http_statustext: result.statusText,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -800,6 +1010,14 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => {
|
||||||
let before = req.query.before;
|
let before = req.query.before;
|
||||||
let sortby = req.params.sort;
|
let sortby = req.params.sort;
|
||||||
let searching = false;
|
let searching = false;
|
||||||
|
let api_req = req.query.api;
|
||||||
|
let api_type = req.query.type;
|
||||||
|
let api_target = req.query.target;
|
||||||
|
|
||||||
|
if (req.query.hasOwnProperty('api')) api_req = true;
|
||||||
|
else api_req = false;
|
||||||
|
|
||||||
|
let raw_json = api_req && req.query.raw_json == '1' ? 1 : 0;
|
||||||
|
|
||||||
if (!after) {
|
if (!after) {
|
||||||
after = '';
|
after = '';
|
||||||
|
@ -821,66 +1039,81 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => {
|
||||||
sortby = '';
|
sortby = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = `subreddits:sort:${sortby}${d}`;
|
let key = `subreddits:sort:${sortby}${d}:raw_json:${raw_json}`;
|
||||||
|
|
||||||
if (sortby === 'search') {
|
if (sortby === 'search') {
|
||||||
if (typeof q == 'undefined' || q == '') return res.redirect('/subreddits');
|
if (typeof q == 'undefined' || q == '') return res.redirect('/subreddits');
|
||||||
|
|
||||||
key = `subreddits:search:q:${q}:nsfw:${nsfw}${d}`;
|
key = `subreddits:search:q:${q}:nsfw:${nsfw}${d}:raw_json:${raw_json}`;
|
||||||
searching = true;
|
searching = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
redis.get(key, (error, json) => {
|
redis.get(key, (error, json) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error(`Error getting the subreddits key from redis.`, error);
|
console.error(`Error getting the subreddits key from redis.`, error);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
console.log(`Got subreddits key from redis.`);
|
console.log(`Got subreddits key from redis.`);
|
||||||
(async () => {
|
(async () => {
|
||||||
let processed_json = await processJsonSubredditsExplore(
|
if (api_req) {
|
||||||
json,
|
return handleTedditApiSubredditsExplore(
|
||||||
'redis',
|
json,
|
||||||
null,
|
req,
|
||||||
req.cookies
|
res,
|
||||||
);
|
'redis',
|
||||||
if (!processed_json.error) {
|
api_type,
|
||||||
return res.render('subreddits_explore', {
|
api_target,
|
||||||
json: processed_json,
|
q
|
||||||
sortby: sortby,
|
);
|
||||||
after: after,
|
|
||||||
before: before,
|
|
||||||
q: q,
|
|
||||||
nsfw: nsfw,
|
|
||||||
searching: searching,
|
|
||||||
subreddits_front: !before && !after ? true : false,
|
|
||||||
user_preferences: req.cookies,
|
|
||||||
instance_nsfw_enabled: config.nsfw_enabled,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
return res.render('subreddits_explore', {
|
let processed_json = await processJsonSubredditsExplore(
|
||||||
json: null,
|
json,
|
||||||
error: true,
|
'redis',
|
||||||
data: processed_json,
|
null,
|
||||||
user_preferences: req.cookies,
|
req.cookies
|
||||||
});
|
);
|
||||||
|
if (!processed_json.error) {
|
||||||
|
return res.render('subreddits_explore', {
|
||||||
|
json: processed_json,
|
||||||
|
sortby: sortby,
|
||||||
|
after: after,
|
||||||
|
before: before,
|
||||||
|
q: q,
|
||||||
|
nsfw: nsfw,
|
||||||
|
searching: searching,
|
||||||
|
subreddits_front: !before && !after ? true : false,
|
||||||
|
user_preferences: req.cookies,
|
||||||
|
instance_nsfw_enabled: config.nsfw_enabled,
|
||||||
|
instance_config: config,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return res.render('subreddits_explore', {
|
||||||
|
json: null,
|
||||||
|
error: true,
|
||||||
|
data: processed_json,
|
||||||
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
} else {
|
} else {
|
||||||
let url = '';
|
let url = '';
|
||||||
if (config.use_reddit_oauth) {
|
if (config.use_reddit_oauth) {
|
||||||
if (!searching)
|
if (!searching)
|
||||||
url = `https://oauth.reddit.com/subreddits/${sortby}?api_type=json&count=25&g=GLOBAL&t=${d}`;
|
url = `https://oauth.reddit.com/subreddits/${sortby}?api_type=json&count=25&g=GLOBAL&t=${d}&raw_json=${raw_json}`;
|
||||||
else
|
else
|
||||||
url = `https://oauth.reddit.com/subreddits/search?api_type=json&q=${q}&include_over_18=${nsfw}${d}`;
|
url = `https://oauth.reddit.com/subreddits/search?api_type=json&q=${q}&include_over_18=${nsfw}${d}&raw_json=${raw_json}`;
|
||||||
} else {
|
} else {
|
||||||
if (!searching)
|
if (!searching)
|
||||||
url = `https://reddit.com/subreddits/${sortby}.json?api_type=json&count=25&g=GLOBAL&t=${d}`;
|
url = `https://reddit.com/subreddits/${sortby}.json?api_type=json&count=25&g=GLOBAL&t=${d}&raw_json=${raw_json}`;
|
||||||
else
|
else
|
||||||
url = `https://reddit.com/subreddits/search.json?api_type=json&q=${q}&include_over_18=${nsfw}${d}`;
|
url = `https://reddit.com/subreddits/search.json?api_type=json&q=${q}&include_over_18=${nsfw}${d}&raw_json=${raw_json}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(encodeURI(url), redditApiGETHeaders())
|
fetch(encodeURI(url), redditApiGETHeaders())
|
||||||
|
@ -899,28 +1132,42 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => {
|
||||||
return res.render('subreddits_explore', {
|
return res.render('subreddits_explore', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log(`Fetched the JSON from reddit.com/subreddits.`);
|
console.log(`Fetched the JSON from reddit.com/subreddits.`);
|
||||||
(async () => {
|
(async () => {
|
||||||
let processed_json = await processJsonSubredditsExplore(
|
if (api_req) {
|
||||||
json,
|
return handleTedditApiSubredditsExplore(
|
||||||
'from_online',
|
json,
|
||||||
null,
|
req,
|
||||||
req.cookies
|
res,
|
||||||
);
|
'from_online',
|
||||||
return res.render('subreddits_explore', {
|
api_type,
|
||||||
json: processed_json,
|
api_target,
|
||||||
sortby: sortby,
|
q
|
||||||
after: after,
|
);
|
||||||
before: before,
|
} else {
|
||||||
q: q,
|
let processed_json = await processJsonSubredditsExplore(
|
||||||
nsfw: nsfw,
|
json,
|
||||||
searching: searching,
|
'from_online',
|
||||||
subreddits_front: !before && !after ? true : false,
|
null,
|
||||||
user_preferences: req.cookies,
|
req.cookies
|
||||||
instance_nsfw_enabled: config.nsfw_enabled,
|
);
|
||||||
});
|
return res.render('subreddits_explore', {
|
||||||
|
json: processed_json,
|
||||||
|
sortby: sortby,
|
||||||
|
after: after,
|
||||||
|
before: before,
|
||||||
|
q: q,
|
||||||
|
nsfw: nsfw,
|
||||||
|
searching: searching,
|
||||||
|
subreddits_front: !before && !after ? true : false,
|
||||||
|
user_preferences: req.cookies,
|
||||||
|
instance_nsfw_enabled: config.nsfw_enabled,
|
||||||
|
instance_config: config,
|
||||||
|
});
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -934,10 +1181,11 @@ subredditRoutes.get('/subreddits/:sort?', (req, res, next) => {
|
||||||
);
|
);
|
||||||
console.error(config.reddit_api_error_text);
|
console.error(config.reddit_api_error_text);
|
||||||
}
|
}
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,16 +2,11 @@ const config = require('../config');
|
||||||
const { redis, fetch } = require('../app');
|
const { redis, fetch } = require('../app');
|
||||||
const userRoutes = require('express').Router();
|
const userRoutes = require('express').Router();
|
||||||
|
|
||||||
const processUser = require('../inc/processJsonUser.js')();
|
const processJsonUser = require('../inc/processJsonUser.js');
|
||||||
const processPost = require('../inc/processJsonPost.js')();
|
|
||||||
const processAbout = require('../inc/processSubredditAbout.js')();
|
|
||||||
const tedditApiUser = require('../inc/teddit_api/handleUser.js')();
|
const tedditApiUser = require('../inc/teddit_api/handleUser.js')();
|
||||||
const processSearches = require('../inc/processSearchResults.js')();
|
const processJsonSubreddit = require('../inc/processJsonSubreddit.js');
|
||||||
const processSubreddit = require('../inc/processJsonSubreddit.js')();
|
|
||||||
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
const tedditApiSubreddit = require('../inc/teddit_api/handleSubreddit.js')();
|
||||||
const processMoreComments = require('../inc/processMoreComments.js')();
|
const processMoreComments = require('../inc/processMoreComments.js')();
|
||||||
const processSubredditsExplore =
|
|
||||||
require('../inc/processSubredditsExplore.js')();
|
|
||||||
|
|
||||||
userRoutes.get('/user/:user/:kind?', (req, res, next) => {
|
userRoutes.get('/user/:user/:kind?', (req, res, next) => {
|
||||||
let kind = '';
|
let kind = '';
|
||||||
|
@ -96,9 +91,10 @@ userRoutes.get('/u/:user/:kind?', (req, res, next) => {
|
||||||
redis.get(key, (error, json) => {
|
redis.get(key, (error, json) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error(`Error getting the user ${key} key from redis.`, error);
|
console.error(`Error getting the user ${key} key from redis.`, error);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
|
@ -131,6 +127,7 @@ userRoutes.get('/u/:user/:kind?', (req, res, next) => {
|
||||||
sortby: sortby,
|
sortby: sortby,
|
||||||
past: past,
|
past: past,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -168,9 +165,10 @@ userRoutes.get('/u/:user/:kind?', (req, res, next) => {
|
||||||
`Error setting the user ${key} key to redis.`,
|
`Error setting the user ${key} key to redis.`,
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
post: null,
|
post: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
(async () => {
|
(async () => {
|
||||||
|
@ -201,22 +199,33 @@ userRoutes.get('/u/:user/:kind?', (req, res, next) => {
|
||||||
sortby: sortby,
|
sortby: sortby,
|
||||||
past: past,
|
past: past,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
}).catch(error => {
|
||||||
|
console.error(`Something went wrong while fetching data from Reddit API: invalid or non-JSON data was returned.`);
|
||||||
|
return res.render('frontpage', {
|
||||||
|
json: null,
|
||||||
|
http_status_code: 500,
|
||||||
|
http_statustext: "Invalid response from Reddit",
|
||||||
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
console.error(
|
||||||
`Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}`
|
`Something went wrong while fetching data from Reddit. ${result.status} – ${result.statusText}`
|
||||||
);
|
);
|
||||||
console.error(config.reddit_api_error_text);
|
console.error(config.reddit_api_error_text);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -225,10 +234,11 @@ userRoutes.get('/u/:user/:kind?', (req, res, next) => {
|
||||||
`Error fetching the overview JSON file from reddit.com/u/${user}`,
|
`Error fetching the overview JSON file from reddit.com/u/${user}`,
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -241,11 +251,12 @@ userRoutes.get('/u/:user/:kind?', (req, res, next) => {
|
||||||
);
|
);
|
||||||
console.error(config.reddit_api_error_text);
|
console.error(config.reddit_api_error_text);
|
||||||
}
|
}
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
http_statustext: result.statusText,
|
http_statustext: result.statusText,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -316,9 +327,10 @@ userRoutes.get('/u/:user/m/:custom_feed/:sort?', (req, res, next) => {
|
||||||
`Error getting the ${user} custom_feed key from redis.`,
|
`Error getting the ${user} custom_feed key from redis.`,
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (json) {
|
if (json) {
|
||||||
|
@ -332,7 +344,8 @@ userRoutes.get('/u/:user/m/:custom_feed/:sort?', (req, res, next) => {
|
||||||
'redis',
|
'redis',
|
||||||
api_type,
|
api_type,
|
||||||
api_target,
|
api_target,
|
||||||
subreddit
|
subreddit,
|
||||||
|
'full'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let processed_json = await processJsonSubreddit(
|
let processed_json = await processJsonSubreddit(
|
||||||
|
@ -354,6 +367,7 @@ userRoutes.get('/u/:user/m/:custom_feed/:sort?', (req, res, next) => {
|
||||||
redis_key: key,
|
redis_key: key,
|
||||||
after: req.query.after,
|
after: req.query.after,
|
||||||
before: req.query.before,
|
before: req.query.before,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return res.render('subreddit', {
|
return res.render('subreddit', {
|
||||||
|
@ -361,6 +375,7 @@ userRoutes.get('/u/:user/m/:custom_feed/:sort?', (req, res, next) => {
|
||||||
error: true,
|
error: true,
|
||||||
data: processed_json,
|
data: processed_json,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,6 +403,7 @@ userRoutes.get('/u/:user/m/:custom_feed/:sort?', (req, res, next) => {
|
||||||
return res.render('subreddit', {
|
return res.render('subreddit', {
|
||||||
json: null,
|
json: null,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -402,7 +418,8 @@ userRoutes.get('/u/:user/m/:custom_feed/:sort?', (req, res, next) => {
|
||||||
'from_online',
|
'from_online',
|
||||||
api_type,
|
api_type,
|
||||||
api_target,
|
api_target,
|
||||||
subreddit
|
subreddit,
|
||||||
|
'full'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let processed_json = await processJsonSubreddit(
|
let processed_json = await processJsonSubreddit(
|
||||||
|
@ -423,6 +440,7 @@ userRoutes.get('/u/:user/m/:custom_feed/:sort?', (req, res, next) => {
|
||||||
redis_key: key,
|
redis_key: key,
|
||||||
after: req.query.after,
|
after: req.query.after,
|
||||||
before: req.query.before,
|
before: req.query.before,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -439,10 +457,11 @@ userRoutes.get('/u/:user/m/:custom_feed/:sort?', (req, res, next) => {
|
||||||
);
|
);
|
||||||
console.error(config.reddit_api_error_text);
|
console.error(config.reddit_api_error_text);
|
||||||
}
|
}
|
||||||
return res.render('index', {
|
return res.render('frontpage', {
|
||||||
json: null,
|
json: null,
|
||||||
http_status_code: result.status,
|
http_status_code: result.status,
|
||||||
user_preferences: req.cookies,
|
user_preferences: req.cookies,
|
||||||
|
instance_config: config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,211 @@
|
||||||
|
:root {
|
||||||
|
--darkbg: #2E3440;
|
||||||
|
--darkbglight: #434C5E;
|
||||||
|
--darklinkcolor: #599bff;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.nord {
|
||||||
|
background: var(--darkbg);
|
||||||
|
color: #ECEFF4;
|
||||||
|
}
|
||||||
|
body.nord nav {
|
||||||
|
background: #3E4450;
|
||||||
|
}
|
||||||
|
body.nord .top-links a {
|
||||||
|
background: var(--darkbg);
|
||||||
|
color: #bfbfbf;
|
||||||
|
}
|
||||||
|
body.nord header {
|
||||||
|
background: var(--darkbglight);
|
||||||
|
color: #f1f1f1;
|
||||||
|
}
|
||||||
|
body.nord #post header div a {
|
||||||
|
color: var(--darklinkcolor);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
body.nord a {
|
||||||
|
color: #f5f5f5;
|
||||||
|
}
|
||||||
|
body.nord a:hover, body.nord a:focus {
|
||||||
|
color: #88C0D0;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
body.nord #post header div a:hover,
|
||||||
|
body.nord #post header div a:focus {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
body.nord input[type="submit"]:hover,
|
||||||
|
body.nord input[type="submit"]:focus,
|
||||||
|
body.nord .btn:hover,
|
||||||
|
body.nord .btn:focus {
|
||||||
|
background: #ECEFF4;
|
||||||
|
color: #2E3440;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
body.nord form legend {
|
||||||
|
border-bottom: 1px solid #353535;
|
||||||
|
}
|
||||||
|
body.nord #post .title a {
|
||||||
|
color: var(--darklinkcolor);
|
||||||
|
}
|
||||||
|
body.nord #post .submitted {
|
||||||
|
color: #a5a5a5;
|
||||||
|
}
|
||||||
|
body.nord #post .usertext-body {
|
||||||
|
background: #2A2935;
|
||||||
|
border: 1px solid #404040;
|
||||||
|
}
|
||||||
|
body.nord .infobar {
|
||||||
|
background-color: #d2d2d2;
|
||||||
|
color: #2f2f2f;
|
||||||
|
}
|
||||||
|
body.nord .infobar.blue {
|
||||||
|
background: #c7e3f9;
|
||||||
|
border: 1px solid #4b78a4;
|
||||||
|
}
|
||||||
|
body.nord .infobar a {
|
||||||
|
color: #0356d4;
|
||||||
|
}
|
||||||
|
body.nord header .tabmenu li a {
|
||||||
|
background: #3e3e3e;
|
||||||
|
}
|
||||||
|
body.nord header .tabmenu li a:hover, body.nord header .tabmenu li a:focus {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #ECEFF4;
|
||||||
|
}
|
||||||
|
body.nord #search {
|
||||||
|
color: #d2d2d2;
|
||||||
|
}
|
||||||
|
body.nord .md {
|
||||||
|
color: #dadada;
|
||||||
|
}
|
||||||
|
body.nord .md blockquote, body.nord .md del {
|
||||||
|
color: #777777;
|
||||||
|
}
|
||||||
|
body.nord .md code, body.nord .md pre {
|
||||||
|
background: #2E3440;
|
||||||
|
color: #cacaca;
|
||||||
|
}
|
||||||
|
body.nord .comment .body blockquote {
|
||||||
|
background: #2E3440;
|
||||||
|
color: #afafaf;
|
||||||
|
border-color: #464646;
|
||||||
|
}
|
||||||
|
body.nord .even-depth {
|
||||||
|
background: var(--darkbg);
|
||||||
|
}
|
||||||
|
body.nord .odd-depth {
|
||||||
|
background: var(--darkbglight);
|
||||||
|
}
|
||||||
|
|
||||||
|
body.nord .comment .comment {
|
||||||
|
border-left: 1px solid #545454;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.nord .comment .meta .created a {
|
||||||
|
color: #7b7b7b;
|
||||||
|
}
|
||||||
|
body.nord .comment details summary {
|
||||||
|
color: #868686;
|
||||||
|
}
|
||||||
|
body.nord .comment details summary::-webkit-details-marker,
|
||||||
|
body.nord .comment details summary::marker {
|
||||||
|
color: #868686;
|
||||||
|
}
|
||||||
|
body.nord #links .link .entry .title a h2 {
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
body.nord #links .link .entry .title a:visited h2 {
|
||||||
|
color: #8FBCBB;
|
||||||
|
}
|
||||||
|
body.nord #links .link .image .no-image,
|
||||||
|
body.nord #user .entry .image .no-image {
|
||||||
|
filter: opacity(0.5);
|
||||||
|
}
|
||||||
|
body.nord #user .comment {
|
||||||
|
width: 100%;
|
||||||
|
background: var(--darkbg);
|
||||||
|
}
|
||||||
|
body.nord #links .link .upvotes {
|
||||||
|
color: #D08770;
|
||||||
|
}
|
||||||
|
body.nord .upvotes .arrow,
|
||||||
|
body.nord .score .arrow {
|
||||||
|
filter: opacity(0.5);
|
||||||
|
}
|
||||||
|
body.nord #links .link .entry .meta a {
|
||||||
|
color: #81A1C1;
|
||||||
|
}
|
||||||
|
#links .link .entry .meta {
|
||||||
|
color: #D8DEE9 !important;
|
||||||
|
}
|
||||||
|
#links .link .entry .title span {
|
||||||
|
color: #5E81AC !important;
|
||||||
|
}
|
||||||
|
body.nord #links .link .entry .selftext {
|
||||||
|
background: #2A2935;
|
||||||
|
border: 1px solid #404040;
|
||||||
|
}
|
||||||
|
body.nord #links .link .entry .meta .links .selftext a {
|
||||||
|
color: var(--darklinkcolor);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
body.nord #links .link .entry details .line {
|
||||||
|
width: 16px;
|
||||||
|
margin-top: 3px;
|
||||||
|
background: #4C566A;
|
||||||
|
border: 1px solid #81A1C1;
|
||||||
|
}
|
||||||
|
body.nord .content .bottom img {
|
||||||
|
filter: invert(1);
|
||||||
|
}
|
||||||
|
body.nord .container .content {
|
||||||
|
border: 1px solid #434C5E;
|
||||||
|
}
|
||||||
|
body.nord input[type="submit"],
|
||||||
|
body.nord .btn {
|
||||||
|
background: #2E3440;
|
||||||
|
color: #ECEFF4;
|
||||||
|
}
|
||||||
|
body.nord #post .crosspost {
|
||||||
|
background: var(--darkbg);
|
||||||
|
}
|
||||||
|
body.nord .view-more-links a {
|
||||||
|
background: #2E3440;
|
||||||
|
color: #cacaca;
|
||||||
|
}
|
||||||
|
body.nord .md .md-spoiler-text:not(.revealed):active,
|
||||||
|
body.nord .md .md-spoiler-text:not(.revealed):focus,
|
||||||
|
body.nord .md .md-spoiler-text:not(.revealed):hover {
|
||||||
|
background: #cacaca;
|
||||||
|
color: #2E3440;
|
||||||
|
}
|
||||||
|
body.nord .comment .body a,
|
||||||
|
body.nord .usertext-body a {
|
||||||
|
color: #3d99fb;
|
||||||
|
}
|
||||||
|
body.nord header .tabmenu li.active a {
|
||||||
|
background: #acacac;
|
||||||
|
color: #151515;
|
||||||
|
}
|
||||||
|
body.nord #search form input[type="text"] {
|
||||||
|
background: #2E3440;
|
||||||
|
color: #ECEFF4;
|
||||||
|
}
|
||||||
|
body.nord footer {
|
||||||
|
background: #2f2f2f;
|
||||||
|
}
|
||||||
|
body.nord footer a {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
body.nord .flair {
|
||||||
|
color: #eaeaea !important;
|
||||||
|
background-color: #404040 !important;
|
||||||
|
}
|
||||||
|
body.nord #sr-more-link {
|
||||||
|
color: #ECEFF4;
|
||||||
|
background: #2E3440;
|
||||||
|
}
|
||||||
|
body.nord #post .usertext-body .poll {
|
||||||
|
border: 1px solid #404040;
|
||||||
|
}
|
|
@ -84,6 +84,7 @@ nav .nav-item.left a {
|
||||||
}
|
}
|
||||||
nav .nav-item.left img {
|
nav .nav-item.left img {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
margin: 0 7px 0 0;
|
margin: 0 7px 0 0;
|
||||||
}
|
}
|
||||||
|
@ -280,9 +281,11 @@ header .tabmenu li.active a {
|
||||||
color: white;
|
color: white;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
input, select {
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
input[type="submit"],
|
input[type="submit"],
|
||||||
.btn {
|
.btn {
|
||||||
padding: 3px;
|
|
||||||
margin-top: 7px;
|
margin-top: 7px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
@ -749,6 +752,14 @@ footer a {
|
||||||
#post .submitted span {
|
#post .submitted span {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
#post .source-details {
|
||||||
|
float: left;
|
||||||
|
margin: 10px 0 10px 30px;
|
||||||
|
}
|
||||||
|
#post .source-details summary:hover {
|
||||||
|
color: var(--linkcolor);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
#post .comments {
|
#post .comments {
|
||||||
float: left;
|
float: left;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -1572,6 +1583,103 @@ code {
|
||||||
padding:4px;
|
padding:4px;
|
||||||
margin:5px 0
|
margin:5px 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* "CLEANED HOMEPAGE" SECTION */
|
||||||
|
body.homepage.clean {
|
||||||
|
margin: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.homepage.clean main {
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.homepage.clean h1 {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-size: 3rem;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.homepage.clean form {
|
||||||
|
width: 100vw;
|
||||||
|
max-width: 750px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.homepage.clean input[name="q"] {
|
||||||
|
width: 90%;
|
||||||
|
padding: 0.4rem;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
background: #555;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.homepage.clean .sublinks {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
max-width: 650px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.homepage.clean .sublinks a {
|
||||||
|
color: gray;
|
||||||
|
margin-right: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.homepage.clean .top-links {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 768px) {
|
||||||
|
body.homepage.clean form, body.homepage.clean .sublinks {
|
||||||
|
width: 90%;
|
||||||
|
max-width: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Large gallery items */
|
||||||
|
.gallery .item.large {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
position: relative;
|
||||||
|
margin-right: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery .item.large img {
|
||||||
|
max-height: 90vh;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery .item.large .caption {
|
||||||
|
position: absolute;
|
||||||
|
width: calc(100% - 0.6rem);
|
||||||
|
color: white;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
padding: 0.3rem;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 768px) {
|
||||||
|
.gallery .item.large img {
|
||||||
|
max-height: unset;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Fix spoiler texts not showing without JS */
|
/* Fix spoiler texts not showing without JS */
|
||||||
.md .md-spoiler-text:not(.revealed):active,.md .md-spoiler-text:not(.revealed):focus,.md .md-spoiler-text:not(.revealed):hover {
|
.md .md-spoiler-text:not(.revealed):active,.md .md-spoiler-text:not(.revealed):focus,.md .md-spoiler-text:not(.revealed):hover {
|
||||||
color: black;
|
color: black;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
../instances.json
|
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
|
@ -1,2 +1,3 @@
|
||||||
User-agent: MJ12bot
|
User-agent: MJ12bot
|
||||||
|
User-agent: Applebot
|
||||||
Disallow: /
|
Disallow: /
|
||||||
|
|
|
@ -2,6 +2,9 @@ doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title about - teddit
|
title about - teddit
|
||||||
|
meta(property='og:title', content='about - teddit')
|
||||||
|
include includes/meta_default.pug
|
||||||
|
include includes/meta_description.pug
|
||||||
include includes/head.pug
|
include includes/head.pug
|
||||||
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
||||||
include includes/topbar.pug
|
include includes/topbar.pug
|
||||||
|
@ -18,8 +21,10 @@ html
|
||||||
a(href="/privacy") Privacy policy
|
a(href="/privacy") Privacy policy
|
||||||
h2 Donating
|
h2 Donating
|
||||||
p(class="word-break") XMR: 832ogRwuoSs2JGYg7wJTqshidK7dErgNdfpenQ9dzMghNXQTJRby1xGbqC3gW3GAifRM9E84J91VdMZRjoSJ32nkAZnaCEj
|
p(class="word-break") XMR: 832ogRwuoSs2JGYg7wJTqshidK7dErgNdfpenQ9dzMghNXQTJRby1xGbqC3gW3GAifRM9E84J91VdMZRjoSJ32nkAZnaCEj
|
||||||
|
h2 Legal
|
||||||
|
p Teddit does not host any content. All content shown on any Teddit instances is from Reddit™. Reddit is a trademark of Reddit Inc. Teddit is not affiliated with Reddit Inc. Any issues with content shown on any Teddit instances need to be reported to Reddit, not the instance host's internet provider or domain provider.
|
||||||
.bottom
|
.bottom
|
||||||
a(href="https://en.wikipedia.org/wiki/Piratbyr%C3%A5n#Kopimi", target="_blank")
|
a(href="https://en.wikipedia.org/wiki/Piratbyr%C3%A5n#Kopimi", target="_blank")
|
||||||
img(src="kopimi.gif")
|
img(src="kopimi.gif")
|
||||||
p.version v.0.4.0
|
p.version v.0.4.9
|
||||||
include includes/footer.pug
|
include includes/footer.pug
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
.link
|
.link
|
||||||
|
if user_preferences.show_upvotes === 'false'
|
||||||
|
style.
|
||||||
|
.upvotes {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.upvotes
|
.upvotes
|
||||||
.arrow
|
.arrow
|
||||||
span #{kFormatter(link.ups)}
|
span #{kFormatter(link.ups)}
|
||||||
|
@ -92,3 +97,4 @@
|
||||||
a(href="/unsave/" + link.id + "/?rk=" + redis_key + "&b=" + back_url + "") unsave
|
a(href="/unsave/" + link.id + "/?rk=" + redis_key + "&b=" + back_url + "") unsave
|
||||||
else
|
else
|
||||||
a(href="/save/" + link.id + "/?rk=" + redis_key + "&b=" + back_url + "") save
|
a(href="/save/" + link.id + "/?rk=" + redis_key + "&b=" + back_url + "") save
|
||||||
|
a(href=("https://www.reddit.com" + link.permalink) target="_blank" title="Open in Reddit (new tab)") [R↗]
|
||||||
|
|
|
@ -2,6 +2,9 @@ doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title teddit
|
title teddit
|
||||||
|
meta(property='og:title', content='frontpage : teddit')
|
||||||
|
include includes/meta_default.pug
|
||||||
|
include includes/meta_description.pug
|
||||||
include includes/head.pug
|
include includes/head.pug
|
||||||
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
||||||
include includes/topbar.pug
|
include includes/topbar.pug
|
||||||
|
@ -38,6 +41,7 @@ html
|
||||||
#intro
|
#intro
|
||||||
h1 Welcome to teddit
|
h1 Welcome to teddit
|
||||||
h2 the alternative, privacy respecting, front page of internet.
|
h2 the alternative, privacy respecting, front page of internet.
|
||||||
|
|
||||||
#links.sr
|
#links.sr
|
||||||
if sortby === 'top' || sortby === 'controversial'
|
if sortby === 'top' || sortby === 'controversial'
|
||||||
details
|
details
|
|
@ -0,0 +1,33 @@
|
||||||
|
doctype html
|
||||||
|
html
|
||||||
|
head
|
||||||
|
title teddit
|
||||||
|
meta(property='og:title', content='home : teddit')
|
||||||
|
include includes/meta_default.pug
|
||||||
|
include includes/meta_description.pug
|
||||||
|
include includes/head.pug
|
||||||
|
body(class="" + (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + " homepage clean")
|
||||||
|
include includes/topbar.pug
|
||||||
|
main
|
||||||
|
h1 teddit
|
||||||
|
form(action="/search", method="GET")
|
||||||
|
input(type="text", name="q")
|
||||||
|
input(type="hidden", name="restrict_sr", value="on")
|
||||||
|
input(type="hidden", name="nsfw", value="on")
|
||||||
|
input(type="hidden", name="sort", value="relevance")
|
||||||
|
input(type="hidden", name="t", value="all")
|
||||||
|
.sublinks
|
||||||
|
if user_preferences.subbed_subreddits && Array.isArray(user_preferences.subbed_subreddits)
|
||||||
|
a(href="/r/popular") Popular
|
||||||
|
a(href="/r/all") All
|
||||||
|
a(href="/saved") Saved
|
||||||
|
each subreddit in user_preferences.subbed_subreddits
|
||||||
|
a(href="/r/" + subreddit) #{subreddit}
|
||||||
|
else if instance_config.suggested_subreddits && Array.isArray(instance_config.suggested_subreddits)
|
||||||
|
each subreddit in instance_config.suggested_subreddits
|
||||||
|
if subreddit.toLowerCase() === 'saved'
|
||||||
|
a(href="/saved") Saved
|
||||||
|
else
|
||||||
|
a(href="/r/" + subreddit) #{subreddit}
|
||||||
|
include includes/footer.pug
|
||||||
|
|
|
@ -4,8 +4,11 @@ if(user_preferences.theme === 'dark')
|
||||||
link(rel="stylesheet", type="text/css", href="/css/dark.css")
|
link(rel="stylesheet", type="text/css", href="/css/dark.css")
|
||||||
if(user_preferences.theme === 'sepia')
|
if(user_preferences.theme === 'sepia')
|
||||||
link(rel="stylesheet", type="text/css", href="/css/sepia.css")
|
link(rel="stylesheet", type="text/css", href="/css/sepia.css")
|
||||||
|
if(user_preferences.theme === 'nord')
|
||||||
|
link(rel="stylesheet", type="text/css", href="/css/nord.css")
|
||||||
link(rel="stylesheet", type="text/css", href="/css/styles.css")
|
link(rel="stylesheet", type="text/css", href="/css/styles.css")
|
||||||
link(rel="icon", type="image/png", sizes="32x32", href="/favicon.png")
|
link(rel="icon", type="image/png", sizes="32x32", href="/favicon.png")
|
||||||
|
meta(property='og:site_name', content='teddit')
|
||||||
meta(name="viewport", content="width=device-width, initial-scale=1.0")
|
meta(name="viewport", content="width=device-width, initial-scale=1.0")
|
||||||
-
|
-
|
||||||
if(!user_preferences)
|
if(!user_preferences)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
meta(property='og:type', content='website')
|
||||||
|
meta(name='twitter:card', content='summary')
|
||||||
|
include meta_logo.pug
|
|
@ -0,0 +1 @@
|
||||||
|
meta(property='og:description', content='Teddit is a free and open source alternative Reddit front-end focused on privacy. Teddit doesn\'t require you to have JavaScript enabled in your browser.')
|
|
@ -0,0 +1,4 @@
|
||||||
|
meta(property='og:image', content='/logo512.png')
|
||||||
|
meta(property='og:image:width', content='128')
|
||||||
|
meta(property='og:image:height', content='128')
|
||||||
|
meta(property='og:author_name', content='')
|
|
@ -0,0 +1,43 @@
|
||||||
|
meta(property='og:title', content=cleanTitle(post.title) + ' : r/' + subreddit)
|
||||||
|
meta(property='og:description', content='' + post.selftext_preview)
|
||||||
|
meta(property='og:author_name', content='u/' + post.author)
|
||||||
|
if !post.has_media
|
||||||
|
if post.gallery
|
||||||
|
meta(property='twitter:card', content='summary_large_image')
|
||||||
|
meta(property='og:type', content='image')
|
||||||
|
each item in post.gallery_items
|
||||||
|
meta(property='og:image', content='' + item.large)
|
||||||
|
else
|
||||||
|
if post.images
|
||||||
|
meta(property='twitter:card', content='summary_large_image')
|
||||||
|
meta(property='og:type', content='image')
|
||||||
|
meta(property='og:image', content='' + post.images.source)
|
||||||
|
meta(property='og:image:url', content='' + post.images.source)
|
||||||
|
else
|
||||||
|
include meta_logo.pug
|
||||||
|
else
|
||||||
|
if post.media
|
||||||
|
if post.media.not_hosted_in_reddit
|
||||||
|
if post.media.source === 'YouTube'
|
||||||
|
meta(property='twitter:card', content='player')
|
||||||
|
meta(property='og:type', content='video')
|
||||||
|
meta(property='og:video', content='' + post.media.embed_src)
|
||||||
|
else
|
||||||
|
if post.media.source === 'external'
|
||||||
|
if post.images
|
||||||
|
meta(name='twitter:card', content='summary_large_image')
|
||||||
|
meta(property='og:type', content='image')
|
||||||
|
meta(property='og:image', content='' + post.images.source)
|
||||||
|
meta(property='og:image:src', content='' + post.images.source)
|
||||||
|
else
|
||||||
|
meta(name='twitter:card', content='summary_large_image')
|
||||||
|
meta(property='og:type', content='image')
|
||||||
|
meta(property='og:image', content='' + post.media.source)
|
||||||
|
meta(property='og:image:url', content='' + post.media.source)
|
||||||
|
else
|
||||||
|
meta(property='twitter:card', content='player')
|
||||||
|
meta(property='og:type', content='video')
|
||||||
|
meta(property='og:video', content='' + post.media.source)
|
||||||
|
meta(property='og:video:type', content='video/mp4')
|
||||||
|
else
|
||||||
|
include meta_logo.pug
|
|
@ -16,55 +16,10 @@ div#topbar
|
||||||
a(href="/saved") Saved
|
a(href="/saved") Saved
|
||||||
each subreddit in user_preferences.subbed_subreddits
|
each subreddit in user_preferences.subbed_subreddits
|
||||||
a(href="/r/" + subreddit) #{subreddit}
|
a(href="/r/" + subreddit) #{subreddit}
|
||||||
else
|
else if instance_config.suggested_subreddits && Array.isArray(instance_config.suggested_subreddits)
|
||||||
a(href="/r/popular") Popular
|
each subreddit in instance_config.suggested_subreddits
|
||||||
a(href="/r/all") All
|
if subreddit.toLowerCase() === 'saved'
|
||||||
a(href="/saved") Saved
|
a(href="/saved") Saved
|
||||||
a(href="/r/AskReddit") AskReddit
|
else
|
||||||
a(href="/r/pics") pics
|
a(href="/r/" + subreddit) #{subreddit}
|
||||||
a(href="/r/news") news
|
|
||||||
a(href="/r/worldnews") worldnews
|
|
||||||
a(href="/r/funny") funny
|
|
||||||
a(href="/r/tifu") tifu
|
|
||||||
a(href="/r/videos") videos
|
|
||||||
a(href="/r/gaming") gaming
|
|
||||||
a(href="/r/aww") aww
|
|
||||||
a(href="/r/todayilearned") todayilearned
|
|
||||||
a(href="/r/gifs") gifs
|
|
||||||
a(href="/r/Art") Art
|
|
||||||
a(href="/r/explainlikeimfive") explainlikeimfive
|
|
||||||
a(href="/r/movies") movies
|
|
||||||
a(href="/r/Jokes") Jokes
|
|
||||||
a(href="/r/TwoXChromosomes") TwoXChromosomes
|
|
||||||
a(href="/r/mildlyinteresting") mildlyinteresting
|
|
||||||
a(href="/r/LifeProTips") LifeProTips
|
|
||||||
a(href="/r/askscience") askscience
|
|
||||||
a(href="/r/IAmA") IAmA
|
|
||||||
a(href="/r/dataisbeautiful") dataisbeautiful
|
|
||||||
a(href="/r/books") books
|
|
||||||
a(href="/r/science") science
|
|
||||||
a(href="/r/Showerthoughts") Showerthoughts
|
|
||||||
a(href="/r/gadgets") gadgets
|
|
||||||
a(href="/r/Futurology") Futurology
|
|
||||||
a(href="/r/nottheonion") nottheonion
|
|
||||||
a(href="/r/history") history
|
|
||||||
a(href="/r/sports") sports
|
|
||||||
a(href="/r/OldSchoolCool") OldSchoolCool
|
|
||||||
a(href="/r/GetMotivated") GetMotivated
|
|
||||||
a(href="/r/DIY") DIY
|
|
||||||
a(href="/r/photoshopbattles") photoshopbattles
|
|
||||||
a(href="/r/nosleep") nosleep
|
|
||||||
a(href="/r/Music") Music
|
|
||||||
a(href="/r/space") space
|
|
||||||
a(href="/r/food") food
|
|
||||||
a(href="/r/UpliftingNews") UpliftingNews
|
|
||||||
a(href="/r/EarthPorn") EarthPorn
|
|
||||||
a(href="/r/Documentaries") Documentaries
|
|
||||||
a(href="/r/InternetIsBeautiful") InternetIsBeautiful
|
|
||||||
a(href="/r/WritingPrompts") WritingPrompts
|
|
||||||
a(href="/r/creepy") creepy
|
|
||||||
a(href="/r/philosophy") philosophy
|
|
||||||
a(href="/r/announcements") announcements
|
|
||||||
a(href="/r/listentothis") listentothis
|
|
||||||
a(href="/r/blog") blog
|
|
||||||
a(href="/subreddits", id="sr-more-link") more »
|
a(href="/subreddits", id="sr-more-link") more »
|
||||||
|
|
|
@ -2,6 +2,7 @@ doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title #{cleanTitle(post.title)} : #{subreddit}
|
title #{cleanTitle(post.title)} : #{subreddit}
|
||||||
|
include includes/meta_post.pug
|
||||||
include includes/head.pug
|
include includes/head.pug
|
||||||
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
||||||
include includes/topbar.pug
|
include includes/topbar.pug
|
||||||
|
@ -46,6 +47,12 @@ html
|
||||||
video_muted = false
|
video_muted = false
|
||||||
}
|
}
|
||||||
.info
|
.info
|
||||||
|
if user_preferences.show_upvotes === 'false'
|
||||||
|
style.
|
||||||
|
.comment .meta .ups, #post .score, #user .upvotes {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.score
|
.score
|
||||||
div.arrow
|
div.arrow
|
||||||
span #{kFormatter(post.ups)}
|
span #{kFormatter(post.ups)}
|
||||||
|
@ -80,6 +87,7 @@ html
|
||||||
a(href="/unsave/" + post.id + "/?rk=" + redis_key + "&b=" + back_url + "") unsave
|
a(href="/unsave/" + post.id + "/?rk=" + redis_key + "&b=" + back_url + "") unsave
|
||||||
else
|
else
|
||||||
a(href="/save/" + post.id + "/?rk=" + redis_key + "&b=" + back_url + "") save
|
a(href="/save/" + post.id + "/?rk=" + redis_key + "&b=" + back_url + "") save
|
||||||
|
a(href=("https://www.reddit.com" + back_url) target="_blank" title="Open in Reddit (new tab)" style="margin-left: 10px") [R↗]
|
||||||
if post.crosspost.is_crosspost === true
|
if post.crosspost.is_crosspost === true
|
||||||
.crosspost
|
.crosspost
|
||||||
.title
|
.title
|
||||||
|
@ -130,12 +138,19 @@ html
|
||||||
if post.gallery
|
if post.gallery
|
||||||
.gallery
|
.gallery
|
||||||
each item in post.gallery_items
|
each item in post.gallery_items
|
||||||
.item
|
if user_preferences.show_large_gallery_images == 'true'
|
||||||
div
|
.item.large
|
||||||
a(href="" + item.large + "", target="_blank")
|
a(href="" + item.large + "", target="_blank")
|
||||||
img(src=""+ item.thumbnail +"", alt="")
|
img(src="" + item.large + "", title="" + item.caption + "")
|
||||||
a(href="" + item.source + "", target="_blank", class="source-link")
|
if item.caption
|
||||||
small source
|
span.caption !{item.caption}
|
||||||
|
else
|
||||||
|
.item
|
||||||
|
div
|
||||||
|
a(href="" + item.large + "", target="_blank")
|
||||||
|
img(src=""+ item.thumbnail +"", alt="")
|
||||||
|
a(href="" + item.source + "", target="_blank", class="source-link")
|
||||||
|
small source
|
||||||
if post.images
|
if post.images
|
||||||
.image
|
.image
|
||||||
a(href="" + post.images.source + "")
|
a(href="" + post.images.source + "")
|
||||||
|
@ -163,10 +178,11 @@ html
|
||||||
a(href="" + post.media.embed_src + "", target="_blank", rel="noopener noreferrer")
|
a(href="" + post.media.embed_src + "", target="_blank", rel="noopener noreferrer")
|
||||||
img(src="" + post.images.source + "", alt="")
|
img(src="" + post.images.source + "", alt="")
|
||||||
if !post.media.embed_src.startsWith("https://twitter.com")
|
if !post.media.embed_src.startsWith("https://twitter.com")
|
||||||
p
|
details(class="source-details")
|
||||||
| source:
|
summary Source
|
||||||
a(href="" + post.media.embed_src + "", target="_blank", rel="noopener noreferrer")
|
p
|
||||||
p(class="source-url") #{post.media.embed_src}
|
a(href="" + post.media.embed_src + "", target="_blank", rel="noopener noreferrer")
|
||||||
|
p(class="source-url") #{post.media.embed_src}
|
||||||
else
|
else
|
||||||
.video
|
.video
|
||||||
a(href="" + post.media.source + "")
|
a(href="" + post.media.source + "")
|
||||||
|
|
|
@ -2,6 +2,9 @@ doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title preferences - teddit
|
title preferences - teddit
|
||||||
|
meta(property='og:title', content='preferences - teddit')
|
||||||
|
include includes/meta_default.pug
|
||||||
|
include includes/meta_description.pug
|
||||||
include includes/head.pug
|
include includes/head.pug
|
||||||
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
||||||
include includes/topbar.pug
|
include includes/topbar.pug
|
||||||
|
@ -11,23 +14,29 @@ html
|
||||||
form(action="/saveprefs", method="POST")
|
form(action="/saveprefs", method="POST")
|
||||||
legend Privacy
|
legend Privacy
|
||||||
.setting
|
.setting
|
||||||
label(for="domain_twitter") Replace Twitter links with Nitter (blank to disable):
|
label(for="domain_twitter") Replace Twitter links with <a href="https://github.com/zedeus/nitter">Nitter</a> (blank to disable):
|
||||||
if(user_preferences.domain_twitter != '' && typeof(user_preferences.domain_twitter) != 'undefined')
|
if(user_preferences.domain_twitter != '' && typeof(user_preferences.domain_twitter) != 'undefined')
|
||||||
input(type="text", name="domain_twitter", id="domain_twitter", value="" + user_preferences.domain_twitter + "", placeholder="e.g. nitter.net")
|
input(type="text", name="domain_twitter", id="domain_twitter", value="" + user_preferences.domain_twitter + "", placeholder="e.g. nitter.net")
|
||||||
else
|
else
|
||||||
input(type="text", name="domain_twitter", id="domain_twitter", placeholder="e.g. nitter.net")
|
input(type="text", name="domain_twitter", id="domain_twitter", placeholder="e.g. nitter.net")
|
||||||
.setting
|
.setting
|
||||||
label(for="domain_youtube") Replace YouTube links with Invidious (blank to disable):
|
label(for="domain_youtube") Replace YouTube links with <a href="https://github.com/iv-org/invidious">Invidious</a>/<a href="https://github.com/TeamPiped/Piped">Piped</a> (blank to disable):
|
||||||
if(user_preferences.domain_youtube != '' && typeof(user_preferences.domain_youtube) != 'undefined')
|
if(user_preferences.domain_youtube != '' && typeof(user_preferences.domain_youtube) != 'undefined')
|
||||||
input(type="text", name="domain_youtube", id="domain_youtube", value="" + user_preferences.domain_youtube + "", placeholder="e.g. invidious.site")
|
input(type="text", name="domain_youtube", id="domain_youtube", value="" + user_preferences.domain_youtube + "", placeholder="e.g. invidious.site")
|
||||||
else
|
else
|
||||||
input(type="text", name="domain_youtube", id="domain_youtube", placeholder="e.g. invidious.site")
|
input(type="text", name="domain_youtube", id="domain_youtube", placeholder="e.g. invidious.site")
|
||||||
.setting
|
.setting
|
||||||
label(for="domain_instagram") Replace Instagram links with Bibliogram (blank to disable):
|
label(for="domain_quora") Replace Quora links with <a href="https://codeberg.org/zyachel/quetre">Quetre</a> (blank to disable):
|
||||||
if(user_preferences.domain_instagram != '' && typeof(user_preferences.domain_instagram) != 'undefined')
|
if(user_preferences.domain_quora != '' && typeof(user_preferences.domain_quora) != 'undefined')
|
||||||
input(type="text", name="domain_instagram", id="domain_instagram", value="" + user_preferences.domain_instagram + "", placeholder="e.g. bibliogram.art")
|
input(type="text", name="domain_quora", id="domain_quora", value="" + user_preferences.domain_quora + "", placeholder="e.g. quetre.iket.me")
|
||||||
else
|
else
|
||||||
input(type="text", name="domain_instagram", id="domain_instagram", placeholder="e.g. bibliogram.art")
|
input(type="text", name="domain_quora", id="domain_quora", placeholder="e.g. quetre.iket.me")
|
||||||
|
.setting
|
||||||
|
label(for="domain_imgur") Replace Imgur links with <a href="https://codeberg.org/video-prize-ranch/rimgo">Rimgo</a> (blank to disable):
|
||||||
|
if(user_preferences.domain_imgur != '' && typeof(user_preferences.domain_imgur) != 'undefined')
|
||||||
|
input(type="text", name="domain_imgur", id="domain_imgur", value="" + user_preferences.domain_imgur + "", placeholder="e.g. rimgo.bcow.xyz")
|
||||||
|
else
|
||||||
|
input(type="text", name="domain_imgur", id="domain_imgur", placeholder="e.g. rimgo.bcow.xyz")
|
||||||
legend Display
|
legend Display
|
||||||
.setting
|
.setting
|
||||||
label(for="theme") Theme:
|
label(for="theme") Theme:
|
||||||
|
@ -37,21 +46,37 @@ html
|
||||||
option(value="white") White
|
option(value="white") White
|
||||||
option(value="dark") Dark
|
option(value="dark") Dark
|
||||||
option(value="sepia") Sepia
|
option(value="sepia") Sepia
|
||||||
if(user_preferences.theme == 'white')
|
option(value="nord") Nord
|
||||||
|
else if(user_preferences.theme == 'white')
|
||||||
option(value="auto") Auto
|
option(value="auto") Auto
|
||||||
option(value="white", selected="selected") White
|
option(value="white", selected="selected") White
|
||||||
option(value="dark") Dark
|
option(value="dark") Dark
|
||||||
option(value="sepia") Sepia
|
option(value="sepia") Sepia
|
||||||
if(user_preferences.theme === 'dark')
|
option(value="nord") Nord
|
||||||
|
else if(user_preferences.theme === 'dark')
|
||||||
option(value="auto") Auto
|
option(value="auto") Auto
|
||||||
option(value="white") White
|
option(value="white") White
|
||||||
option(value="dark", selected="selected") Dark
|
option(value="dark", selected="selected") Dark
|
||||||
option(value="sepia") Sepia
|
option(value="sepia") Sepia
|
||||||
if(user_preferences.theme === 'sepia')
|
option(value="nord") Nord
|
||||||
|
else if(user_preferences.theme === 'sepia')
|
||||||
option(value="auto") Auto
|
option(value="auto") Auto
|
||||||
option(value="white") White
|
option(value="white") White
|
||||||
option(value="dark") Dark
|
option(value="dark") Dark
|
||||||
option(value="sepia", selected="selected") Sepia
|
option(value="sepia", selected="selected") Sepia
|
||||||
|
option(value="nord") Nord
|
||||||
|
else if(user_preferences.theme === 'nord')
|
||||||
|
option(value="auto") Auto
|
||||||
|
option(value="white") White
|
||||||
|
option(value="dark") Dark
|
||||||
|
option(value="sepia") Sepia
|
||||||
|
option(value="nord", selected="selected") Nord
|
||||||
|
else
|
||||||
|
option(value="auto") Auto
|
||||||
|
option(value="white") White
|
||||||
|
option(value="dark") Dark
|
||||||
|
option(value="sepia") Sepia
|
||||||
|
option(value="nord") Nord
|
||||||
.setting
|
.setting
|
||||||
label(for="flairs") Show flairs:
|
label(for="flairs") Show flairs:
|
||||||
if(!user_preferences.flairs || user_preferences.flairs == 'true')
|
if(!user_preferences.flairs || user_preferences.flairs == 'true')
|
||||||
|
@ -96,6 +121,29 @@ html
|
||||||
input(type="checkbox", name="show_upvoted_percentage", id="show_upvoted_percentage", checked="checked")
|
input(type="checkbox", name="show_upvoted_percentage", id="show_upvoted_percentage", checked="checked")
|
||||||
else
|
else
|
||||||
input(type="checkbox", name="show_upvoted_percentage", id="show_upvoted_percentage")
|
input(type="checkbox", name="show_upvoted_percentage", id="show_upvoted_percentage")
|
||||||
|
.setting
|
||||||
|
label(for="show_upvotes") Show upvotes:
|
||||||
|
if(!user_preferences.show_upvotes || user_preferences.show_upvotes == 'true')
|
||||||
|
input(type="checkbox", name="show_upvotes", id="show_upvotes", checked="checked")
|
||||||
|
else
|
||||||
|
input(type="checkbox", name="show_upvotes", id="show_upvotes")
|
||||||
|
.setting
|
||||||
|
label(for="prefer_frontpage") Prefer reddit-style frontpage as homepage:
|
||||||
|
if ((!instance_config.clean_homepage && !user_preferences.prefer_frontpage) || user_preferences.prefer_frontpage == 'true')
|
||||||
|
input(type="checkbox", name="prefer_frontpage", id="prefer_frontpage", checked="checked")
|
||||||
|
else
|
||||||
|
input(type="checkbox", name="prefer_frontpage", id="prefer_frontpage")
|
||||||
|
.setting
|
||||||
|
label(for="default_comment_sort") Default comment sorting:
|
||||||
|
select(id="default_comment_sort", name="default_comment_sort")
|
||||||
|
-
|
||||||
|
let default_comment_sort_html = ''
|
||||||
|
let user_default_sort = user_preferences.default_comment_sort || 'best'
|
||||||
|
|
||||||
|
for(let key of comment_sort_values) {
|
||||||
|
default_comment_sort_html += `<option value="${key}" ${(user_default_sort == key ? "selected" : "")}>${key == 'qa' ? 'Q&A' : key}</option>`
|
||||||
|
}
|
||||||
|
!= default_comment_sort_html
|
||||||
legend Media
|
legend Media
|
||||||
.setting
|
.setting
|
||||||
label(for="videos_muted") Mute videos by default:
|
label(for="videos_muted") Mute videos by default:
|
||||||
|
@ -111,6 +159,12 @@ html
|
||||||
input(type="checkbox", name="videos_muted", id="videos_muted", checked="checked")
|
input(type="checkbox", name="videos_muted", id="videos_muted", checked="checked")
|
||||||
else
|
else
|
||||||
input(type="checkbox", name="videos_muted", id="videos_muted")
|
input(type="checkbox", name="videos_muted", id="videos_muted")
|
||||||
|
.setting
|
||||||
|
label(for="show_large_gallery_images") Show large gallery images with captions:
|
||||||
|
if (user_preferences.show_large_gallery_images == 'true')
|
||||||
|
input(type="checkbox", name="show_large_gallery_images", id="show_large_gallery_images", checked="checked")
|
||||||
|
else
|
||||||
|
input(type="checkbox", name="show_large_gallery_images", id="show_large_gallery_images")
|
||||||
small(class="notice") Preferences are stored client-side using cookies without any personal information.
|
small(class="notice") Preferences are stored client-side using cookies without any personal information.
|
||||||
br
|
br
|
||||||
input(type="submit", value="Save preferences")
|
input(type="submit", value="Save preferences")
|
||||||
|
|
|
@ -2,6 +2,9 @@ doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title privacy policy - teddit
|
title privacy policy - teddit
|
||||||
|
meta(property='og:title', content='privacy policy - teddit')
|
||||||
|
include includes/meta_default.pug
|
||||||
|
include includes/meta_description.pug
|
||||||
include includes/head.pug
|
include includes/head.pug
|
||||||
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
||||||
include includes/topbar.pug
|
include includes/topbar.pug
|
||||||
|
|
|
@ -2,6 +2,9 @@ doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title saved
|
title saved
|
||||||
|
meta(property='og:title', content='saved - teddit')
|
||||||
|
include includes/meta_default.pug
|
||||||
|
include includes/meta_description.pug
|
||||||
include includes/head.pug
|
include includes/head.pug
|
||||||
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
||||||
include includes/topbar.pug
|
include includes/topbar.pug
|
||||||
|
|
|
@ -3,8 +3,12 @@ html
|
||||||
head
|
head
|
||||||
if no_query
|
if no_query
|
||||||
title search teddit
|
title search teddit
|
||||||
|
meta(property='og:title', content='search - teddit')
|
||||||
else
|
else
|
||||||
title search results for #{q}
|
title search results for #{q}
|
||||||
|
meta(property='og:title', content='search results for ' + q + ' - teddit')
|
||||||
|
include includes/meta_default.pug
|
||||||
|
include includes/meta_description.pug
|
||||||
include includes/head.pug
|
include includes/head.pug
|
||||||
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
||||||
include includes/topbar.pug
|
include includes/topbar.pug
|
||||||
|
@ -140,8 +144,8 @@ html
|
||||||
include components/link.pug
|
include components/link.pug
|
||||||
if json.before || json.after
|
if json.before || json.after
|
||||||
.view-more-links
|
.view-more-links
|
||||||
if json.before && !subreddit_front
|
if json.before
|
||||||
a(href="?q=" + q + "&restrict_sr=" + restrict_sr + "&nsfw=" + nsfw + "&before=" + json.before + "") ‹ prev
|
a(href="?q=" + q + "&restrict_sr=" + restrict_sr + "&nsfw=" + nsfw + "&before=" + json.before + "" + (sortby === "new" && sortby ? "&" : "&sort=" + sortby + "&") + (!past ? "" : "t=" + past)) ‹ prev
|
||||||
if json.after
|
if json.after
|
||||||
a(href="?q=" + q + "&restrict_sr=" + restrict_sr + "&nsfw=" + nsfw + "&after=" + json.after + "") next ›
|
a(href="?q=" + q + "&restrict_sr=" + restrict_sr + "&nsfw=" + nsfw + "&after=" + json.after + "" + (sortby === "new" && sortby ? "&" : "&sort=" + sortby + "&") + (!past ? "" : "t=" + past)) next ›
|
||||||
include includes/footer.pug
|
include includes/footer.pug
|
||||||
|
|
|
@ -2,6 +2,10 @@ doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title /r/#{subreddit}
|
title /r/#{subreddit}
|
||||||
|
meta(property='og:title', content='/r/' + subreddit)
|
||||||
|
if subreddit_about
|
||||||
|
meta(property='og:description', content='' + unescape(subreddit_about.public_description_html, user_preferences))
|
||||||
|
include includes/meta_default.pug
|
||||||
include includes/head.pug
|
include includes/head.pug
|
||||||
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
||||||
include includes/topbar.pug
|
include includes/topbar.pug
|
||||||
|
|
|
@ -2,6 +2,8 @@ doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title wiki /r/#{subreddit}
|
title wiki /r/#{subreddit}
|
||||||
|
meta(property='og:title', content='wiki /r/' + subreddit)
|
||||||
|
include includes/meta_default.pug
|
||||||
include includes/head.pug
|
include includes/head.pug
|
||||||
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
||||||
include includes/topbar.pug
|
include includes/topbar.pug
|
||||||
|
|
|
@ -2,6 +2,9 @@ doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title subreddits - explore
|
title subreddits - explore
|
||||||
|
meta(property='og:title', content='explore subreddits - teddit')
|
||||||
|
include includes/meta_default.pug
|
||||||
|
include includes/meta_description.pug
|
||||||
include includes/head.pug
|
include includes/head.pug
|
||||||
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
||||||
include includes/topbar.pug
|
include includes/topbar.pug
|
||||||
|
|
|
@ -2,6 +2,8 @@ doctype html
|
||||||
html
|
html
|
||||||
head
|
head
|
||||||
title overview for #{data.username}
|
title overview for #{data.username}
|
||||||
|
meta(property='og:title', content='u/' + data.username + ' - teddit')
|
||||||
|
include includes/meta_default.pug
|
||||||
include includes/head.pug
|
include includes/head.pug
|
||||||
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
body(class=""+ (user_preferences.theme === 'auto' ? 'dark' : user_preferences.theme) + "")
|
||||||
include includes/topbar.pug
|
include includes/topbar.pug
|
||||||
|
|
Loading…
Reference in New Issue