From e11a2acd3ff05f922dda1489668a106ffe698f9f Mon Sep 17 00:00:00 2001 From: Jubbeart Date: Tue, 6 Feb 2018 04:07:30 +0100 Subject: [PATCH] Now works with subreddits! --- README.md | 21 ++++---- production/letsencrypt.conf | 2 +- production/nginx-basic | 7 ++- production/nginx-ssl | 9 +++- src/js/App.js | 6 ++- src/js/api/pushshift/index.js | 74 ++++++++++++++++++----------- src/js/api/reddit/index.js | 2 +- src/js/api/reddit/thread.js | 15 ++++++ src/js/api/removeddit/index.js | 8 ++++ src/js/components/Comment.js | 4 +- src/js/components/CommentSection.js | 5 ++ src/js/pages/Subreddit.js | 57 +++++++++++++++++++++- src/js/pages/Thread.js | 8 +++- src/sass/subreddit.sass | 17 ++++++- src/sass/thread.sass | 1 + 15 files changed, 185 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index c4eb14c..59b1178 100644 --- a/README.md +++ b/README.md @@ -15,22 +15,24 @@ npm start Visit http://localhost:8080 and make sure the site is running. Subreddits and the banned subreddit list will not work unless you also set up a backend. This might change in the future if I decide to open up my backend on removeddit.com/api. Contact me if you want this feature and we can discuss it. -# Production +# Production (basic setup) **THIS WILL BE UPDATED LATER WHEN THE PROJECT IN REWRITTEN** Using [Ubuntu 16.04](http://releases.ubuntu.com/16.04/) and [nginx](https://www.nginx.com/resources/wiki/) ``` -sudo git clone https://github.com/JubbeArt/removeddit.git /var/www/removeddit +cd /srv +sudo git clone https://github.com/JubbeArt/removeddit.git /srv/removeddit/site +chown -R www-data:www-data /srv/removeddit sudo apt install -y nginx -sudo cp /var/www/removeddit/server-config/basic /etc/nginx/sites-available/default +sudo cp /srv/removeddit/site/production/nginx-basic /etc/nginx/sites-available/default ``` Create a reddit app [here](https://www.reddit.com/prefs/apps/), select **installed app**. For "redirect url" it doesn't really matter in this case, you can pick `http://localhost`. Copy the **client ID** for your app set it as a variable in `id.js`, e.g. with ``` -sudo nano /var/www/removeddit/static/js/id.js +sudo nano /srv/removeddit/site/..../id.js # Insert with ctrl-shift-v # Save with ctrl-o, exit with ctrl-x ``` @@ -57,7 +59,7 @@ In the same file you also want to change `gzip on` to `gzip off` (read more [her ## Nginx server config Copy the ssl config and create a soft link. Create folder for logs and also remove the default config ``` -sudo cp /var/www/removeddit/server-config/ssl /etc/nginx/sites-available/removeddit.com +sudo cp /srv/removeddit/site/production/nginx-ssl /etc/nginx/sites-available/removeddit.com sudo ln -s /etc/nginx/sites-available/removeddit.com /etc/nginx/sites-enabled/removeddit.com sudo mkdir /var/log/nginx/removeddit sudo rm /etc/nginx/sites-enabled/default @@ -77,13 +79,12 @@ sudo apt install -y python-certbot-nginx Copy the Let's Encrypt config file for our site ``` sudo mkdir /etc/letsencrypt/configs -cp /var/www/removeddit/server-config/letsencrypt.conf /etc/letsencrypt/configs/removeddit.com.conf +cp /srv/removeddit/site/production/letsencrypt.conf /etc/letsencrypt/configs/removeddit.com.conf ``` In this config file change the domains and the email address for your own. The emails tells you when the certificates are close to expiring. -This is when the webmasters start praying to God, for only He can deside the fate of the certbot. -Forgive me Father, for I have committed. +Pray to God and do this ``` sudo certbot --config /etc/letsencrypt/configs/removeddit.com.conf certonly ``` @@ -108,6 +109,6 @@ Add the following lines at the bottom 30 4 * * * certbot renew --post-hook "systemctl reload nginx" ``` -Then just restart nginx and that should do it! +Then just restart nginx and that should do it! -This guide was mostly written for myself, you learn a shitton writing guides, highly recommended. Hopefully you learned something too. \ No newline at end of file +This guide was mostly written for myself, you learn a shitton writing guides, highly recommended. Hopefully you learned something too. diff --git a/production/letsencrypt.conf b/production/letsencrypt.conf index 58c6c71..7b4ecb2 100644 --- a/production/letsencrypt.conf +++ b/production/letsencrypt.conf @@ -6,4 +6,4 @@ email = removeddit@gmail.com rsa-key-size = 2048 text = True authenticator = webroot -webroot-path = /var/www/removeddit/ \ No newline at end of file +webroot-path = /srv/removeddit/site/ \ No newline at end of file diff --git a/production/nginx-basic b/production/nginx-basic index 843eb9e..00bb3ec 100644 --- a/production/nginx-basic +++ b/production/nginx-basic @@ -2,12 +2,17 @@ server { listen 80 default_server; listen [::]:80 default_server; - root /var/www/removeddit; + root /srv/removeddit/site; index index.html; server_name _; error_page 404 /index.html + #location /api/ { + # include uwsgi_params; + # uwsgi_pass unix:/srv/removeddit-api/socket/uwsgi.sock; + #} + location / { try_files $uri $uri/ /index.html =404; } diff --git a/production/nginx-ssl b/production/nginx-ssl index 652e471..c9d4ee4 100644 --- a/production/nginx-ssl +++ b/production/nginx-ssl @@ -2,7 +2,7 @@ server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; - root /var/www/removeddit; + root /srv/removeddit/site; index index.html; server_name removeddit.com www.removeddit.com; @@ -16,6 +16,11 @@ server { location / { try_files $uri $uri/ /index.html =404; } + + #location /api/ { + # include uwsgi_params; + # uwsgi_pass unix:/srv/removeddit-api/socket/uwsgi.sock; + #} } server { @@ -30,4 +35,4 @@ server { location ~ /.well-known { allow all; } -} \ No newline at end of file +} diff --git a/src/js/App.js b/src/js/App.js index 2848cec..9a83f74 100644 --- a/src/js/App.js +++ b/src/js/App.js @@ -14,10 +14,12 @@ export default () => (
- + - + + +
diff --git a/src/js/api/pushshift/index.js b/src/js/api/pushshift/index.js index 5e6a5d7..4019408 100644 --- a/src/js/api/pushshift/index.js +++ b/src/js/api/pushshift/index.js @@ -24,34 +24,52 @@ export const getPost = threadID => { ) } -export const getComments = threadID => { - const elasticQuery = { - query: { - match: { - link_id: toBase10(threadID), - }, - }, - size: 10000, - _source: [ - 'author', 'body', 'created_utc', 'parent_id', 'score', - ], - } +export const getComments = threadID => ( + fetch(`https://api.pushshift.io/reddit/comment/search?link_id=${threadID}&limit=10000`) + .then(json) + .then(data => data.data) + .then(comments => { + comments.forEach(comment => { + comment.link_id = comment.link_id.split('_')[1] + comment.parent_id = comment.parent_id.split('_')[1] + }) + return comments + }) +) - return ( - fetch(commentURL + JSON.stringify(elasticQuery)) - .then(json) - .then(jsonData => jsonData.hits.hits) - .then(comments => comments.map(comment => { - comment._source.id = toBase36(comment._id) +// export const getComments = threadID => { +// const elasticQuery = { +// query: { +// match: { +// link_id: toBase10(threadID), +// }, +// }, +// size: 10000, +// // _source: [ +// // 'author', 'body', 'created_utc', 'parent_id', 'score', 'subreddit', 'link_id', +// // ], +// } - // Missing parent id === direct reply to thread - if (!comment._source.parent_id) { - comment._source.parent_id = threadID - } else { - comment._source.parent_id = toBase36(comment._source.parent_id) - } +// return ( +// fetch(commentURL + JSON.stringify(elasticQuery)) +// .then(json) +// .then(jsonData => jsonData.hits.hits) +// .then(comments => comments.map(comment => { +// comment._source.id = toBase36(comment._id) +// comment._source.link_id = toBase36(comment._source.link_id) - return comment._source - })) - ) -} +// // Missing parent id === direct reply to thread +// if (!comment._source.parent_id) { +// comment._source.parent_id = threadID +// } else { +// comment._source.parent_id = toBase36(comment._source.parent_id) +// } + +// if (comment._source.id === 'dmrxgic') { +// console.log(JSON.stringify(comment._source)) +// } + +// return comment._source +// })) +// ) +// } diff --git a/src/js/api/reddit/index.js b/src/js/api/reddit/index.js index 180eab3..2c6d727 100644 --- a/src/js/api/reddit/index.js +++ b/src/js/api/reddit/index.js @@ -1,2 +1,2 @@ -export { getPost } from './thread' +export { getPost, getThreads } from './thread' export { getComments } from './comment' diff --git a/src/js/api/reddit/thread.js b/src/js/api/reddit/thread.js index 421b001..45a057c 100644 --- a/src/js/api/reddit/thread.js +++ b/src/js/api/reddit/thread.js @@ -38,3 +38,18 @@ export const getThread = (subreddit, threadID, commentID = '') => { }) ) } + + +export const getThreads = threadIDs => { + const threadString = threadIDs.map(id => `t3_${id}`).join() + + return ( + getAuth() + .then(auth => fetch(`https://oauth.reddit.com/api/info?id=${threadString}`, auth)) + .then(json) + .then(response => { + const threads = response.data.children + return threads.map(threadData => threadData.data) + }) + ) +} diff --git a/src/js/api/removeddit/index.js b/src/js/api/removeddit/index.js index e69de29..fcecb72 100644 --- a/src/js/api/removeddit/index.js +++ b/src/js/api/removeddit/index.js @@ -0,0 +1,8 @@ +import { json } from 'utils' + +const baseURL = 'http://localhost:9000/api' + +export const getRemovedThreadIDs = (subreddit = '', page = 1) => ( + fetch(`${baseURL}/threads?subreddit=${subreddit}&page=${page - 1}`) + .then(json) +) diff --git a/src/js/components/Comment.js b/src/js/components/Comment.js index 865093e..e93d827 100644 --- a/src/js/components/Comment.js +++ b/src/js/components/Comment.js @@ -1,5 +1,5 @@ import React from 'react' -import { prettyScore, prettyDate, parse, sortComments } from 'utils' +import { prettyScore, prettyDate, parse } from 'utils' const Comment = (props) => { let commentStyle = 'comment ' @@ -13,7 +13,7 @@ const Comment = (props) => { } const innerHTML = (props.body === '[removed]' && props.removed) ? '

[removed too quickly to be archived]

' : parse(props.body) - const permalink = `/r/${props.subreddit}/comments/${props.threadID}/_/${props.id}/` + const permalink = `/r/${props.subreddit}/comments/${props.link_id}/_/${props.id}/` return (
diff --git a/src/js/components/CommentSection.js b/src/js/components/CommentSection.js index b161004..5c833c4 100644 --- a/src/js/components/CommentSection.js +++ b/src/js/components/CommentSection.js @@ -50,6 +50,11 @@ const unflatten = (comments, root, removed, deleted) => { } }) + if (lookup[root] !== undefined) { + lookup[root].replies = commentTree + return [lookup[root]] + } + return commentTree } diff --git a/src/js/pages/Subreddit.js b/src/js/pages/Subreddit.js index b357c42..a5ece53 100644 --- a/src/js/pages/Subreddit.js +++ b/src/js/pages/Subreddit.js @@ -1,14 +1,67 @@ import React from 'react' +import { getRemovedThreadIDs } from 'api/removeddit' +import { getThreads } from 'api/reddit' +import Post from 'components/Post' + +const displaySubreddit = props => { + const subreddit = props.match.params.subreddit + if (subreddit === undefined) { + return 'all' + } + return subreddit +} + +const getSubredditForAPI = props => { + const subreddit = props.match.params.subreddit + if (subreddit === undefined) { + return '' + } else if (subreddit.toLowerCase() === 'all') { + return '' + } + return subreddit.toLowerCase() +} + export default class Subreddit extends React.Component { constructor(props) { super(props) this.state = { - + threads: [], } } + + componentDidMount() { + const subreddit = getSubredditForAPI(this.props) + getRemovedThreadIDs(subreddit) + .then(threadIDs => getThreads(threadIDs)) + .then(threads => { + threads.forEach(thread => { + thread.removed = true + thread.selftext = '' + }) + this.setState({ threads }) + }) + } + render() { - return

Subreddit

+ const subreddit = `/r/${displaySubreddit(this.props)}` + + return ( + +
+ {subreddit} + + reddit + + ceddit +
+ { + this.state.threads.map(thread => ( + + )) + } +
+ ) } } diff --git a/src/js/pages/Thread.js b/src/js/pages/Thread.js index 03da0e5..9b2b76e 100644 --- a/src/js/pages/Thread.js +++ b/src/js/pages/Thread.js @@ -95,13 +95,19 @@ export default class Thread extends React.Component { } render() { + let root = this.state.post.id + + if (this.props.match.params.commentID !== undefined) { + root = this.props.match.params.commentID + } + return (
{ !this.state.loadingComments &&