mirror of
https://github.com/gurnec/removeddit.git
synced 2026-03-11 08:54:27 +00:00
Started linting the code with eslint
This commit is contained in:
parent
7374366726
commit
1af9e59644
24 changed files with 1726 additions and 719 deletions
48
.eslintrc.json
Normal file
48
.eslintrc.json
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"extends": "airbnb",
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"rules": {
|
||||
"semi": "off",
|
||||
"arrow-parens": "off",
|
||||
"no-unused-vars": "warn",
|
||||
"react/jsx-filename-extension": "off",
|
||||
"react/prop-types": "off",
|
||||
"jsx-quotes": "off",
|
||||
"no-script-url": "off",
|
||||
"max-len": "warn",
|
||||
"import/no-extraneous-dependencies": "off",
|
||||
"import/no-unresolved": "off",
|
||||
"import/extensions": "off",
|
||||
"react/no-danger": "off",
|
||||
"no-underscore-dangle": "off",
|
||||
"no-param-reassign": "warn",
|
||||
"jsx-a11y/anchor-has-content": "off",
|
||||
"jsx-a11y/anchor-is-valid": [
|
||||
"error",
|
||||
{
|
||||
"components": [ "Link" ],
|
||||
"specialLink": [ "to", "hrefLeft", "hrefRight" ],
|
||||
"aspects": [ "noHref", "invalidHref", "preferButton" ]
|
||||
}
|
||||
],
|
||||
|
||||
"no-plusplus": [
|
||||
"error",
|
||||
{
|
||||
"allowForLoopAfterthoughts": true
|
||||
}
|
||||
],
|
||||
"comma-dangle": [
|
||||
"error",
|
||||
{
|
||||
"arrays": "always-multiline",
|
||||
"objects": "always-multiline",
|
||||
"imports": "always-multiline",
|
||||
"exports": "always-multiline",
|
||||
"functions": "ignore"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
963
package-lock.json
generated
963
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -24,7 +24,8 @@
|
|||
"build": "webpack --config webpack.dev.js",
|
||||
"build-prod": "webpack --config webpack.prod.js",
|
||||
"clean": "rm -r node_modules && rm package-lock.json",
|
||||
"gh-pages": "npm run build-prod && node publish.js"
|
||||
"gh-pages": "npm run build-prod && node publish.js",
|
||||
"es": "eslint --init"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "^7.0.0-beta.37",
|
||||
|
|
@ -42,10 +43,16 @@
|
|||
"@babel/plugin-transform-async-to-generator": "^7.0.0-beta.37",
|
||||
"@babel/preset-es2015": "^7.0.0-beta.37",
|
||||
"@babel/preset-react": "^7.0.0-beta.37",
|
||||
"babel-eslint": "^8.2.1",
|
||||
"babel-loader": "^8.0.0-beta.0",
|
||||
"clean-webpack-plugin": "^0.1.17",
|
||||
"copy-webpack-plugin": "^4.3.1",
|
||||
"css-loader": "^0.28.8",
|
||||
"eslint": "^4.15.0",
|
||||
"eslint-config-airbnb": "^16.1.0",
|
||||
"eslint-plugin-import": "^2.8.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.0.3",
|
||||
"eslint-plugin-react": "^7.5.1",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"gh-pages": "^1.1.0",
|
||||
"html-loader": "^0.5.4",
|
||||
|
|
|
|||
|
|
@ -1,43 +1,25 @@
|
|||
import React from 'react'
|
||||
import {
|
||||
BrowserRouter,
|
||||
Switch,
|
||||
Route,
|
||||
IndexRoute
|
||||
BrowserRouter,
|
||||
Switch,
|
||||
Route,
|
||||
} from 'react-router-dom'
|
||||
|
||||
import Menu from 'components/Menu'
|
||||
import {About, Thread, Subreddit} from 'pages'
|
||||
import { About, Thread, Subreddit } from 'pages'
|
||||
|
||||
class App extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
export default props => (
|
||||
<BrowserRouter basename={__dirname}>
|
||||
<>
|
||||
<Menu status={props.status} />
|
||||
<div className='main'>
|
||||
<Switch>
|
||||
<Route exact path='/' component={Thread} />
|
||||
<Route path='/about' component={About} />
|
||||
<Route path='/r/:subreddit/comments/:threadID' component={Thread} />
|
||||
</Switch>
|
||||
</div>
|
||||
</>
|
||||
</BrowserRouter>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
handleStatusChange(text, image) {
|
||||
this.setState({
|
||||
statusText: text,
|
||||
statusImage: image
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<BrowserRouter basename={__dirname}>
|
||||
<>
|
||||
<Menu status={this.props.status}/>
|
||||
<div className='main'>
|
||||
<Switch>
|
||||
<Route exact path='/' component={Thread} />
|
||||
<Route path='/about' component={About}/>
|
||||
<Route path='/r/:subreddit/comments/:threadID' component={Thread}/>
|
||||
</Switch>
|
||||
</div>
|
||||
</>
|
||||
</BrowserRouter>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default App
|
||||
|
|
@ -2,27 +2,36 @@ import React from 'react'
|
|||
import { prettyScore, prettyDate, parse } from 'utils'
|
||||
|
||||
export default (props) => {
|
||||
const commentCss = 'comment comment-' + (props.removed ? 'removed' : (props.deleted ? 'deleted' : (props.depth % 2 == 0 ? 'even' : 'odd')));
|
||||
const innerHTML = (props.body === '[removed]' && props.removed) ? '<p>[removed too quickly to be archived]</p>' : parse(comment.body)
|
||||
const permalink = `/r/${props.subreddit}/comments/${props.threadID}/_/${props.id}/`
|
||||
let commentStyle = 'comment comment-'
|
||||
|
||||
return (
|
||||
<div id={props.id} className={commentCss}>
|
||||
<div className='comment-head'>
|
||||
<a href='javascript:void(0)' className='author'>[–]</a>
|
||||
<a href={`https://www.reddit.com/user/${props.author}`} className='author comment-author'>
|
||||
{props.author}
|
||||
{props.deleted && ' (deleted by user)'}
|
||||
</a>
|
||||
<span className='comment-score'>{prettyScore(props.score)} point{(comment.score !== 1) && 's'}</span>
|
||||
<span className='comment-time'>{prettyDate(props.created_utc)}</span>
|
||||
</div>
|
||||
<div className='comment-body' dangerouslySetInnerHTML={{__html: innerHTML}}></div>
|
||||
<div className='comment-links'>
|
||||
<a href={permalink}>permalink</a>
|
||||
<a href={`https://www.reddit.com${permalink}`}>reddit</a>
|
||||
<a href={`https://snew.github.io${permalink}`}>ceddit</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (props.removed) {
|
||||
commentStyle += 'removed'
|
||||
} else if (props.deleted) {
|
||||
commentStyle += 'deleted'
|
||||
} else {
|
||||
commentStyle += props.depth % 2 === 0 ? 'even' : 'odd'
|
||||
}
|
||||
|
||||
const innerHTML = (props.body === '[removed]' && props.removed) ? '<p>[removed too quickly to be archived]</p>' : parse(props.body)
|
||||
const permalink = `/r/${props.subreddit}/comments/${props.threadID}/_/${props.id}/`
|
||||
|
||||
return (
|
||||
<div id={props.id} className={commentStyle}>
|
||||
<div className='comment-head'>
|
||||
<button onClick={false} className='author'>[–]</button>
|
||||
<a href={`https://www.reddit.com/user/${props.author}`} className='author comment-author'>
|
||||
{props.author}
|
||||
{props.deleted && ' (deleted by user)'}
|
||||
</a>
|
||||
<span className='comment-score'>{prettyScore(props.score)} point{(props.score !== 1) && 's'}</span>
|
||||
<span className='comment-time'>{prettyDate(props.created_utc)}</span>
|
||||
</div>
|
||||
<div className='comment-body' dangerouslySetInnerHTML={{ __html: innerHTML }} />
|
||||
<div className='comment-links'>
|
||||
<a href={permalink}>permalink</a>
|
||||
<a href={`https://www.reddit.com${permalink}`}>reddit</a>
|
||||
<a href={`https://snew.github.io${permalink}`}>ceddit</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import React from 'react'
|
||||
|
||||
export default (props) => {
|
||||
return (
|
||||
<div id={props.root}>
|
||||
{props.children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default (props) => (
|
||||
<div id={props.root}>
|
||||
{props.children}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,20 +1,18 @@
|
|||
import React from 'react'
|
||||
import {Link} from 'react-router-dom'
|
||||
import { Link } from 'react-router-dom'
|
||||
import StatusBox from 'components/StatusBox'
|
||||
|
||||
export default (props) => {
|
||||
return (
|
||||
<header>
|
||||
<div id='header'>
|
||||
<h1>
|
||||
<Link to='/'>Removeddit</Link>
|
||||
</h1>
|
||||
<nav>
|
||||
<Link to='/r/all'>/r/all</Link>
|
||||
<Link to='/about/'>about</Link>
|
||||
</nav>
|
||||
</div>
|
||||
<StatusBox />
|
||||
</header>
|
||||
)
|
||||
}
|
||||
export default () => (
|
||||
<header>
|
||||
<div id='header'>
|
||||
<h1>
|
||||
<Link to='/'>Removeddit</Link>
|
||||
</h1>
|
||||
<nav>
|
||||
<Link to='/r/all'>/r/all</Link>
|
||||
<Link to='/about/'>about</Link>
|
||||
</nav>
|
||||
</div>
|
||||
<StatusBox />
|
||||
</header>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,26 +1,22 @@
|
|||
import React from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import { setStatusLoading, setStatusSuccess, setStatusError } from 'state'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
class StatusBox extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div id='status'>
|
||||
{this.props.text &&
|
||||
<p id='status-text'>{this.props.text}</p>}
|
||||
{this.props.image &&
|
||||
<img id='status-image' src={this.props.image}/>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
class StatusBox extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div id='status'>
|
||||
{this.props.text &&
|
||||
<p id='status-text'>{this.props.text}</p>}
|
||||
{this.props.image &&
|
||||
<img id='status-image' src={this.props.image} />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
text: state.status.text,
|
||||
image: state.status.image
|
||||
const mapStateToProps = state => ({
|
||||
text: state.status.text,
|
||||
image: state.status.image,
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(StatusBox)
|
||||
export default connect(mapStateToProps)(StatusBox)
|
||||
|
|
|
|||
|
|
@ -1,22 +1,24 @@
|
|||
import React from 'react'
|
||||
|
||||
export default (props) => {
|
||||
let pageination = <></>
|
||||
let pageination = <div></div>
|
||||
|
||||
for(var i = start; i <= end; i++) {
|
||||
if(currentPage === i) {
|
||||
pageination += <span>{i}</span>
|
||||
} else {
|
||||
pageination += <a href={`${props.url+i}`}>{i}</a>
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div id="pagination">
|
||||
Page:
|
||||
{start > 1 &&
|
||||
<><a href={`${props.url+1}`}>1</a>
|
||||
<span> ...</span></>}
|
||||
{pageination}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
for (let i = props.start; i <= props.end; i++) {
|
||||
if (props.currentPage === i) {
|
||||
pageination += <span>{i}</span>
|
||||
} else {
|
||||
pageination += <a href={`${props.url + i}`}>{i}</a>
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div id="pagination">
|
||||
Page:
|
||||
{props.start > 1 &&
|
||||
<>
|
||||
<a href={`${props.url + 1}`}>1</a>
|
||||
<span> ...</span>
|
||||
</>}
|
||||
{pageination}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
import React from 'react'
|
||||
|
||||
export default (props) => {
|
||||
const isSelected = time => props.time == time
|
||||
const isSelected = time => props.time === time
|
||||
|
||||
return (
|
||||
<div className='subreddit-info'>
|
||||
top post of <a href={`https://www.reddit.com/r/${props.subreddit}`}>/r/{subreddit}</a> from:
|
||||
{/* <select onchange='Vars.reload(this)'> */}
|
||||
<select>
|
||||
<option value='hour' selected={isSelected('hour')} >past hour</option>
|
||||
<option value='12hour' selected={isSelected('12hour')} >past 12 hours</option>
|
||||
<option value='day' selected={isSelected('day')} >past day</option>
|
||||
<option value='week' selected={isSelected('week')} >past week</option>
|
||||
<option value='month' selected={isSelected('month')} >past month</option>
|
||||
<option value='6month' selected={isSelected('6month')} >past 6 months</option>
|
||||
<option value='year' selected={isSelected('year')} >past year</option>
|
||||
<option value='all' selected={isSelected('all')} >all time</option>
|
||||
</select>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className='subreddit-info'>
|
||||
top post of <a href={`https://www.reddit.com/r/${props.subreddit}`}>/r/{props.subreddit}</a> from:
|
||||
{/* <select onchange='Vars.reload(this)'> */}
|
||||
<select>
|
||||
<option value='hour' selected={isSelected('hour')}>past hour</option>
|
||||
<option value='12hour' selected={isSelected('12hour')}>past 12 hours</option>
|
||||
<option value='day' selected={isSelected('day')}>past day</option>
|
||||
<option value='week' selected={isSelected('week')}>past week</option>
|
||||
<option value='month' selected={isSelected('month')}>past month</option>
|
||||
<option value='6month' selected={isSelected('6month')}>past 6 months</option>
|
||||
<option value='year' selected={isSelected('year')}>past year</option>
|
||||
<option value='all' selected={isSelected('all')}>all time</option>
|
||||
</select>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,62 +1,62 @@
|
|||
import React from 'react'
|
||||
import {prettyScore, prettyDate, parse, redditThumbnails} from 'utils'
|
||||
import { prettyScore, prettyDate, parse, redditThumbnails } from 'utils'
|
||||
|
||||
export default (props) => {
|
||||
if(!props.title) {
|
||||
return <div></div>
|
||||
}
|
||||
if (!props.title) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
const url = props.url.replace('https://www.reddit.com', '')
|
||||
const userLink = props.author !== '[deleted]' ? `https://www.reddit.com/user/${props.author}` : ''
|
||||
const url = props.url.replace('https://www.reddit.com', '')
|
||||
const userLink = props.author !== '[deleted]' ? `https://www.reddit.com/user/${props.author}` : ''
|
||||
|
||||
let thumbnail
|
||||
const thumbnailWidth = props.thumbnail_width ? props.thumbnail_width * 0.5 : 70
|
||||
const thumbnailHeight = props.thumbnail_height ? props.thumbnail_height * 0.5 : 70
|
||||
let thumbnail
|
||||
const thumbnailWidth = props.thumbnail_width ? props.thumbnail_width * 0.5 : 70
|
||||
const thumbnailHeight = props.thumbnail_height ? props.thumbnail_height * 0.5 : 70
|
||||
|
||||
if(redditThumbnails.includes(props.thumbnail)) {
|
||||
thumbnail = <a href={url} className={`thumbnail thumbnail-${props.thumbnail}`}></a>
|
||||
} else if(props.thumbnail !== ''){
|
||||
thumbnail = (
|
||||
<a href={url}>
|
||||
<img className='thumbnail' src={props.thumbnail} width={thumbnailWidth} height={thumbnailHeight}/>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
if (redditThumbnails.includes(props.thumbnail)) {
|
||||
thumbnail = <a href={url} className={`thumbnail thumbnail-${props.thumbnail}`} />
|
||||
} else if (props.thumbnail !== '') {
|
||||
thumbnail = (
|
||||
<a href={url}>
|
||||
<img className='thumbnail' src={props.thumbnail} width={thumbnailWidth} height={thumbnailHeight} alt='Thumbnail' />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='thread'>
|
||||
{props.position &&
|
||||
<span className='post-rank'>{props.position}</span>}
|
||||
<div className='thread-score-box'>
|
||||
<div className='vote upvote'></div>
|
||||
<div className='thread-score'>{prettyScore(props.score)}</div>
|
||||
<div className='vote downvote'></div>
|
||||
</div>
|
||||
{thumbnail}
|
||||
<div className='thread-content'>
|
||||
<a className='thread-title' href={url}>{props.title}</a>
|
||||
{props.link_flair_text &&
|
||||
<span className='link-flair'>{props.link_flair_text}</span>}
|
||||
<span className='domain'>({props.domain})</span>
|
||||
<div className='thread-info'>
|
||||
submitted <span className='thread-time'>{prettyDate(props.created_utc)}</span> by
|
||||
<a className='thread-author author' href={userLink}>{props.author}</a>
|
||||
to <a className='subreddit-link author' href={`/r/${props.subreddit}`}>/r/{props.subreddit}</a>
|
||||
</div>
|
||||
{props.selftext &&
|
||||
<div className='thread-selftext user-text' dangerouslySetInnerHTML={{__html: parse(props.selftext)}}></div>}
|
||||
<div className='total-comments'>
|
||||
<a className='grey-link' href={props.permalink}>
|
||||
<b>{props.num_comments} comments</b>
|
||||
</a>
|
||||
<a className='grey-link' href={`https://www.reddit.com${props.permalink}`}>
|
||||
<b>reddit</b>
|
||||
</a>
|
||||
<a className='grey-link' href={`https://snew.github.io${props.permalink}`}>
|
||||
<b>ceddit</b>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className='thread'>
|
||||
{props.position &&
|
||||
<span className='post-rank'>{props.position}</span>}
|
||||
<div className='thread-score-box'>
|
||||
<div className='vote upvote' />
|
||||
<div className='thread-score'>{prettyScore(props.score)}</div>
|
||||
<div className='vote downvote' />
|
||||
</div>
|
||||
{thumbnail}
|
||||
<div className='thread-content'>
|
||||
<a className='thread-title' href={url}>{props.title}</a>
|
||||
{props.link_flair_text &&
|
||||
<span className='link-flair'>{props.link_flair_text}</span>}
|
||||
<span className='domain'>({props.domain})</span>
|
||||
<div className='thread-info'>
|
||||
submitted <span className='thread-time'>{prettyDate(props.created_utc)}</span> by
|
||||
<a className='thread-author author' href={userLink}>{props.author}</a>
|
||||
to <a className='subreddit-link author' href={`/r/${props.subreddit}`}>/r/{props.subreddit}</a>
|
||||
</div>
|
||||
{props.selftext &&
|
||||
<div className='thread-selftext user-text' dangerouslySetInnerHTML={{ __html: parse(props.selftext) }} />}
|
||||
<div className='total-comments'>
|
||||
<a className='grey-link' href={props.permalink}>
|
||||
<b>{props.num_comments} comments</b>
|
||||
</a>
|
||||
<a className='grey-link' href={`https://www.reddit.com${props.permalink}`}>
|
||||
<b>reddit</b>
|
||||
</a>
|
||||
<a className='grey-link' href={`https://snew.github.io${props.permalink}`}>
|
||||
<b>ceddit</b>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import React from 'react'
|
||||
|
||||
export default (props) => {
|
||||
return (
|
||||
<>
|
||||
<div id='comment-info'>
|
||||
removed comments: {props.removedComments}/${props.totalComments} ({(100 * removedComments / totalComments).toFixed(1)}%)
|
||||
</div>
|
||||
<div id='comment-sort'>sorted by: top</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default (props) => (
|
||||
<>
|
||||
<div id='comment-info'>
|
||||
removed comments: {props.removedComments}/${props.totalComments}
|
||||
({ ((100 * props.removedComments) / props.totalComments).toFixed(1) }%)
|
||||
</div>
|
||||
<div id='comment-sort'>sorted by: top</div>
|
||||
</>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,19 +1,20 @@
|
|||
import '../sass/main.sass'
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { Provider } from 'react-redux'
|
||||
import { store } from 'state'
|
||||
import App from './App'
|
||||
import App from 'App'
|
||||
|
||||
import '../sass/main.sass'
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>,
|
||||
document.getElementById("app")
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>,
|
||||
document.getElementById('app')
|
||||
)
|
||||
|
||||
// import {setStatusLoading} from 'state'
|
||||
// store.dispatch(setStatusLoading('hi'))
|
||||
|
||||
// import { getThread } from 'reddit'
|
||||
// getThread('videos', '7q4vxi')
|
||||
// getThread('videos', '7q4vxi')
|
||||
|
|
|
|||
|
|
@ -1,40 +1,48 @@
|
|||
import React from 'react'
|
||||
|
||||
export default (props) => {
|
||||
return (
|
||||
<div id='main'>
|
||||
<div id='main-box'>
|
||||
<h2 className='about'>About</h2>
|
||||
<p>Display <b className='removed' title='Removed by mods'>removed</b> (by mods) and <b className='deleted' title='Deleted by users'>deleted</b> (by users) comments/threads from Reddit.</p>
|
||||
<p>
|
||||
<b>Usage</b>: Drag this bookmarklet
|
||||
<a className='bookmarklet' href="javascript: document.location = document.URL.replace('reddit.com','removeddit.com');">Removeddit</a>
|
||||
to your bookmark bar and use it to get from reddit to removeddit.
|
||||
<br/><br/>
|
||||
Alternatively you can manually replace the <i>reddit</i> in the URL to <i>removeddit</i>.
|
||||
<br/>
|
||||
E.g. <a href='/r/TwoXChromosomes/comments/6z1hch/'>https://www.removeddit.com/r/TwoXChromosomes/comments/6z1hch/</a>
|
||||
</p>
|
||||
<p>
|
||||
Created by <a href='https://github.com/JubbeArt/'>Jesper Wrang</a> and uses <a href='https://pushshift.io/'>Jason Baumgartner</a> service for getting removed comments.
|
||||
</p>
|
||||
<h2 className='todo'>TODO</h2>
|
||||
<ul>
|
||||
<li>Collapsing comments</li>
|
||||
<li>Get removed selftext of thread</li>
|
||||
<li>Subreddits!</li>
|
||||
<li>Maybe for specific users </li>
|
||||
</ul>
|
||||
<h2 className='contact'>Links/Contact</h2>
|
||||
<p style={{marginBottom:'8px'}}>For feedback and bug reports:</p>
|
||||
<ul>
|
||||
<li>email: removeddit (at) gmail.com</li>
|
||||
<li>reddit: <a href='https://www.reddit.com/user/Jubbeart/'>/u/JubbeArt</a></li>
|
||||
</ul>
|
||||
<p>
|
||||
<a href='https://github.com/JubbeArt/removeddit'>Code on Github.</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default props => (
|
||||
<div id='main'>
|
||||
<div id='main-box'>
|
||||
<h2 className='about'>About</h2>
|
||||
<p>
|
||||
Display
|
||||
<b className='removed' title='Removed by mods'>removed</b>
|
||||
(by mods) and
|
||||
<b className='deleted' title='Deleted by users'>deleted</b>
|
||||
(by users) comments/threads from Reddit.
|
||||
</p>
|
||||
<p>
|
||||
<b>Usage</b>: Drag this bookmarklet
|
||||
<a className='bookmarklet' href="javascript: document.location = document.URL.replace('reddit.com','removeddit.com');">
|
||||
Removeddit
|
||||
</a>
|
||||
to your bookmark bar and use it to get from reddit to removeddit.
|
||||
<br /><br />
|
||||
Alternatively you can manually replace the <i>reddit</i> in the URL to <i>removeddit</i>.
|
||||
<br />
|
||||
E.g. <a href='/r/TwoXChromosomes/comments/6z1hch/'>https://www.removeddit.com/r/TwoXChromosomes/comments/6z1hch/</a>
|
||||
</p>
|
||||
<p>
|
||||
Created by
|
||||
<a href='https://github.com/JubbeArt/'>Jesper Wrang</a> and uses
|
||||
<a href='https://pushshift.io/'>Jason Baumgartner</a> service for getting removed comments.
|
||||
</p>
|
||||
<h2 className='todo'>TODO</h2>
|
||||
<ul>
|
||||
<li>Collapsing comments</li>
|
||||
<li>Get removed selftext of thread</li>
|
||||
<li>Subreddits!</li>
|
||||
<li>Maybe for specific users </li>
|
||||
</ul>
|
||||
<h2 className='contact'>Links/Contact</h2>
|
||||
<p style={{ marginBottom: '8px' }}>For feedback and bug reports:</p>
|
||||
<ul>
|
||||
<li>email: removeddit (at) gmail.com</li>
|
||||
<li>reddit: <a href='https://www.reddit.com/user/Jubbeart/'>/u/JubbeArt</a></li>
|
||||
</ul>
|
||||
<p>
|
||||
<a href='https://github.com/JubbeArt/removeddit'>Code on Github.</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,78 +1,78 @@
|
|||
|
||||
// var radioInput = function(name, displayNames, values) {
|
||||
// var inputs = "";
|
||||
|
||||
// for(var i = 0, len = displayNames.length; i < len; i++){
|
||||
// inputs += '<span class="radioButton"'+ (Vars.lookup[name] === values[i] ? ' style="background: #239f2b; color:#fff"':'')+'>';
|
||||
// inputs += '<input type="radio" id="'+name+i+'" name="'+name+'" onchange="CSS.radio(this)"';
|
||||
// inputs += 'value="'+values[i]+'" '+(Vars.lookup[name] === values[i] ? ' checked "':'')+' >';
|
||||
// inputs += '<label for="'+name+i+'">'+displayNames[i]+'</label></span>';
|
||||
// }
|
||||
// return inputs;
|
||||
// };
|
||||
// var radioInput = function(name, displayNames, values) {
|
||||
// var inputs = "";
|
||||
|
||||
// for(var i = 0, len = displayNames.length; i < len; i++){
|
||||
// inputs += '<span class="radioButton"'+ (Vars.lookup[name] === values[i] ? ' style="background: #239f2b; color:#fff"':'')+'>';
|
||||
// inputs += '<input type="radio" id="'+name+i+'" name="'+name+'" onchange="CSS.radio(this)"';
|
||||
// inputs += 'value="'+values[i]+'" '+(Vars.lookup[name] === values[i] ? ' checked "':'')+' >';
|
||||
// inputs += '<label for="'+name+i+'">'+displayNames[i]+'</label></span>';
|
||||
// }
|
||||
// return inputs;
|
||||
// };
|
||||
|
||||
// var textInput = function(name){
|
||||
// return '<input type="text" name="'+name+'" id="'+name+'" value="'+Vars.get(name)+'">';
|
||||
// };
|
||||
// var textInput = function(name){
|
||||
// return '<input type="text" name="'+name+'" id="'+name+'" value="'+Vars.get(name)+'">';
|
||||
// };
|
||||
|
||||
// var label = function(name, display) {
|
||||
// return '<label for="'+name+'">'+display+': </label>';
|
||||
// };
|
||||
// var label = function(name, display) {
|
||||
// return '<label for="'+name+'">'+display+': </label>';
|
||||
// };
|
||||
|
||||
// var inputRow = function(text, input) {
|
||||
// return '<div class="search-row"><span class="search-left">'+text+'</span><span>'+input+"</span></div>";
|
||||
// };
|
||||
// var inputRow = function(text, input) {
|
||||
// return '<div class="search-row"><span class="search-left">'+text+'</span><span>'+input+"</span></div>";
|
||||
// };
|
||||
|
||||
// var selectTime = function() {
|
||||
// var values = ["hour", "12hour", "day", "week", "month", "6month", "year", "all"];
|
||||
// var display = ["past hour", "past 12 hours", "past day", "past week", "past month", "past 6 months", "past year", "all time"];
|
||||
// var html = '<select name="time" id="time">';
|
||||
// var selectTime = function() {
|
||||
// var values = ["hour", "12hour", "day", "week", "month", "6month", "year", "all"];
|
||||
// var display = ["past hour", "past 12 hours", "past day", "past week", "past month", "past 6 months", "past year", "all time"];
|
||||
// var html = '<select name="time" id="time">';
|
||||
|
||||
// for(var i = 0, len = values.length; i < len; i++) {
|
||||
// html += '<option value="'+values[i]+'"' + ((Vars.get("time") === values[i]) ? " selected" : '')+'>'+display[i]+'</option>';
|
||||
// }
|
||||
// for(var i = 0, len = values.length; i < len; i++) {
|
||||
// html += '<option value="'+values[i]+'"' + ((Vars.get("time") === values[i]) ? " selected" : '')+'>'+display[i]+'</option>';
|
||||
// }
|
||||
|
||||
// return html + "</select>";
|
||||
// };
|
||||
// return html + "</select>";
|
||||
// };
|
||||
|
||||
// var select = function(name, display, values){
|
||||
// var html = '<select name="'+name+'" id="'+name+'">';
|
||||
|
||||
// for(var i = 0, len = values.length; i < len; i++) {
|
||||
// html += '<option value="'+values[i]+'"' + ((Vars.get(name) === values[i]) ? " selected" : '')+'>'+display[i]+'</option>';
|
||||
// }
|
||||
// var select = function(name, display, values){
|
||||
// var html = '<select name="'+name+'" id="'+name+'">';
|
||||
|
||||
// for(var i = 0, len = values.length; i < len; i++) {
|
||||
// html += '<option value="'+values[i]+'"' + ((Vars.get(name) === values[i]) ? " selected" : '')+'>'+display[i]+'</option>';
|
||||
// }
|
||||
|
||||
// return html + "</select>";
|
||||
// };
|
||||
// return html + "</select>";
|
||||
// };
|
||||
|
||||
// return {
|
||||
// createSearch: function(){
|
||||
// var searchBox = document.createElement("div");
|
||||
// searchBox.id = "main-box";
|
||||
// searchBox.className = "search-box";
|
||||
// /*
|
||||
// Comments:
|
||||
// text (body) string
|
||||
// title (title) string
|
||||
// subreddit (subreddit) string
|
||||
// author (author) string
|
||||
// over_18 (over_18) sfw,nsfw,both *
|
||||
// locked (locked) bool *
|
||||
// between (after/before) "date"
|
||||
// sort (sort) asc,desc
|
||||
// */
|
||||
// var html = inputRow('Im looking for: ', radioInput("thread", ["Thread","Comment"], ["true", "false"]));
|
||||
// html += inputRow(label("text", "Text"), textInput("text"));
|
||||
// html += inputRow(label("title","Title"), textInput("title"));
|
||||
// html += inputRow(label("subreddit", "Subreddit"), textInput("subreddit"));
|
||||
// html += inputRow(label("author", "Author"), textInput("author"));
|
||||
// html += inputRow("Over 18: ", radioInput("over_18", ["Both","NSFW","SFW"], ["both","nsfw","sfw"]));
|
||||
// html += inputRow("Locked: ", radioInput("locked", ["Both","True", "False"], ["both","true","false"]));
|
||||
// html += inputRow("Removed: ", select("removed", ["Removed and non-removed", "Only removed", "Only deleted"], ["all", "removed", "deleted"]));
|
||||
// html += inputRow("From:", selectTime());
|
||||
// html += inputRow("Sort: ", select("sort", ["Highest score","Lowest score","Newest","Oldest"], ["score_desc","score_asc","time_desc","time_asc"]));
|
||||
// html += '<input type="button" value="'+(showAdvanced?'Hide':'Show')+' advanced">';
|
||||
// html += '<input type="submit" value="Search">';
|
||||
// searchBox.innerHTML = html;
|
||||
|
||||
// mainDiv.appendChild(searchBox);
|
||||
// createSearch: function(){
|
||||
// var searchBox = document.createElement("div");
|
||||
// searchBox.id = "main-box";
|
||||
// searchBox.className = "search-box";
|
||||
// /*
|
||||
// Comments:
|
||||
// text (body) string
|
||||
// title (title) string
|
||||
// subreddit (subreddit) string
|
||||
// author (author) string
|
||||
// over_18 (over_18) sfw,nsfw,both *
|
||||
// locked (locked) bool *
|
||||
// between (after/before) "date"
|
||||
// sort (sort) asc,desc
|
||||
// */
|
||||
// var html = inputRow('Im looking for: ', radioInput("thread", ["Thread","Comment"], ["true", "false"]));
|
||||
// html += inputRow(label("text", "Text"), textInput("text"));
|
||||
// html += inputRow(label("title","Title"), textInput("title"));
|
||||
// html += inputRow(label("subreddit", "Subreddit"), textInput("subreddit"));
|
||||
// html += inputRow(label("author", "Author"), textInput("author"));
|
||||
// html += inputRow("Over 18: ", radioInput("over_18", ["Both","NSFW","SFW"], ["both","nsfw","sfw"]));
|
||||
// html += inputRow("Locked: ", radioInput("locked", ["Both","True", "False"], ["both","true","false"]));
|
||||
// html += inputRow("Removed: ", select("removed", ["Removed and non-removed", "Only removed", "Only deleted"], ["all", "removed", "deleted"]));
|
||||
// html += inputRow("From:", selectTime());
|
||||
// html += inputRow("Sort: ", select("sort", ["Highest score","Lowest score","Newest","Oldest"], ["score_desc","score_asc","time_desc","time_asc"]));
|
||||
// html += '<input type="button" value="'+(showAdvanced?'Hide':'Show')+' advanced">';
|
||||
// html += '<input type="submit" value="Search">';
|
||||
// searchBox.innerHTML = html;
|
||||
|
||||
// mainDiv.appendChild(searchBox);
|
||||
|
|
@ -1,8 +1,14 @@
|
|||
import React from 'react'
|
||||
|
||||
export default class Subreddit extends React.Component {
|
||||
render() {
|
||||
return <h1>Subreddit</h1>
|
||||
}
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
}
|
||||
this.state = {
|
||||
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return <h1>Subreddit</h1>
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,32 +3,31 @@ import ThreadHead from 'components/ThreadHead'
|
|||
import { getThread } from 'reddit'
|
||||
|
||||
export default class Thread extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
thread: {}
|
||||
}
|
||||
}
|
||||
this.state = {
|
||||
thread: {},
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
getThread(this.props.match.params.subreddit, this.props.match.params.threadID)
|
||||
.then(thread => {
|
||||
this.setState({thread})
|
||||
|
||||
// check if thread is deleted
|
||||
//if(thread.)
|
||||
return thread
|
||||
})
|
||||
|
||||
}
|
||||
componentDidMount() {
|
||||
getThread(this.props.match.params.subreddit, this.props.match.params.threadID)
|
||||
.then(thread => {
|
||||
this.setState({ thread })
|
||||
|
||||
render () {
|
||||
return (
|
||||
<>
|
||||
<ThreadHead {...this.state.thread} />
|
||||
<h1>lol</h1>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
// check if thread is deleted
|
||||
// if(thread.)
|
||||
return thread
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<ThreadHead {...this.state.thread} />
|
||||
<h1>lol</h1>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
export {default as About} from './About'
|
||||
export {default as Subreddit} from './Subreddit'
|
||||
export {default as Thread} from './Thread'
|
||||
export { default as About } from './About'
|
||||
export { default as Subreddit } from './Subreddit'
|
||||
export { default as Thread } from './Thread'
|
||||
|
|
|
|||
|
|
@ -1,37 +1,38 @@
|
|||
const baseURL = 'https://elastic.pushshift.io'
|
||||
const submissionURL = baseURL + '/rs/submissions/_search?source='
|
||||
const commentURL = baseURL + '/rc/comments/_search?source='
|
||||
const commentIDsURL = 'https://api.pushshift.io/reddit/submission/comment_ids/'
|
||||
|
||||
import { json, toBase10, toBase36 } from 'utils'
|
||||
|
||||
export const getCommentIDs = threadID => {
|
||||
return fetch(commentIDsURL + threadID)
|
||||
.then(json)
|
||||
.then(results => {
|
||||
return results.data
|
||||
})
|
||||
}
|
||||
const baseURL = 'https://elastic.pushshift.io'
|
||||
const submissionURL = `${baseURL}/rs/submissions/_search?source=`
|
||||
const commentURL = `${baseURL}/rc/comments/_search?source=`
|
||||
const commentIDsURL = 'https://api.pushshift.io/reddit/submission/comment_ids/'
|
||||
|
||||
|
||||
export const getCommentIDs = threadID => (
|
||||
fetch(commentIDsURL + threadID)
|
||||
.then(json)
|
||||
.then(results => results.data)
|
||||
)
|
||||
|
||||
export const test = threadID => {
|
||||
const elasticQuery = {
|
||||
query: {
|
||||
term: {
|
||||
link_id: toBase10(threadID)
|
||||
}
|
||||
},
|
||||
size: 10000,
|
||||
}
|
||||
const elasticQuery = {
|
||||
query: {
|
||||
term: {
|
||||
link_id: toBase10(threadID),
|
||||
},
|
||||
},
|
||||
size: 10000,
|
||||
}
|
||||
|
||||
return fetch(commentURL + JSON.stringify(elasticQuery))
|
||||
.then(json)
|
||||
.then(results => {
|
||||
results.hits.hits.map(result => {
|
||||
result._source.link_id = toBase36(result._source.link_id )
|
||||
result._source.parent_id = toBase36(result._source.parent_id)
|
||||
result._source.id = toBase36(result._id)
|
||||
return (
|
||||
fetch(commentURL + JSON.stringify(elasticQuery))
|
||||
.then(json)
|
||||
.then(results => {
|
||||
results.hits.hits.map(result => {
|
||||
result._source.link_id = toBase36(result._source.link_id)
|
||||
result._source.parent_id = toBase36(result._source.parent_id)
|
||||
result._source.id = toBase36(result._id)
|
||||
|
||||
return result._source
|
||||
})
|
||||
})
|
||||
}
|
||||
return result._source
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
// Change this to your own client ID: https://www.reddit.com/prefs/apps
|
||||
// The app NEEDS TO BE an installed app and NOT a web apps
|
||||
export default 'YSidAws9twqCZg'
|
||||
export default 'YSidAws9twqCZg'
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
import { json } from 'utils'
|
||||
import clientID from './clientID'
|
||||
import {json} from 'utils'
|
||||
|
||||
|
||||
// Reddit API
|
||||
|
||||
// Headers for general api calls
|
||||
const init = {
|
||||
headers: {
|
||||
'Authorization': ''
|
||||
}
|
||||
headers: {
|
||||
Authorization: '',
|
||||
},
|
||||
}
|
||||
|
||||
let hasToken = false
|
||||
|
|
@ -16,194 +15,195 @@ let baseCommentTree = {}
|
|||
|
||||
// Headers for getting reddit api token
|
||||
const tokenInit = {
|
||||
headers: {
|
||||
'Authorization': 'Basic ' + btoa(clientID + ':'),
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
|
||||
},
|
||||
method: 'POST',
|
||||
body: `grant_type=${encodeURIComponent('https://oauth.reddit.com/grants/installed_client')}&device_id=DO_NOT_TRACK_THIS_DEVICE`
|
||||
headers: {
|
||||
Authorization: `Basic ${btoa(clientID + ':')}`,
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
|
||||
},
|
||||
method: 'POST',
|
||||
body: `grant_type=${encodeURIComponent('https://oauth.reddit.com/grants/installed_client')}&device_id=DO_NOT_TRACK_THIS_DEVICE`
|
||||
}
|
||||
|
||||
const fetchToken = () => {
|
||||
if(hasToken) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
if (hasToken) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
return fetch('https://www.reddit.com/api/v1/access_token', tokenInit)
|
||||
.then(json)
|
||||
.then(json => {
|
||||
init.headers.Authorization = 'bearer ' + json.access_token;
|
||||
hasToken = true
|
||||
})
|
||||
return (
|
||||
fetch('https://www.reddit.com/api/v1/access_token', tokenInit)
|
||||
.then(json)
|
||||
.then(jsonData => {
|
||||
init.headers.Authorization = `bearer ${jsonData.access_token}`;
|
||||
hasToken = true
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export const getThread = (subreddit, threadID) => {
|
||||
return fetchToken()
|
||||
.then(() => fetch(`https://oauth.reddit.com/r/${subreddit}/comments/${threadID}`, init))
|
||||
.then(json)
|
||||
.then(results => {
|
||||
// Save the comments for later
|
||||
baseCommentTree = results[1].data.children
|
||||
export const getThread = (subreddit, threadID) => (
|
||||
fetchToken()
|
||||
.then(() => fetch(`https://oauth.reddit.com/r/${subreddit}/comments/${threadID}`, init))
|
||||
.then(json)
|
||||
.then(results => {
|
||||
// Save the comments for later
|
||||
baseCommentTree = results[1].data.children
|
||||
|
||||
// Return the thread
|
||||
return results[0].data.children[0].data
|
||||
})
|
||||
}
|
||||
// Return the thread
|
||||
return results[0].data.children[0].data
|
||||
})
|
||||
)
|
||||
|
||||
export const getCommentIDs = () => {
|
||||
|
||||
|
||||
}
|
||||
|
||||
// HandleIDs.normal(thread);
|
||||
// return HandleIDs.morechildren()
|
||||
// .catch(function(error){
|
||||
// return Promise.reject("Could not get comments from Reddit (moreChildren)");
|
||||
// });
|
||||
// })
|
||||
// .then(function(){
|
||||
// return Promise.all(_.map(_.uniq(Comments.countinuethread), function(id) {
|
||||
// return fetch(URLs.thread+"/_/"+id.split("_")[1], Reddit.init)
|
||||
// .then(Fetch2.json)
|
||||
// .catch(function(error){ return Promise.reject("Could not get comments from Reddit (continueThisThread)") })
|
||||
// }))
|
||||
// .catch(function(error){
|
||||
// return Promise.reject("Could not get comments from Reddit (continueThisThread)");
|
||||
// });
|
||||
// })
|
||||
// .then(function(smallerThreads){
|
||||
// _.forEach(smallerThreads, function(thread){
|
||||
// HandleIDs.normal(thread);
|
||||
// })
|
||||
// Status.loading("Getting removed comments...");
|
||||
// HandleIDs.removed();
|
||||
// ThreadHTML.createCommentInfo(Comments.removed.length);
|
||||
// return Fetch2.multiple(URLs.format(URLs.pushshiftComments, Comments.removed), null, "data")
|
||||
// .catch(function(error){
|
||||
// return Promise.reject("Could not get removed comments");
|
||||
// });
|
||||
// })
|
||||
// .then(function(removedComments){
|
||||
// Status.loading("Generating comments...");
|
||||
// return Comments.generate(removedComments);
|
||||
// })
|
||||
// .then(function(){
|
||||
// Status.success();
|
||||
// })
|
||||
// .catch(function(error) {
|
||||
// if(_.includes(_.toLower(error), "error")) {
|
||||
// Status.error(error);
|
||||
// } else {
|
||||
// Status.error("Error: "+error);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// HandleIDs.normal(thread);
|
||||
// return HandleIDs.morechildren()
|
||||
// .catch(function(error){
|
||||
// return Promise.reject("Could not get comments from Reddit (moreChildren)");
|
||||
// });
|
||||
// })
|
||||
// .then(function(){
|
||||
// return Promise.all(_.map(_.uniq(Comments.countinuethread), function(id) {
|
||||
// return fetch(URLs.thread+"/_/"+id.split("_")[1], Reddit.init)
|
||||
// .then(Fetch2.json)
|
||||
// .catch(function(error){ return Promise.reject("Could not get comments from Reddit (continueThisThread)") })
|
||||
// }))
|
||||
// .catch(function(error){
|
||||
// return Promise.reject("Could not get comments from Reddit (continueThisThread)");
|
||||
// });
|
||||
// })
|
||||
// .then(function(smallerThreads){
|
||||
// _.forEach(smallerThreads, function(thread){
|
||||
// HandleIDs.normal(thread);
|
||||
// })
|
||||
// Status.loading("Getting removed comments...");
|
||||
// HandleIDs.removed();
|
||||
// ThreadHTML.createCommentInfo(Comments.removed.length);
|
||||
// return Fetch2.multiple(URLs.format(URLs.pushshiftComments, Comments.removed), null, "data")
|
||||
// .catch(function(error){
|
||||
// return Promise.reject("Could not get removed comments");
|
||||
// });
|
||||
// })
|
||||
// .then(function(removedComments){
|
||||
// Status.loading("Generating comments...");
|
||||
// return Comments.generate(removedComments);
|
||||
// })
|
||||
// .then(function(){
|
||||
// Status.success();
|
||||
// })
|
||||
// .catch(function(error) {
|
||||
// if(_.includes(_.toLower(error), "error")) {
|
||||
// Status.error(error);
|
||||
// } else {
|
||||
// Status.error("Error: "+error);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }})();
|
||||
|
||||
// // ------------------------------------------------------------------------------
|
||||
// // ----------------------- Store and genrates comments --------------------------
|
||||
// // ------------------------------------------------------------------------------
|
||||
// var Comments = (function() {
|
||||
// var totalComments;
|
||||
// var lookup = {};
|
||||
// var toBeCreated = [];
|
||||
// var totalComments;
|
||||
// var lookup = {};
|
||||
// var toBeCreated = [];
|
||||
|
||||
// var getParentComments = function(toLookup){
|
||||
// var newCommentsToLookup = [];
|
||||
// var commentsToFetch = [];
|
||||
// var getParentComments = function(toLookup){
|
||||
// var newCommentsToLookup = [];
|
||||
// var commentsToFetch = [];
|
||||
|
||||
// _.forEach(toLookup, function(id){
|
||||
// var parentID = lookup[id].parent_id.split("_")[1];
|
||||
|
||||
// if(parentID === Reddit.threadID) {} // Has no parent (is parent of thread)
|
||||
// else if(_.includes(Comments.toBeCreated, parentID)) {} // Parent already exists, do nothing
|
||||
// else if(_.includes(newCommentsToLookup, parentID)) {} // Parent already exists (this iteration)
|
||||
// else if(_.has(lookup, parentID)) {
|
||||
// newCommentsToLookup.push(parentID);
|
||||
// } else{
|
||||
// commentsToFetch.push(parentID);
|
||||
// }
|
||||
|
||||
// Comments.toBeCreated.push(id);
|
||||
// });
|
||||
|
||||
// return new Promise(function(resolve, reject){
|
||||
// if(_.uniq(commentsToFetch).length !== 0) {
|
||||
// fetch(URLs.singleComments + _.join(_.map(_.uniq(commentsToFetch),function(comments){
|
||||
// return "t1_" + comments;
|
||||
// })), Reddit.init)
|
||||
// .then(Fetch2.json)
|
||||
// .then(function(json){
|
||||
// _.forEach(json.data.children, function(comment) {
|
||||
// lookup[comment.data.id] = comment.data;
|
||||
// newCommentsToLookup.push(comment.data.id);
|
||||
// });
|
||||
// })
|
||||
// .then(function(){
|
||||
// resolve();
|
||||
// });
|
||||
|
||||
// } else {
|
||||
// resolve();
|
||||
// }
|
||||
// })
|
||||
// .then(function(){
|
||||
// if(newCommentsToLookup.length !== 0) {
|
||||
// return getParentComments(newCommentsToLookup)
|
||||
// }
|
||||
// });
|
||||
|
||||
// };
|
||||
// _.forEach(toLookup, function(id){
|
||||
// var parentID = lookup[id].parent_id.split("_")[1];
|
||||
|
||||
// if(parentID === Reddit.threadID) {} // Has no parent (is parent of thread)
|
||||
// else if(_.includes(Comments.toBeCreated, parentID)) {} // Parent already exists, do nothing
|
||||
// else if(_.includes(newCommentsToLookup, parentID)) {} // Parent already exists (this iteration)
|
||||
// else if(_.has(lookup, parentID)) {
|
||||
// newCommentsToLookup.push(parentID);
|
||||
// } else{
|
||||
// commentsToFetch.push(parentID);
|
||||
// }
|
||||
|
||||
// Comments.toBeCreated.push(id);
|
||||
// });
|
||||
|
||||
// return new Promise(function(resolve, reject){
|
||||
// if(_.uniq(commentsToFetch).length !== 0) {
|
||||
// fetch(URLs.singleComments + _.join(_.map(_.uniq(commentsToFetch),function(comments){
|
||||
// return "t1_" + comments;
|
||||
// })), Reddit.init)
|
||||
// .then(Fetch2.json)
|
||||
// .then(function(json){
|
||||
// _.forEach(json.data.children, function(comment) {
|
||||
// lookup[comment.data.id] = comment.data;
|
||||
// newCommentsToLookup.push(comment.data.id);
|
||||
// });
|
||||
// })
|
||||
// .then(function(){
|
||||
// resolve();
|
||||
// });
|
||||
|
||||
// } else {
|
||||
// resolve();
|
||||
// }
|
||||
// })
|
||||
// .then(function(){
|
||||
// if(newCommentsToLookup.length !== 0) {
|
||||
// return getParentComments(newCommentsToLookup)
|
||||
// }
|
||||
// });
|
||||
|
||||
// };
|
||||
|
||||
// return {
|
||||
// ids: [], // The comments we found
|
||||
// morechildren: [],
|
||||
// countinuethread: [],
|
||||
|
||||
// allIDs: [], // All the comments that we were suppose to find
|
||||
// removed: [],
|
||||
// deleted: [],
|
||||
// toBeCreated: toBeCreated,
|
||||
// lookup: lookup,
|
||||
// ids: [], // The comments we found
|
||||
// morechildren: [],
|
||||
// countinuethread: [],
|
||||
|
||||
// allIDs: [], // All the comments that we were suppose to find
|
||||
// removed: [],
|
||||
// deleted: [],
|
||||
// toBeCreated: toBeCreated,
|
||||
// lookup: lookup,
|
||||
|
||||
// getTotalComments: function() { return totalComments; },
|
||||
// setTotalComments: function(total) { totalComments = total; },
|
||||
// getTotalComments: function() { return totalComments; },
|
||||
// setTotalComments: function(total) { totalComments = total; },
|
||||
|
||||
// getRoot: function() {
|
||||
// if(Reddit.permalink !== undefined && Reddit.permalink === "") {
|
||||
// return Reddit.threadID;
|
||||
// }
|
||||
// getRoot: function() {
|
||||
// if(Reddit.permalink !== undefined && Reddit.permalink === "") {
|
||||
// return Reddit.threadID;
|
||||
// }
|
||||
|
||||
// if(Reddit.permalink === undefined) {
|
||||
// return Reddit.threadID;
|
||||
// }
|
||||
// if(Reddit.permalink === undefined) {
|
||||
// return Reddit.threadID;
|
||||
// }
|
||||
|
||||
// if(_.has(Comments.lookup, Reddit.permalink)) {
|
||||
// return Comments.lookup[Reddit.permalink].parent_id.split("_")[1];
|
||||
// }
|
||||
// return "";
|
||||
// },
|
||||
// generate: function(removedComments) {
|
||||
// removedComments.forEach(function(comment){
|
||||
// if(_.includes(Comments.deleted, comment.id)) {
|
||||
// comment["deleted"] = true;
|
||||
// } else {
|
||||
// comment["removed"] = true;
|
||||
// }
|
||||
|
||||
// Comments.lookup[comment.id] = comment;
|
||||
// });
|
||||
|
||||
// Comments.removed = _.map(removedComments, function(comment){
|
||||
// return comment.id;
|
||||
// });
|
||||
|
||||
// return getParentComments(Comments.removed)
|
||||
// .then(function(){
|
||||
// ThreadHTML.createCommentSection();
|
||||
// ThreadHTML.createComments();
|
||||
// })
|
||||
// }
|
||||
// if(_.has(Comments.lookup, Reddit.permalink)) {
|
||||
// return Comments.lookup[Reddit.permalink].parent_id.split("_")[1];
|
||||
// }
|
||||
// return "";
|
||||
// },
|
||||
// generate: function(removedComments) {
|
||||
// removedComments.forEach(function(comment){
|
||||
// if(_.includes(Comments.deleted, comment.id)) {
|
||||
// comment["deleted"] = true;
|
||||
// } else {
|
||||
// comment["removed"] = true;
|
||||
// }
|
||||
|
||||
// Comments.lookup[comment.id] = comment;
|
||||
// });
|
||||
|
||||
// Comments.removed = _.map(removedComments, function(comment){
|
||||
// return comment.id;
|
||||
// });
|
||||
|
||||
// return getParentComments(Comments.removed)
|
||||
// .then(function(){
|
||||
// ThreadHTML.createCommentSection();
|
||||
// ThreadHTML.createComments();
|
||||
// })
|
||||
// }
|
||||
// }})();
|
||||
|
||||
|
||||
|
|
@ -212,54 +212,54 @@ export const getCommentIDs = () => {
|
|||
// // ----------------- Handle comments from different requests --------------------
|
||||
// // ------------------------------------------------------------------------------
|
||||
// var HandleIDs = (function(){
|
||||
// var normal = function(thread){
|
||||
// return _.flatten(_.map(thread[1].data.children, Extract.normal))
|
||||
// };
|
||||
// var normal = function(thread){
|
||||
// return _.flatten(_.map(thread[1].data.children, Extract.normal))
|
||||
// };
|
||||
|
||||
// var morechildren = function(){
|
||||
// return Promise.all(_.map(_.uniq(Comments.morechildren), function(idArray){
|
||||
// return Fetch2.multiple(URLs.format(URLs.moreChildren, idArray), Reddit.init);
|
||||
// }))
|
||||
// .then(function(responseArrays){
|
||||
// Comments.morechildren.length = 0;
|
||||
// _.forEach(responseArrays, function(responseArray){
|
||||
// _.forEach(responseArray, function(response){
|
||||
// _.forEach(response.jquery[10][3][0], function(comment){
|
||||
// Extract.normal(comment);
|
||||
// })
|
||||
// });
|
||||
// });
|
||||
// }).then(function(){
|
||||
// if(Comments.morechildren.length !== 0) {
|
||||
// return morechildren();
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
// var morechildren = function(){
|
||||
// return Promise.all(_.map(_.uniq(Comments.morechildren), function(idArray){
|
||||
// return Fetch2.multiple(URLs.format(URLs.moreChildren, idArray), Reddit.init);
|
||||
// }))
|
||||
// .then(function(responseArrays){
|
||||
// Comments.morechildren.length = 0;
|
||||
// _.forEach(responseArrays, function(responseArray){
|
||||
// _.forEach(responseArray, function(response){
|
||||
// _.forEach(response.jquery[10][3][0], function(comment){
|
||||
// Extract.normal(comment);
|
||||
// })
|
||||
// });
|
||||
// });
|
||||
// }).then(function(){
|
||||
// if(Comments.morechildren.length !== 0) {
|
||||
// return morechildren();
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
|
||||
// var removed = function(){
|
||||
// Comments.removed = _.difference(Comments.allIDs, Comments.ids);
|
||||
// var removed = function(){
|
||||
// Comments.removed = _.difference(Comments.allIDs, Comments.ids);
|
||||
|
||||
// Comments.ids.forEach(function(id){
|
||||
// if(! _.has(Comments.lookup, id)) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if(Comments.lookup[id].body === "[removed]") {
|
||||
// Comments.removed.push(id);
|
||||
// } else if (Comments.lookup[id].body === "[deleted]"){
|
||||
// Comments.removed.push(id);
|
||||
// Comments.deleted.push(id);
|
||||
// }
|
||||
// });
|
||||
// Comments.ids.forEach(function(id){
|
||||
// if(! _.has(Comments.lookup, id)) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if(Comments.lookup[id].body === "[removed]") {
|
||||
// Comments.removed.push(id);
|
||||
// } else if (Comments.lookup[id].body === "[deleted]"){
|
||||
// Comments.removed.push(id);
|
||||
// Comments.deleted.push(id);
|
||||
// }
|
||||
// });
|
||||
|
||||
// Comments.removed = _.uniq(Comments.removed);
|
||||
// };
|
||||
// Comments.removed = _.uniq(Comments.removed);
|
||||
// };
|
||||
|
||||
// return {
|
||||
// normal: normal,
|
||||
// morechildren: morechildren,
|
||||
// removed: removed
|
||||
// };
|
||||
// return {
|
||||
// normal: normal,
|
||||
// morechildren: morechildren,
|
||||
// removed: removed
|
||||
// };
|
||||
// })();
|
||||
|
||||
|
||||
|
|
@ -267,32 +267,32 @@ export const getCommentIDs = () => {
|
|||
// // ----------------------- Extract ID from comments -----------------------------
|
||||
// // ------------------------------------------------------------------------------
|
||||
// var Extract = (function(){
|
||||
// var normal = function(comment){
|
||||
// var data = comment.data;
|
||||
|
||||
// if(comment.kind == "more") { // "Show more"-comment
|
||||
// if(data.id === "_") { // = "continue this thread" comment
|
||||
// Comments.countinuethread.push(data.parent_id);
|
||||
// } else if(data.children.length < data.count){ // "Load more"-comment (that is missing some of its children)
|
||||
// Comments.morechildren.push(data.children);
|
||||
// }
|
||||
// Comments.ids.push.apply(Comments.ids, data.children);
|
||||
// } else { // Normal comment
|
||||
// if(data.replies) {
|
||||
// data.replies.data.children.forEach(function(child){
|
||||
// normal(child);
|
||||
// });
|
||||
// delete data.replies;
|
||||
// }
|
||||
|
||||
// Comments.ids.push(data.id);
|
||||
// Comments.lookup[data.id] = data;
|
||||
// }
|
||||
// };
|
||||
|
||||
// return {
|
||||
// normal: normal
|
||||
// };
|
||||
// var normal = function(comment){
|
||||
// var data = comment.data;
|
||||
|
||||
// if(comment.kind == "more") { // "Show more"-comment
|
||||
// if(data.id === "_") { // = "continue this thread" comment
|
||||
// Comments.countinuethread.push(data.parent_id);
|
||||
// } else if(data.children.length < data.count){ // "Load more"-comment (that is missing some of its children)
|
||||
// Comments.morechildren.push(data.children);
|
||||
// }
|
||||
// Comments.ids.push.apply(Comments.ids, data.children);
|
||||
// } else { // Normal comment
|
||||
// if(data.replies) {
|
||||
// data.replies.data.children.forEach(function(child){
|
||||
// normal(child);
|
||||
// });
|
||||
// delete data.replies;
|
||||
// }
|
||||
|
||||
// Comments.ids.push(data.id);
|
||||
// Comments.lookup[data.id] = data;
|
||||
// }
|
||||
// };
|
||||
|
||||
// return {
|
||||
// normal: normal
|
||||
// };
|
||||
// })();
|
||||
|
||||
|
||||
|
|
@ -300,37 +300,37 @@ export const getCommentIDs = () => {
|
|||
// // ---------------------------- Generating HTML ---------------------------------
|
||||
// // ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// var createComments = function(){
|
||||
// var commentsToCreate = _.sortBy(_.uniq(Comments.toBeCreated), function(id) {
|
||||
// return Comments.lookup[id].score;
|
||||
// });
|
||||
|
||||
// var createComments = function(){
|
||||
// var commentsToCreate = _.sortBy(_.uniq(Comments.toBeCreated), function(id) {
|
||||
// return Comments.lookup[id].score;
|
||||
// });
|
||||
|
||||
// var createdComments = [Comments.getRoot()];
|
||||
// var didSomething = false;
|
||||
|
||||
// while(commentsToCreate.length > 0) {
|
||||
// didSomething = false;
|
||||
|
||||
// for(var i = commentsToCreate.length - 1; i >= 0; i--) {
|
||||
// var id = commentsToCreate[i];
|
||||
// var parentID = Comments.lookup[id].parent_id.split("_")[1];
|
||||
|
||||
// if(_.includes(createdComments, parentID)) {
|
||||
// document.getElementById(parentID).appendChild(createComment(Comments.lookup[id]));
|
||||
// createdComments.push(id);
|
||||
// commentsToCreate.splice(i, 1);
|
||||
// didSomething = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Fail safe (parents missing for the rest of the comments, shouldn't happend but oh well :D)
|
||||
// if(!didSomething) {
|
||||
// console.error("Didn't generate all comments correctly");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// var createdComments = [Comments.getRoot()];
|
||||
// var didSomething = false;
|
||||
|
||||
// while(commentsToCreate.length > 0) {
|
||||
// didSomething = false;
|
||||
|
||||
// for(var i = commentsToCreate.length - 1; i >= 0; i--) {
|
||||
// var id = commentsToCreate[i];
|
||||
// var parentID = Comments.lookup[id].parent_id.split("_")[1];
|
||||
|
||||
// if(_.includes(createdComments, parentID)) {
|
||||
// document.getElementById(parentID).appendChild(createComment(Comments.lookup[id]));
|
||||
// createdComments.push(id);
|
||||
// commentsToCreate.splice(i, 1);
|
||||
// didSomething = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Fail safe (parents missing for the rest of the comments, shouldn't happend but oh well :D)
|
||||
// if(!didSomething) {
|
||||
// console.error("Didn't generate all comments correctly");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,13 +1,11 @@
|
|||
import { createStore, combineReducers, applyMiddleware } from 'redux'
|
||||
import logger from 'redux-logger'
|
||||
|
||||
import { statusReducer } from './status'
|
||||
|
||||
export { setStatusLoading, setStatusSuccess, setStatusError } from './status'
|
||||
|
||||
const reducer = combineReducers({
|
||||
status: statusReducer
|
||||
status: statusReducer,
|
||||
})
|
||||
|
||||
|
||||
|
||||
export const store = createStore(reducer, applyMiddleware(logger))
|
||||
export const store = createStore(reducer, applyMiddleware(logger))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const images = {
|
||||
loading: '/images/loading.gif',
|
||||
error: '/images/error.png',
|
||||
success: '/images/done.png'
|
||||
loading: '/images/loading.gif',
|
||||
error: '/images/error.png',
|
||||
success: '/images/done.png',
|
||||
}
|
||||
|
||||
// Action types
|
||||
|
|
@ -10,45 +10,37 @@ const STATUS_SET_SUCCESS = 'STATUS_SET_SUCCESS'
|
|||
const STATUS_SET_ERROR = 'STATUS_SET_ERROR'
|
||||
|
||||
// Action creators
|
||||
export const setStatusLoading = (payload = '') => {
|
||||
return {type: STATUS_SET_LOADING, payload}
|
||||
}
|
||||
|
||||
export const setStatusSuccess = (payload = '') => {
|
||||
return {type: STATUS_SET_SUCCESS, payload}
|
||||
}
|
||||
|
||||
export const setStatusError = (payload = '') => {
|
||||
return {type: STATUS_SET_ERROR, payload}
|
||||
}
|
||||
export const setStatusLoading = (payload = '') => ({ type: STATUS_SET_LOADING, payload })
|
||||
export const setStatusSuccess = (payload = '') => ({ type: STATUS_SET_SUCCESS, payload })
|
||||
export const setStatusError = (payload = '') => ({ type: STATUS_SET_ERROR, payload })
|
||||
|
||||
// Init state
|
||||
const initialStatusState = {
|
||||
text: null,
|
||||
image: null
|
||||
text: null,
|
||||
image: null,
|
||||
}
|
||||
|
||||
export const statusReducer = (state = initialStatusState, action) => {
|
||||
switch (action.type) {
|
||||
case STATUS_SET_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
text: action.payload,
|
||||
image: images.success
|
||||
}
|
||||
case STATUS_SET_LOADING:
|
||||
return {
|
||||
...state,
|
||||
text: action.payload,
|
||||
image: images.loading
|
||||
}
|
||||
case STATUS_SET_ERROR:
|
||||
return {
|
||||
...state,
|
||||
text: action.payload,
|
||||
image: images.error
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
switch (action.type) {
|
||||
case STATUS_SET_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
text: action.payload,
|
||||
image: images.success,
|
||||
}
|
||||
case STATUS_SET_LOADING:
|
||||
return {
|
||||
...state,
|
||||
text: action.payload,
|
||||
image: images.loading,
|
||||
}
|
||||
case STATUS_SET_ERROR:
|
||||
return {
|
||||
...state,
|
||||
text: action.payload,
|
||||
image: images.error,
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import SnuOwnd from 'libraries/snuownd.js'
|
|||
const markdown = SnuOwnd.getParser()
|
||||
|
||||
// Change bases
|
||||
export const toBase36 = number => parseInt(number).toString(36)
|
||||
export const toBase36 = number => parseInt(number, 10).toString(36)
|
||||
export const toBase10 = numberString => parseInt(numberString, 36)
|
||||
|
||||
// Default thumbnails for reddit threads
|
||||
|
|
@ -17,32 +17,32 @@ export const parse = text => markdown.render(text)
|
|||
|
||||
// UTC -> "Reddit time format" (e.g. 5 hours ago, just now, etc...)
|
||||
export const prettyDate = createdUTC => {
|
||||
const currentUTC = Math.floor((new Date()).getTime() / 1000)
|
||||
const secondDiff = currentUTC - createdUTC
|
||||
const dayDiff = Math.floor(secondDiff / 86400)
|
||||
|
||||
if(dayDiff < 0) return ""
|
||||
if(dayDiff == 0) {
|
||||
if(secondDiff < 10) return "just now"
|
||||
if(secondDiff < 60) return secondDiff + " seconds ago"
|
||||
if(secondDiff < 120) return "a minute ago"
|
||||
if(secondDiff < 3600) return Math.floor(secondDiff / 60) + " minutes ago"
|
||||
if(secondDiff < 7200) return "an hour ago"
|
||||
if(secondDiff < 86400) return Math.floor(secondDiff / 3600) + " hours ago"
|
||||
}
|
||||
if(dayDiff < 7) return dayDiff + " days ago"
|
||||
if(dayDiff < 31) return Math.floor(dayDiff / 7) + " weeks ago"
|
||||
if(dayDiff < 365) return Math.floor(dayDiff / 30) + " months ago"
|
||||
return Math.floor(dayDiff / 365) + " years ago"
|
||||
const currentUTC = Math.floor((new Date()).getTime() / 1000)
|
||||
const secondDiff = currentUTC - createdUTC
|
||||
const dayDiff = Math.floor(secondDiff / 86400)
|
||||
|
||||
if (dayDiff < 0) return ''
|
||||
if (dayDiff === 0) {
|
||||
if (secondDiff < 10) return 'just now'
|
||||
if (secondDiff < 60) return `${secondDiff} seconds ago`
|
||||
if (secondDiff < 120) return 'a minute ago'
|
||||
if (secondDiff < 3600) return `${Math.floor(secondDiff / 60)} minutes ago`
|
||||
if (secondDiff < 7200) return 'an hour ago'
|
||||
if (secondDiff < 86400) return `${Math.floor(secondDiff / 3600)} hours ago`
|
||||
}
|
||||
if (dayDiff < 7) return `${dayDiff} days ago`
|
||||
if (dayDiff < 31) return `${Math.floor(dayDiff / 7)} weeks ago`
|
||||
if (dayDiff < 365) return `${Math.floor(dayDiff / 30)} months ago`
|
||||
return `${Math.floor(dayDiff / 365)} years ago`
|
||||
}
|
||||
|
||||
// Reddit format for scores, e.g. 12000 => 12k
|
||||
export const prettyScore = score => {
|
||||
if(score >= 100000) {
|
||||
return (score / 1000).toFixed(0) + "k"
|
||||
} else if(score >= 10000) {
|
||||
return (score / 1000).toFixed(1) + "k"
|
||||
}
|
||||
if (score >= 100000) {
|
||||
return `${(score / 1000).toFixed(0)}k`
|
||||
} else if (score >= 10000) {
|
||||
return `${(score / 1000).toFixed(1)}k`
|
||||
}
|
||||
|
||||
return score
|
||||
}
|
||||
return score
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue