Initial commit

This commit is contained in:
Sonny Bakker 2025-03-23 21:20:21 +01:00
parent 1a54fdbcd1
commit 1b0671b34c
8 changed files with 107 additions and 230 deletions

View file

@ -29,11 +29,6 @@ x-django-env: &django-env
EMAIL_USE_SSL:
EMAIL_DEFAULT_FROM:
# Reddit
REDDIT_CLIENT_ID:
REDDIT_CLIENT_SECRET:
REDDIT_CALLBACK_URL:
# Sentry
SENTRY_DSN:

View file

@ -209,16 +209,6 @@ STATICFILES_FINDERS = [
# Email
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
# Reddit integration
REDDIT_CLIENT_ID = "CLIENT_ID"
REDDIT_CLIENT_SECRET = "CLIENT_SECRET"
REDDIT_REDIRECT_URL = (
"http://127.0.0.1:8000/accounts/settings/integrations/reddit/callback/"
)
# Twitter integration
TWITTER_URL = "https://twitter.com"
# Third party settings
AXES_HANDLER = "axes.handlers.cache.AxesCacheHandler"
AXES_CACHE = "axes"

View file

@ -48,11 +48,6 @@ EMAIL_USE_SSL = bool(os.environ.get("EMAIL_USE_SSL"))
VERSION = get_current_version(debug=False)
ENVIRONMENT = "production"
# Reddit integration
REDDIT_CLIENT_ID = os.environ.get("REDDIT_CLIENT_ID", "")
REDDIT_CLIENT_SECRET = os.environ.get("REDDIT_CLIENT_SECRET", "")
REDDIT_REDIRECT_URL = os.environ.get("REDDIT_CALLBACK_URL", "")
# Third party settings
AXES_HANDLER = "axes.handlers.database.AxesDatabaseHandler"

View file

@ -3,14 +3,14 @@ import { connect } from 'react-redux';
import Cookies from 'js-cookie';
import { unSelectPost, markPostRead, toggleSaved } from '../actions/posts.js';
import { SAVED_TYPE, SUBREDDIT } from '../constants.js';
import { SAVED_TYPE } from '../constants.js';
import { formatDatetime } from '../../../utils.js';
class PostModal extends React.Component {
modalListener = ::this.modalListener;
readTimer = null;
readTimer = null;
componentDidMount() {
componentDidMount() {
const post = { ...this.props.post };
const markPostRead = this.props.markPostRead;
const token = Cookies.get('csrftoken');
@ -20,9 +20,9 @@ class PostModal extends React.Component {
}
window.addEventListener('click', this.modalListener);
}
}
componentWillUnmount() {
componentWillUnmount() {
if (this.readTimer) {
clearTimeout(this.readTimer);
}
@ -30,17 +30,17 @@ class PostModal extends React.Component {
this.readTimer = null;
window.removeEventListener('click', this.modalListener);
}
}
modalListener(e) {
modalListener(e) {
const targetClassName = e.target.className;
if (this.props.post && targetClassName == 'modal post-modal') {
this.props.unSelectPost();
}
}
}
render() {
render() {
const post = this.props.post;
const token = Cookies.get('csrftoken');
const publicationDate = formatDatetime(post.publicationDate);
@ -54,9 +54,6 @@ class PostModal extends React.Component {
let ruleUrl = '';
switch (this.props.rule.type) {
case SUBREDDIT:
ruleUrl = `${this.props.subredditUrl}/${this.props.rule.id}/`;
break;
default:
ruleUrl = `${this.props.feedUrl}/${this.props.rule.id}/`;
break;
@ -135,7 +132,7 @@ class PostModal extends React.Component {
</div>
</div>
);
}
}
}
const mapDispatchToProps = dispatch => ({

View file

@ -2,7 +2,7 @@ import React from 'react';
import { connect } from 'react-redux';
import Cookies from 'js-cookie';
import { CATEGORY_TYPE, SAVED_TYPE, SUBREDDIT } from '../../constants.js';
import { CATEGORY_TYPE, SAVED_TYPE } from '../../constants.js';
import { selectPost, toggleSaved } from '../../actions/posts.js';
import { formatDatetime } from '../../../../utils.js';
@ -18,12 +18,7 @@ class PostItem extends React.Component {
: 'posts__header';
const savedIconClass = post.saved ? 'saved-icon saved-icon--saved' : 'saved-icon';
let ruleUrl = '';
if (rule.type === SUBREDDIT) {
ruleUrl = `${this.props.subredditUrl}/${rule.id}/`;
} else {
ruleUrl = `${this.props.feedUrl}/${rule.id}/`;
}
const ruleUrl = `${this.props.feedUrl}/${rule.id}/`;
return (
<li className="posts__item" ref={this.props.forwardedRef}>

View file

@ -2,5 +2,4 @@ export const RULE_TYPE = 'RULE';
export const CATEGORY_TYPE = 'CATEGORY';
export const SAVED_TYPE = 'SAVED';
export const SUBREDDIT = 'subreddit';
export const FEED = 'feed';

View file

@ -1,4 +1,3 @@
from django.conf import settings
from django.db import models
from django.urls import reverse
from django.utils.translation import gettext as _
@ -84,13 +83,6 @@ class CollectionRule(TimeStampedModel):
@property
def source_url(self):
if self.type == RuleTypeChoices.subreddit:
from newsreader.news.collection.reddit import REDDIT_API_URL, REDDIT_URL
return self.url.replace(REDDIT_API_URL, REDDIT_URL)
elif self.type == RuleTypeChoices.twitter_timeline:
return f"{settings.TWITTER_URL}/{self.screen_name}"
return self.url
@property

View file

@ -1,19 +1,13 @@
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.core.mail import send_mail
from django.utils.translation import gettext as _
import requests
from celery.exceptions import Reject
from celery.utils.log import get_task_logger
from newsreader.accounts.models import User
from newsreader.celery import app
from newsreader.news.collection.choices import RuleTypeChoices
from newsreader.news.collection.exceptions.stream import StreamException
from newsreader.news.collection.feed import FeedCollector
from newsreader.news.collection.utils import post
from newsreader.utils.celery import MemCacheLock
@ -49,84 +43,6 @@ class FeedTask(app.Task):
raise Reject(reason="Task already running", requeue=False)
class RedditTask(app.Task):
name = "RedditTask"
ignore_result = True
def run(self):
from newsreader.news.collection.reddit import RedditCollector, RedditScheduler
with MemCacheLock("reddit-task", self.app.oid) as acquired:
if acquired:
logger.info("Running reddit task")
scheduler = RedditScheduler()
subreddits = scheduler.get_scheduled_rules()
collector = RedditCollector()
collector.collect(rules=subreddits)
else:
logger.warning("Cancelling task due to existing lock")
raise Reject(reason="Task already running", requeue=False)
class RedditTokenTask(app.Task):
name = "RedditTokenTask"
ignore_result = True
def run(self, user_pk):
from newsreader.news.collection.reddit import REDDIT_URL
try:
user = User.objects.get(pk=user_pk)
except ObjectDoesNotExist:
message = f"User {user_pk} does not exist"
logger.exception(message)
raise Reject(reason=message, requeue=False)
if not user.reddit_refresh_token:
raise Reject(reason=f"User {user_pk} has no refresh token", requeue=False)
client_auth = requests.auth.HTTPBasicAuth(
settings.REDDIT_CLIENT_ID, settings.REDDIT_CLIENT_SECRET
)
try:
response = post(
f"{REDDIT_URL}/api/v1/access_token",
data={
"grant_type": "refresh_token",
"refresh_token": user.reddit_refresh_token,
},
auth=client_auth,
)
except StreamException:
logger.exception(
f"Failed refreshing reddit access token for user {user_pk}"
)
user.reddit_refresh_token = None
user.save()
message = _(
"Your Reddit account credentials have expired. Re-authenticate in"
" the settings page to keep retrieving Reddit specific information"
" from your account."
)
send_mail(
"Reddit account needs re-authentication", message, None, [user.email]
)
return
response_data = response.json()
user.reddit_access_token = response_data["access_token"]
user.save()
class FaviconTask(app.Task):
name = "FaviconTask"
ignore_result = True
@ -167,5 +83,3 @@ class FaviconTask(app.Task):
FeedTask = app.register_task(FeedTask())
FaviconTask = app.register_task(FaviconTask())
RedditTask = app.register_task(RedditTask())
RedditTokenTask = app.register_task(RedditTokenTask())