From 491f41389d4df8129eb71aed1ea300a87ba468c0 Mon Sep 17 00:00:00 2001 From: Sonny Bakker Date: Sun, 23 Mar 2025 21:02:12 +0100 Subject: [PATCH 01/25] Remove requests-oauthlib --- pyproject.toml | 1 - uv.lock | 24 ------------------------ 2 files changed, 25 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1db5f34..c722183 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,6 @@ dependencies = [ 'python-dotenv~=1.0.1', 'ftfy~=6.2', 'requests', - 'requests_oauthlib', 'feedparser', 'bleach', 'beautifulsoup4', diff --git a/uv.lock b/uv.lock index 84ca47a..c108e5c 100644 --- a/uv.lock +++ b/uv.lock @@ -505,7 +505,6 @@ dependencies = [ { name = "pymemcache", marker = "sys_platform == 'linux'" }, { name = "python-dotenv", marker = "sys_platform == 'linux'" }, { name = "requests", marker = "sys_platform == 'linux'" }, - { name = "requests-oauthlib", marker = "sys_platform == 'linux'" }, ] [package.optional-dependencies] @@ -548,7 +547,6 @@ requires-dist = [ { name = "pymemcache" }, { name = "python-dotenv", specifier = "~=1.0.1" }, { name = "requests" }, - { name = "requests-oauthlib" }, { name = "sentry-sdk", marker = "extra == 'sentry'", specifier = "~=2.0" }, ] provides-extras = ["sentry"] @@ -567,15 +565,6 @@ test-tools = [ { name = "ruff" }, ] -[[package]] -name = "oauthlib" -version = "3.2.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6d/fa/fbf4001037904031639e6bfbfc02badfc7e12f137a8afa254df6c4c8a670/oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918", size = 177352 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/80/cab10959dc1faead58dc8384a781dfbf93cb4d33d50988f7a69f1b7c9bbe/oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", size = 151688 }, -] - [[package]] name = "packaging" version = "24.1" @@ -666,19 +655,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, ] -[[package]] -name = "requests-oauthlib" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "oauthlib", marker = "sys_platform == 'linux'" }, - { name = "requests", marker = "sys_platform == 'linux'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/42/f2/05f29bc3913aea15eb670be136045bf5c5bbf4b99ecb839da9b422bb2c85/requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9", size = 55650 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", size = 24179 }, -] - [[package]] name = "ruff" version = "0.6.3" From 1574661c572a43cb3a2f463438f6f6626b1f1bdc Mon Sep 17 00:00:00 2001 From: Sonny Bakker Date: Sun, 23 Mar 2025 21:05:01 +0100 Subject: [PATCH 02/25] Fix ruff errors --- src/newsreader/accounts/views/__init__.py | 2 +- src/newsreader/conf/production.py | 3 +- src/newsreader/news/collection/endpoints.py | 1 + .../news/collection/forms/__init__.py | 1 + src/newsreader/news/collection/models.py | 2 +- .../collection/tests/favicon/builder/tests.py | 10 +++---- .../collection/tests/feed/builder/tests.py | 24 +++++++-------- .../collection/tests/reddit/builder/tests.py | 30 +++++++++---------- src/newsreader/news/core/endpoints.py | 1 + 9 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/newsreader/accounts/views/__init__.py b/src/newsreader/accounts/views/__init__.py index f5e926b..e62755c 100644 --- a/src/newsreader/accounts/views/__init__.py +++ b/src/newsreader/accounts/views/__init__.py @@ -13,9 +13,9 @@ from newsreader.accounts.views.password import ( PasswordResetDoneView, PasswordResetView, ) - from newsreader.accounts.views.settings import SettingsView + __all__ = [ "LoginView", "LogoutView", diff --git a/src/newsreader/conf/production.py b/src/newsreader/conf/production.py index 2042e29..8615aa2 100644 --- a/src/newsreader/conf/production.py +++ b/src/newsreader/conf/production.py @@ -1,10 +1,9 @@ import os +from .base import * # noqa: F403 from .version import get_current_version -from .base import * # noqa: F403 - DEBUG = False SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") diff --git a/src/newsreader/news/collection/endpoints.py b/src/newsreader/news/collection/endpoints.py index 24918c9..c5c5580 100644 --- a/src/newsreader/news/collection/endpoints.py +++ b/src/newsreader/news/collection/endpoints.py @@ -1,4 +1,5 @@ from django.db.models import Prefetch + from rest_framework import status from rest_framework.generics import ( GenericAPIView, diff --git a/src/newsreader/news/collection/forms/__init__.py b/src/newsreader/news/collection/forms/__init__.py index 4482b5c..daf73b0 100644 --- a/src/newsreader/news/collection/forms/__init__.py +++ b/src/newsreader/news/collection/forms/__init__.py @@ -2,6 +2,7 @@ from newsreader.news.collection.forms.feed import FeedForm, OPMLImportForm from newsreader.news.collection.forms.reddit import SubRedditForm from newsreader.news.collection.forms.rules import CollectionRuleBulkForm + __all__ = [ "FeedForm", "OPMLImportForm", diff --git a/src/newsreader/news/collection/models.py b/src/newsreader/news/collection/models.py index c538ae6..1eb148c 100644 --- a/src/newsreader/news/collection/models.py +++ b/src/newsreader/news/collection/models.py @@ -1,5 +1,5 @@ -from django.db import models from django.conf import settings +from django.db import models from django.urls import reverse from django.utils.translation import gettext as _ diff --git a/src/newsreader/news/collection/tests/favicon/builder/tests.py b/src/newsreader/news/collection/tests/favicon/builder/tests.py index af9b33d..a670f8a 100644 --- a/src/newsreader/news/collection/tests/favicon/builder/tests.py +++ b/src/newsreader/news/collection/tests/favicon/builder/tests.py @@ -5,12 +5,12 @@ from django.test import TestCase from newsreader.news.collection.favicon import FaviconBuilder from newsreader.news.collection.tests.factories import CollectionRuleFactory from newsreader.news.collection.tests.favicon.builder.mocks import ( - simple_mock, - mock_without_url, - mock_without_header, - mock_with_weird_path, - mock_with_other_url, mock_with_multiple_icons, + mock_with_other_url, + mock_with_weird_path, + mock_without_header, + mock_without_url, + simple_mock, ) diff --git a/src/newsreader/news/collection/tests/feed/builder/tests.py b/src/newsreader/news/collection/tests/feed/builder/tests.py index 420d95e..3a32e76 100644 --- a/src/newsreader/news/collection/tests/feed/builder/tests.py +++ b/src/newsreader/news/collection/tests/feed/builder/tests.py @@ -11,21 +11,21 @@ from newsreader.news.core.models import Post from newsreader.news.core.tests.factories import FeedPostFactory from .mocks import ( - multiple_mock, + mock_with_html, + mock_with_long_author, + mock_with_long_exotic_title, + mock_with_long_title, + mock_with_longer_content_detail, + mock_with_multiple_content_detail, + mock_with_shorter_content_detail, + mock_with_update_entries, + mock_without_author, + mock_without_body, + mock_without_entries, mock_without_identifier, mock_without_publish_date, mock_without_url, - mock_without_body, - mock_without_author, - mock_without_entries, - mock_with_update_entries, - mock_with_html, - mock_with_long_author, - mock_with_long_title, - mock_with_long_exotic_title, - mock_with_longer_content_detail, - mock_with_shorter_content_detail, - mock_with_multiple_content_detail, + multiple_mock, ) diff --git a/src/newsreader/news/collection/tests/reddit/builder/tests.py b/src/newsreader/news/collection/tests/reddit/builder/tests.py index d9196a0..5144edf 100644 --- a/src/newsreader/news/collection/tests/reddit/builder/tests.py +++ b/src/newsreader/news/collection/tests/reddit/builder/tests.py @@ -6,24 +6,24 @@ from django.test import TestCase from newsreader.news.collection.reddit import RedditBuilder from newsreader.news.collection.tests.factories import SubredditFactory from newsreader.news.collection.tests.reddit.builder.mocks import ( - simple_mock, - empty_mock, - unknown_mock, - unsanitized_mock, author_mock, - title_mock, - duplicate_mock, - image_mock, - external_image_mock, - video_mock, - external_video_mock, - external_gifv_mock, - nsfw_mock, - spoiler_mock, - seen_mock, - upvote_mock, comment_mock, downvote_mock, + duplicate_mock, + empty_mock, + external_gifv_mock, + external_image_mock, + external_video_mock, + image_mock, + nsfw_mock, + seen_mock, + simple_mock, + spoiler_mock, + title_mock, + unknown_mock, + unsanitized_mock, + upvote_mock, + video_mock, ) from newsreader.news.core.models import Post from newsreader.news.core.tests.factories import RedditPostFactory diff --git a/src/newsreader/news/core/endpoints.py b/src/newsreader/news/core/endpoints.py index 6ed9f39..092ec6f 100644 --- a/src/newsreader/news/core/endpoints.py +++ b/src/newsreader/news/core/endpoints.py @@ -1,4 +1,5 @@ from django.db.models import Prefetch + from rest_framework import status from rest_framework.generics import ( GenericAPIView, From 34afcc02b69268b1d634e7e39f3c40caae1dcffb Mon Sep 17 00:00:00 2001 From: Sonny Bakker Date: Sun, 23 Mar 2025 21:16:36 +0100 Subject: [PATCH 03/25] Remove requests oathlib --- pyproject.toml | 1 - uv.lock | 24 ------------------------ 2 files changed, 25 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1db5f34..c722183 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,6 @@ dependencies = [ 'python-dotenv~=1.0.1', 'ftfy~=6.2', 'requests', - 'requests_oauthlib', 'feedparser', 'bleach', 'beautifulsoup4', diff --git a/uv.lock b/uv.lock index 84ca47a..c108e5c 100644 --- a/uv.lock +++ b/uv.lock @@ -505,7 +505,6 @@ dependencies = [ { name = "pymemcache", marker = "sys_platform == 'linux'" }, { name = "python-dotenv", marker = "sys_platform == 'linux'" }, { name = "requests", marker = "sys_platform == 'linux'" }, - { name = "requests-oauthlib", marker = "sys_platform == 'linux'" }, ] [package.optional-dependencies] @@ -548,7 +547,6 @@ requires-dist = [ { name = "pymemcache" }, { name = "python-dotenv", specifier = "~=1.0.1" }, { name = "requests" }, - { name = "requests-oauthlib" }, { name = "sentry-sdk", marker = "extra == 'sentry'", specifier = "~=2.0" }, ] provides-extras = ["sentry"] @@ -567,15 +565,6 @@ test-tools = [ { name = "ruff" }, ] -[[package]] -name = "oauthlib" -version = "3.2.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6d/fa/fbf4001037904031639e6bfbfc02badfc7e12f137a8afa254df6c4c8a670/oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918", size = 177352 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/80/cab10959dc1faead58dc8384a781dfbf93cb4d33d50988f7a69f1b7c9bbe/oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", size = 151688 }, -] - [[package]] name = "packaging" version = "24.1" @@ -666,19 +655,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, ] -[[package]] -name = "requests-oauthlib" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "oauthlib", marker = "sys_platform == 'linux'" }, - { name = "requests", marker = "sys_platform == 'linux'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/42/f2/05f29bc3913aea15eb670be136045bf5c5bbf4b99ecb839da9b422bb2c85/requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9", size = 55650 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", size = 24179 }, -] - [[package]] name = "ruff" version = "0.6.3" From 1a54fdbcd1e90618fe2f75b3b1c71895854d3ecc Mon Sep 17 00:00:00 2001 From: Sonny Bakker Date: Sat, 8 Feb 2025 10:05:45 +0100 Subject: [PATCH 04/25] Remove function binding usage --- babel.config.js | 30 +++++++++---------- src/newsreader/js/components/Selector.js | 4 +-- src/newsreader/js/pages/categories/App.js | 10 ++----- .../js/pages/homepage/components/ScrollTop.js | 4 +-- .../homepage/components/postlist/PostList.js | 4 +-- .../homepage/components/sidebar/ReadButton.js | 4 +-- 6 files changed, 21 insertions(+), 35 deletions(-) diff --git a/babel.config.js b/babel.config.js index 20d9e41..ed19be2 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,23 +1,21 @@ module.exports = api => { const isTest = api.env('test'); - const preset = [ - "@babel/preset-env" , { targets: 'defaults' } + const preset = [ + "@babel/preset-env", { targets: 'defaults' } + ]; + const testPreset = [ + "@babel/preset-env", { targets: { node: process.versions.node } } ]; - const testPreset = [ - "@babel/preset-env", { targets: { node: process.versions.node } } - ]; - const plugins = [ - "@babel/plugin-syntax-dynamic-import", - "@babel/plugin-transform-react-jsx", - "@babel/plugin-syntax-function-bind", - "@babel/plugin-proposal-function-bind", - "@babel/plugin-proposal-class-properties" - ] + const plugins = [ + "@babel/plugin-syntax-dynamic-import", + "@babel/plugin-transform-react-jsx", + "@babel/plugin-proposal-class-properties" + ] - return { - "presets": [isTest ? testPreset: preset], - "plugins": plugins - } + return { + "presets": [isTest ? testPreset : preset], + "plugins": plugins + } } diff --git a/src/newsreader/js/components/Selector.js b/src/newsreader/js/components/Selector.js index 8b701f5..c6b117a 100644 --- a/src/newsreader/js/components/Selector.js +++ b/src/newsreader/js/components/Selector.js @@ -1,6 +1,4 @@ class Selector { - onClick = ::this.onClick; - inputs = []; constructor() { @@ -11,7 +9,7 @@ class Selector { selectAllInput.onchange = this.onClick; } - onClick(e) { + onClick = (e) => { const targetValue = e.target.checked; this.inputs.forEach(input => { diff --git a/src/newsreader/js/pages/categories/App.js b/src/newsreader/js/pages/categories/App.js index b20ff1d..ac237c3 100644 --- a/src/newsreader/js/pages/categories/App.js +++ b/src/newsreader/js/pages/categories/App.js @@ -9,10 +9,6 @@ import Messages from '../../components/Messages.js'; import Sidebar from '../../components/Sidebar.js'; class App extends React.Component { - selectCategory = ::this.selectCategory; - deselectCategory = ::this.deselectCategory; - deleteCategory = ::this.deleteCategory; - constructor(props) { super(props); @@ -24,15 +20,15 @@ class App extends React.Component { }; } - selectCategory(categoryId) { + selectCategory = (categoryId) => { this.setState({ selectedCategoryId: categoryId }); } - deselectCategory() { + deselectCategory = () => { this.setState({ selectedCategoryId: null }); } - deleteCategory(categoryId) { + deleteCategory = (categoryId) => { const url = `/api/categories/${categoryId}/`; const options = { method: 'DELETE', diff --git a/src/newsreader/js/pages/homepage/components/ScrollTop.js b/src/newsreader/js/pages/homepage/components/ScrollTop.js index 9cca7f7..a9927f2 100644 --- a/src/newsreader/js/pages/homepage/components/ScrollTop.js +++ b/src/newsreader/js/pages/homepage/components/ScrollTop.js @@ -1,8 +1,6 @@ import React from 'react'; export default class ScrollTop extends React.Component { - scrollListener = ::this.scrollListener; - state = { listenerAttached: false, showTop: false, @@ -17,7 +15,7 @@ export default class ScrollTop extends React.Component { } } - scrollListener() { + scrollListener = () => { const postList = this.props.postListNode; const elementEnd = postList.scrollTop + postList.offsetHeight >= postList.scrollHeight; diff --git a/src/newsreader/js/pages/homepage/components/postlist/PostList.js b/src/newsreader/js/pages/homepage/components/postlist/PostList.js index 8bb354a..9c534ee 100644 --- a/src/newsreader/js/pages/homepage/components/postlist/PostList.js +++ b/src/newsreader/js/pages/homepage/components/postlist/PostList.js @@ -4,13 +4,11 @@ import { isEqual } from 'lodash'; import { fetchPostsBySection, fetchSavedPosts } from '../../actions/posts.js'; import { SAVED_TYPE } from '../../constants.js'; -import { filterPosts } from './filters.js'; import LoadingIndicator from '../../../../components/LoadingIndicator.js'; import PostItem from './PostItem.js'; class PostList extends React.Component { - handleIntersect = ::this.handleIntersect; lastPostRef = null; observer = null; @@ -33,7 +31,7 @@ class PostList extends React.Component { this.observer.disconnect(); } - handleIntersect(entries) { + handleIntersect = (entries) => { entries.every(entry => { if (entry.isIntersecting) { this.observer.unobserve(entry.target); diff --git a/src/newsreader/js/pages/homepage/components/sidebar/ReadButton.js b/src/newsreader/js/pages/homepage/components/sidebar/ReadButton.js index 3711c85..fe4175b 100644 --- a/src/newsreader/js/pages/homepage/components/sidebar/ReadButton.js +++ b/src/newsreader/js/pages/homepage/components/sidebar/ReadButton.js @@ -5,9 +5,7 @@ import Cookies from 'js-cookie'; import { markRead } from '../../actions/selected.js'; class ReadButton extends React.Component { - markSelectedRead = ::this.markSelectedRead; - - markSelectedRead() { + markSelectedRead = () => { const token = Cookies.get('csrftoken'); if (this.props.selected.unread > 0) { From b465d0bb8ddb7088454693af0ff87b7c230f726c Mon Sep 17 00:00:00 2001 From: Sonny Bakker Date: Thu, 27 Mar 2025 21:44:21 +0100 Subject: [PATCH 05/25] Remove leftover function binding usages --- src/newsreader/js/components/Messages.js | 4 +--- src/newsreader/js/pages/homepage/components/PostModal.js | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/newsreader/js/components/Messages.js b/src/newsreader/js/components/Messages.js index 3fed5de..e3d776e 100644 --- a/src/newsreader/js/components/Messages.js +++ b/src/newsreader/js/components/Messages.js @@ -3,9 +3,7 @@ import React from 'react'; class Messages extends React.Component { state = { messages: this.props.messages }; - close = ::this.close; - - close(index) { + close = (index) => { const newMessages = this.state.messages.filter((message, currentIndex) => { return currentIndex != index; }); diff --git a/src/newsreader/js/pages/homepage/components/PostModal.js b/src/newsreader/js/pages/homepage/components/PostModal.js index 46410b7..a1a698d 100644 --- a/src/newsreader/js/pages/homepage/components/PostModal.js +++ b/src/newsreader/js/pages/homepage/components/PostModal.js @@ -7,7 +7,6 @@ import { SAVED_TYPE, SUBREDDIT } from '../constants.js'; import { formatDatetime } from '../../../utils.js'; class PostModal extends React.Component { - modalListener = ::this.modalListener; readTimer = null; componentDidMount() { @@ -32,7 +31,7 @@ class PostModal extends React.Component { window.removeEventListener('click', this.modalListener); } - modalListener(e) { + modalListener = (e) => { const targetClassName = e.target.className; if (this.props.post && targetClassName == 'modal post-modal') { From b8559f04999fdcfce4f667889cab7bf99f272fe9 Mon Sep 17 00:00:00 2001 From: Sonny Bakker Date: Thu, 27 Mar 2025 22:02:12 +0100 Subject: [PATCH 06/25] Remove reddit code --- docker-compose.yml | 5 - src/newsreader/accounts/admin.py | 10 - ...emove_user_reddit_access_token_and_more.py | 21 + src/newsreader/accounts/models.py | 4 - .../accounts/components/settings-form.html | 38 +- .../accounts/views/integrations.html | 47 - .../templates/accounts/views/reddit.html | 22 - .../accounts/tests/test_integrations.py | 275 - src/newsreader/accounts/urls.py | 23 - src/newsreader/accounts/views/__init__.py | 10 - src/newsreader/accounts/views/integrations.py | 156 - src/newsreader/conf/base.py | 10 - src/newsreader/conf/production.py | 5 - src/newsreader/js/pages/homepage/App.js | 2 - .../js/pages/homepage/components/PostModal.js | 7 +- .../homepage/components/postlist/PostItem.js | 9 +- .../homepage/components/postlist/PostList.js | 1 - src/newsreader/js/pages/homepage/constants.js | 1 - src/newsreader/js/pages/homepage/index.js | 3 +- src/newsreader/news/collection/choices.py | 8 - .../news/collection/forms/__init__.py | 2 - .../news/collection/forms/reddit.py | 57 - ...llectionrule_reddit_allow_nfsw_and_more.py | 46 + src/newsreader/news/collection/models.py | 32 - src/newsreader/news/collection/reddit.py | 419 -- src/newsreader/news/collection/tasks.py | 95 - .../news/collection/views/rules.html | 252 +- .../collection/views/subreddit-create.html | 13 - .../collection/views/subreddit-update.html | 14 - .../news/collection/tests/factories.py | 6 - .../news/collection/tests/reddit/__init__.py | 0 .../tests/reddit/builder/__init__.py | 0 .../collection/tests/reddit/builder/mocks.py | 5246 ----------------- .../collection/tests/reddit/builder/tests.py | 472 -- .../tests/reddit/client/__init__.py | 0 .../collection/tests/reddit/client/mocks.py | 160 - .../collection/tests/reddit/client/tests.py | 163 - .../tests/reddit/collector/__init__.py | 0 .../tests/reddit/collector/mocks.py | 1662 ------ .../tests/reddit/collector/tests.py | 201 - .../tests/reddit/stream/__init__.py | 0 .../collection/tests/reddit/stream/mocks.py | 3289 ----------- .../collection/tests/reddit/stream/tests.py | 144 - .../collection/tests/reddit/test_scheduler.py | 142 - .../news/collection/tests/views/test_crud.py | 14 - .../tests/views/test_subreddit_views.py | 133 - src/newsreader/news/collection/urls.py | 13 - .../news/collection/views/__init__.py | 7 +- .../news/collection/views/reddit.py | 27 - src/newsreader/news/core/tests/factories.py | 8 - src/newsreader/news/core/views.py | 3 - src/newsreader/scss/components/index.scss | 2 - .../integrations/_integrations.scss | 13 - .../scss/components/integrations/index.scss | 1 - .../scss/elements/button/_button.scss | 15 +- src/newsreader/scss/pages/index.scss | 1 - .../scss/pages/integrations/index.scss | 5 - src/newsreader/scss/partials/_colors.scss | 3 - 58 files changed, 215 insertions(+), 13102 deletions(-) create mode 100644 src/newsreader/accounts/migrations/0018_remove_user_reddit_access_token_and_more.py delete mode 100644 src/newsreader/accounts/templates/accounts/views/integrations.html delete mode 100644 src/newsreader/accounts/templates/accounts/views/reddit.html delete mode 100644 src/newsreader/accounts/tests/test_integrations.py delete mode 100644 src/newsreader/accounts/views/integrations.py delete mode 100644 src/newsreader/news/collection/forms/reddit.py create mode 100644 src/newsreader/news/collection/migrations/0018_remove_collectionrule_reddit_allow_nfsw_and_more.py delete mode 100644 src/newsreader/news/collection/reddit.py delete mode 100644 src/newsreader/news/collection/templates/news/collection/views/subreddit-create.html delete mode 100644 src/newsreader/news/collection/templates/news/collection/views/subreddit-update.html delete mode 100644 src/newsreader/news/collection/tests/reddit/__init__.py delete mode 100644 src/newsreader/news/collection/tests/reddit/builder/__init__.py delete mode 100644 src/newsreader/news/collection/tests/reddit/builder/mocks.py delete mode 100644 src/newsreader/news/collection/tests/reddit/builder/tests.py delete mode 100644 src/newsreader/news/collection/tests/reddit/client/__init__.py delete mode 100644 src/newsreader/news/collection/tests/reddit/client/mocks.py delete mode 100644 src/newsreader/news/collection/tests/reddit/client/tests.py delete mode 100644 src/newsreader/news/collection/tests/reddit/collector/__init__.py delete mode 100644 src/newsreader/news/collection/tests/reddit/collector/mocks.py delete mode 100644 src/newsreader/news/collection/tests/reddit/collector/tests.py delete mode 100644 src/newsreader/news/collection/tests/reddit/stream/__init__.py delete mode 100644 src/newsreader/news/collection/tests/reddit/stream/mocks.py delete mode 100644 src/newsreader/news/collection/tests/reddit/stream/tests.py delete mode 100644 src/newsreader/news/collection/tests/reddit/test_scheduler.py delete mode 100644 src/newsreader/news/collection/tests/views/test_subreddit_views.py delete mode 100644 src/newsreader/news/collection/views/reddit.py delete mode 100644 src/newsreader/scss/components/integrations/_integrations.scss delete mode 100644 src/newsreader/scss/components/integrations/index.scss delete mode 100644 src/newsreader/scss/pages/integrations/index.scss diff --git a/docker-compose.yml b/docker-compose.yml index f29e719..02f1fab 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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: diff --git a/src/newsreader/accounts/admin.py b/src/newsreader/accounts/admin.py index 38bc2f3..8ae55cb 100644 --- a/src/newsreader/accounts/admin.py +++ b/src/newsreader/accounts/admin.py @@ -11,12 +11,6 @@ class UserAdminForm(UserChangeForm): class Meta: widgets = { "email": forms.EmailInput(attrs={"size": "50"}), - "reddit_access_token": forms.PasswordInput( - attrs={"size": "90"}, render_value=True - ), - "reddit_refresh_token": forms.PasswordInput( - attrs={"size": "90"}, render_value=True - ), } @@ -34,10 +28,6 @@ class UserAdmin(DjangoUserAdmin): _("User settings"), {"fields": ("email", "password", "first_name", "last_name", "is_active")}, ), - ( - _("Reddit settings"), - {"fields": ("reddit_access_token", "reddit_refresh_token")}, - ), ( _("Permission settings"), {"classes": ("collapse",), "fields": ("is_staff", "is_superuser")}, diff --git a/src/newsreader/accounts/migrations/0018_remove_user_reddit_access_token_and_more.py b/src/newsreader/accounts/migrations/0018_remove_user_reddit_access_token_and_more.py new file mode 100644 index 0000000..19bda0c --- /dev/null +++ b/src/newsreader/accounts/migrations/0018_remove_user_reddit_access_token_and_more.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.16 on 2025-03-26 08:46 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('accounts', '0017_auto_20240906_0914'), + ] + + operations = [ + migrations.RemoveField( + model_name='user', + name='reddit_access_token', + ), + migrations.RemoveField( + model_name='user', + name='reddit_refresh_token', + ), + ] diff --git a/src/newsreader/accounts/models.py b/src/newsreader/accounts/models.py index e78786f..15cc97e 100644 --- a/src/newsreader/accounts/models.py +++ b/src/newsreader/accounts/models.py @@ -39,10 +39,6 @@ class UserManager(DjangoUserManager): class User(AbstractUser): email = models.EmailField(_("email address"), unique=True) - # reddit settings - reddit_refresh_token = models.CharField(max_length=255, blank=True, null=True) - reddit_access_token = models.CharField(max_length=255, blank=True, null=True) - # settings auto_mark_read = models.BooleanField( _("Auto read marking"), diff --git a/src/newsreader/accounts/templates/accounts/components/settings-form.html b/src/newsreader/accounts/templates/accounts/components/settings-form.html index f5e7065..6e81e79 100644 --- a/src/newsreader/accounts/templates/accounts/components/settings-form.html +++ b/src/newsreader/accounts/templates/accounts/components/settings-form.html @@ -2,27 +2,23 @@ {% load i18n %} {% block actions %} -
-
- {% include "components/form/confirm-button.html" %} +
+
+ {% include "components/form/confirm-button.html" %} - - {% trans "Change password" %} - + + {% trans "Change password" %} + - {% if favicon_task_allowed %} - - {% trans "Fetch favicons" %} - - {% else %} - - {% endif %} - - - {% trans "Third party integrations" %} - -
-
+ {% if favicon_task_allowed %} + + {% trans "Fetch favicons" %} + + {% else %} + + {% endif %} +
+
{% endblock actions %} diff --git a/src/newsreader/accounts/templates/accounts/views/integrations.html b/src/newsreader/accounts/templates/accounts/views/integrations.html deleted file mode 100644 index 559d3d2..0000000 --- a/src/newsreader/accounts/templates/accounts/views/integrations.html +++ /dev/null @@ -1,47 +0,0 @@ -{% extends "sidebar.html" %} -{% load i18n %} - -{% block content %} -
-
-
- {% include "components/header/header.html" with title="Integrations" only %} - -
-

Reddit

-
- {% if reddit_authorization_url %} - - {% trans "Authorize account" %} - - {% else %} - - {% endif %} - - {% if reddit_refresh_url %} - - {% trans "Refresh token" %} - - {% else %} - - {% endif %} - - {% if reddit_revoke_url %} - - {% trans "Deauthorize account" %} - - {% else %} - - {% endif %} -
-
-
-
-
-{% endblock %} diff --git a/src/newsreader/accounts/templates/accounts/views/reddit.html b/src/newsreader/accounts/templates/accounts/views/reddit.html deleted file mode 100644 index 9fa8378..0000000 --- a/src/newsreader/accounts/templates/accounts/views/reddit.html +++ /dev/null @@ -1,22 +0,0 @@ -{% extends "sidebar.html" %} -{% load i18n %} - -{% block content %} -
-
-
- {% if error %} -

{% trans "Reddit authorization failed" %}

-

{{ error }}

- {% elif access_token and refresh_token %} -

{% trans "Reddit account is linked" %}

-

{% trans "Your reddit account was successfully linked." %}

- {% endif %} - -

- {% trans "Return to integrations page" %} -

-
-
-
-{% endblock %} diff --git a/src/newsreader/accounts/tests/test_integrations.py b/src/newsreader/accounts/tests/test_integrations.py deleted file mode 100644 index de0b142..0000000 --- a/src/newsreader/accounts/tests/test_integrations.py +++ /dev/null @@ -1,275 +0,0 @@ -from unittest.mock import patch -from urllib.parse import urlencode -from uuid import uuid4 - -from django.core.cache import cache -from django.test import TestCase -from django.urls import reverse - -from bs4 import BeautifulSoup - -from newsreader.accounts.tests.factories import UserFactory -from newsreader.news.collection.exceptions import ( - StreamException, - StreamTooManyException, -) - - -class IntegrationsViewTestCase(TestCase): - def setUp(self): - self.user = UserFactory(email="test@test.nl", password="test") - self.client.force_login(self.user) - - self.url = reverse("accounts:settings:integrations") - - -class RedditIntegrationsTestCase(IntegrationsViewTestCase): - def test_reddit_authorization(self): - self.user.reddit_refresh_token = None - self.user.save() - - response = self.client.get(self.url) - - soup = BeautifulSoup(response.content, features="lxml") - button = soup.find("a", class_="link button button--reddit") - - self.assertEquals(button.text.strip(), "Authorize account") - - def test_reddit_refresh_token(self): - self.user.reddit_refresh_token = "jadajadajada" - self.user.reddit_access_token = None - self.user.save() - - response = self.client.get(self.url) - - soup = BeautifulSoup(response.content, features="lxml") - button = soup.find("a", class_="link button button--reddit") - - self.assertEquals(button.text.strip(), "Refresh token") - - def test_reddit_revoke(self): - self.user.reddit_refresh_token = "jadajadajada" - self.user.reddit_access_token = None - self.user.save() - - response = self.client.get(self.url) - - soup = BeautifulSoup(response.content, features="lxml") - buttons = soup.find_all("a", class_="link button button--reddit") - - self.assertIn( - "Deauthorize account", [button.text.strip() for button in buttons] - ) - - -class RedditTemplateViewTestCase(TestCase): - def setUp(self): - self.user = UserFactory(email="test@test.nl", password="test") - self.client.force_login(self.user) - - self.base_url = reverse("accounts:settings:reddit-template") - self.state = str(uuid4()) - - self.patch = patch("newsreader.news.collection.reddit.post") - self.mocked_post = self.patch.start() - - def tearDown(self): - patch.stopall() - - def test_simple(self): - response = self.client.get(self.base_url) - - self.assertEquals(response.status_code, 200) - self.assertContains(response, "Return to integrations page") - - def test_successful_authorization(self): - self.mocked_post.return_value.json.return_value = { - "access_token": "1001010412", - "refresh_token": "134510143", - } - - cache.set(f"{self.user.email}-reddit-auth", self.state) - - params = {"state": self.state, "code": "Valid code"} - url = f"{self.base_url}?{urlencode(params)}" - - response = self.client.get(url) - - self.mocked_post.assert_called_once() - - self.assertEquals(response.status_code, 200) - self.assertContains(response, "Your reddit account was successfully linked.") - - self.user.refresh_from_db() - - self.assertEquals(self.user.reddit_access_token, "1001010412") - self.assertEquals(self.user.reddit_refresh_token, "134510143") - - self.assertEquals(cache.get(f"{self.user.email}-reddit-auth"), None) - - def test_error(self): - params = {"error": "Denied authorization"} - - url = f"{self.base_url}?{urlencode(params)}" - - response = self.client.get(url) - - self.assertEquals(response.status_code, 200) - self.assertContains(response, "Denied authorization") - - def test_invalid_state(self): - cache.set(f"{self.user.email}-reddit-auth", str(uuid4())) - - params = {"code": "Valid code", "state": "Invalid state"} - - url = f"{self.base_url}?{urlencode(params)}" - - response = self.client.get(url) - - self.assertEquals(response.status_code, 200) - self.assertContains( - response, "The saved state for Reddit authorization did not match" - ) - - def test_stream_error(self): - self.mocked_post.side_effect = StreamTooManyException - - cache.set(f"{self.user.email}-reddit-auth", self.state) - - params = {"state": self.state, "code": "Valid code"} - url = f"{self.base_url}?{urlencode(params)}" - - response = self.client.get(url) - - self.mocked_post.assert_called_once() - - self.assertEquals(response.status_code, 200) - self.assertContains(response, "Too many requests") - - self.user.refresh_from_db() - - self.assertEquals(self.user.reddit_access_token, None) - self.assertEquals(self.user.reddit_refresh_token, None) - - self.assertEquals(cache.get(f"{self.user.email}-reddit-auth"), self.state) - - def test_unexpected_json(self): - self.mocked_post.return_value.json.return_value = {"message": "Happy eastern"} - - cache.set(f"{self.user.email}-reddit-auth", self.state) - - params = {"state": self.state, "code": "Valid code"} - url = f"{self.base_url}?{urlencode(params)}" - - response = self.client.get(url) - - self.mocked_post.assert_called_once() - - self.assertEquals(response.status_code, 200) - self.assertContains(response, "Access and refresh token not found in response") - - self.user.refresh_from_db() - - self.assertEquals(self.user.reddit_access_token, None) - self.assertEquals(self.user.reddit_refresh_token, None) - - self.assertEquals(cache.get(f"{self.user.email}-reddit-auth"), self.state) - - -class RedditTokenRedirectViewTestCase(TestCase): - def setUp(self): - self.user = UserFactory(email="test@test.nl", password="test") - self.client.force_login(self.user) - - self.patch = patch("newsreader.accounts.views.integrations.RedditTokenTask") - self.mocked_task = self.patch.start() - - def tearDown(self): - cache.clear() - - def test_simple(self): - response = self.client.get(reverse("accounts:settings:reddit-refresh")) - - self.assertRedirects(response, reverse("accounts:settings:integrations")) - - self.mocked_task.delay.assert_called_once_with(self.user.pk) - - self.assertEquals(1, cache.get(f"{self.user.email}-reddit-refresh")) - - def test_not_active(self): - cache.set(f"{self.user.email}-reddit-refresh", 1) - - response = self.client.get(reverse("accounts:settings:reddit-refresh")) - - self.assertRedirects(response, reverse("accounts:settings:integrations")) - - self.mocked_task.delay.assert_not_called() - - -class RedditRevokeRedirectViewTestCase(TestCase): - def setUp(self): - self.user = UserFactory(email="test@test.nl", password="test") - self.client.force_login(self.user) - - self.patch = patch("newsreader.accounts.views.integrations.revoke_reddit_token") - self.mocked_revoke = self.patch.start() - - def test_simple(self): - self.user.reddit_access_token = "jadajadajada" - self.user.reddit_refresh_token = "jadajadajada" - self.user.save() - - self.mocked_revoke.return_value = True - - response = self.client.get(reverse("accounts:settings:reddit-revoke")) - - self.assertRedirects(response, reverse("accounts:settings:integrations")) - - self.mocked_revoke.assert_called_once_with(self.user) - - self.user.refresh_from_db() - - self.assertEquals(self.user.reddit_access_token, None) - self.assertEquals(self.user.reddit_refresh_token, None) - - def test_no_refresh_token(self): - self.user.reddit_refresh_token = None - self.user.save() - - response = self.client.get(reverse("accounts:settings:reddit-revoke")) - - self.assertRedirects(response, reverse("accounts:settings:integrations")) - - self.mocked_revoke.assert_not_called() - - def test_unsuccessful_response(self): - self.user.reddit_access_token = "jadajadajada" - self.user.reddit_refresh_token = "jadajadajada" - self.user.save() - - self.mocked_revoke.return_value = False - - response = self.client.get(reverse("accounts:settings:reddit-revoke")) - - self.assertRedirects(response, reverse("accounts:settings:integrations")) - - self.user.refresh_from_db() - - self.assertEquals(self.user.reddit_access_token, "jadajadajada") - self.assertEquals(self.user.reddit_refresh_token, "jadajadajada") - - def test_stream_exception(self): - self.user.reddit_access_token = "jadajadajada" - self.user.reddit_refresh_token = "jadajadajada" - self.user.save() - - self.mocked_revoke.side_effect = StreamException - - response = self.client.get(reverse("accounts:settings:reddit-revoke")) - - self.assertRedirects(response, reverse("accounts:settings:integrations")) - - self.user.refresh_from_db() - - self.assertEquals(self.user.reddit_access_token, "jadajadajada") - self.assertEquals(self.user.reddit_refresh_token, "jadajadajada") diff --git a/src/newsreader/accounts/urls.py b/src/newsreader/accounts/urls.py index b363f82..18a9b21 100644 --- a/src/newsreader/accounts/urls.py +++ b/src/newsreader/accounts/urls.py @@ -3,7 +3,6 @@ from django.urls import include, path from newsreader.accounts.views import ( FaviconRedirectView, - IntegrationsView, LoginView, LogoutView, PasswordChangeView, @@ -11,33 +10,11 @@ from newsreader.accounts.views import ( PasswordResetConfirmView, PasswordResetDoneView, PasswordResetView, - RedditRevokeRedirectView, - RedditTemplateView, - RedditTokenRedirectView, SettingsView, ) settings_patterns = [ - # Integrations - path( - "integrations/reddit/callback/", - login_required(RedditTemplateView.as_view()), - name="reddit-template", - ), - path( - "integrations/reddit/refresh/", - login_required(RedditTokenRedirectView.as_view()), - name="reddit-refresh", - ), - path( - "integrations/reddit/revoke/", - login_required(RedditRevokeRedirectView.as_view()), - name="reddit-revoke", - ), - path( - "integrations/", login_required(IntegrationsView.as_view()), name="integrations" - ), # Misc path("favicon/", login_required(FaviconRedirectView.as_view()), name="favicon"), path("", login_required(SettingsView.as_view()), name="home"), diff --git a/src/newsreader/accounts/views/__init__.py b/src/newsreader/accounts/views/__init__.py index e62755c..d20e6bb 100644 --- a/src/newsreader/accounts/views/__init__.py +++ b/src/newsreader/accounts/views/__init__.py @@ -1,11 +1,5 @@ from newsreader.accounts.views.auth import LoginView, LogoutView from newsreader.accounts.views.favicon import FaviconRedirectView -from newsreader.accounts.views.integrations import ( - IntegrationsView, - RedditRevokeRedirectView, - RedditTemplateView, - RedditTokenRedirectView, -) from newsreader.accounts.views.password import ( PasswordChangeView, PasswordResetCompleteView, @@ -20,10 +14,6 @@ __all__ = [ "LoginView", "LogoutView", "FaviconRedirectView", - "IntegrationsView", - "RedditRevokeRedirectView", - "RedditTemplateView", - "RedditTokenRedirectView", "PasswordChangeView", "PasswordResetCompleteView", "PasswordResetConfirmView", diff --git a/src/newsreader/accounts/views/integrations.py b/src/newsreader/accounts/views/integrations.py deleted file mode 100644 index 1235195..0000000 --- a/src/newsreader/accounts/views/integrations.py +++ /dev/null @@ -1,156 +0,0 @@ -import logging - -from django.contrib import messages -from django.core.cache import cache -from django.urls import reverse_lazy -from django.utils.translation import gettext as _ -from django.views.generic import RedirectView, TemplateView - -from newsreader.news.collection.exceptions import StreamException -from newsreader.news.collection.reddit import ( - get_reddit_access_token, - get_reddit_authorization_url, - revoke_reddit_token, -) -from newsreader.news.collection.tasks import RedditTokenTask -from newsreader.utils.views import NavListMixin - - -logger = logging.getLogger(__name__) - - -class IntegrationsView(NavListMixin, TemplateView): - template_name = "accounts/views/integrations.html" - - def get_context_data(self, **kwargs): - return { - **super().get_context_data(**kwargs), - **self.get_reddit_context(**kwargs), - } - - def get_reddit_context(self, **kwargs): - user = self.request.user - reddit_authorization_url = None - reddit_refresh_url = None - - reddit_task_active = cache.get(f"{user.email}-reddit-refresh") - - if ( - user.reddit_refresh_token - and not user.reddit_access_token - and not reddit_task_active - ): - reddit_refresh_url = reverse_lazy("accounts:settings:reddit-refresh") - - if not user.reddit_refresh_token: - reddit_authorization_url = get_reddit_authorization_url(user) - - return { - "reddit_authorization_url": reddit_authorization_url, - "reddit_refresh_url": reddit_refresh_url, - "reddit_revoke_url": ( - reverse_lazy("accounts:settings:reddit-revoke") - if not reddit_authorization_url - else None - ), - } - - -class RedditTemplateView(NavListMixin, TemplateView): - template_name = "accounts/views/reddit.html" - - def get(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - - error = request.GET.get("error", None) - state = request.GET.get("state", None) - code = request.GET.get("code", None) - - if error: - return self.render_to_response({**context, "error": error}) - - if not code or not state: - return self.render_to_response(context) - - cached_state = cache.get(f"{request.user.email}-reddit-auth") - - if state != cached_state: - return self.render_to_response( - { - **context, - "error": _( - "The saved state for Reddit authorization did not match" - ), - } - ) - - try: - access_token, refresh_token = get_reddit_access_token(code, request.user) - - return self.render_to_response( - { - **context, - "access_token": access_token, - "refresh_token": refresh_token, - } - ) - except StreamException as e: - return self.render_to_response({**context, "error": str(e)}) - except KeyError: - return self.render_to_response( - { - **context, - "error": _("Access and refresh token not found in response"), - } - ) - - -class RedditTokenRedirectView(RedirectView): - url = reverse_lazy("accounts:settings:integrations") - - def get(self, request, *args, **kwargs): - response = super().get(request, *args, **kwargs) - - user = request.user - task_active = cache.get(f"{user.email}-reddit-refresh") - - if not task_active: - RedditTokenTask.delay(user.pk) - messages.success(request, _("Access token is being retrieved")) - cache.set(f"{user.email}-reddit-refresh", 1, 300) - return response - - messages.error(request, _("Unable to retrieve token")) - return response - - -class RedditRevokeRedirectView(RedirectView): - url = reverse_lazy("accounts:settings:integrations") - - def get(self, request, *args, **kwargs): - response = super().get(request, *args, **kwargs) - - user = request.user - - if not user.reddit_refresh_token: - messages.error(request, _("No reddit account is linked to this account")) - return response - - try: - is_revoked = revoke_reddit_token(user) - except StreamException: - logger.exception(f"Unable to revoke reddit token for {user.pk}") - - messages.error(request, _("Unable to revoke reddit token")) - return response - - if not is_revoked: - messages.error(request, _("Unable to revoke reddit token")) - return response - - user.reddit_access_token = None - user.reddit_refresh_token = None - user.save() - - messages.success(request, _("Reddit account deathorized")) - return response diff --git a/src/newsreader/conf/base.py b/src/newsreader/conf/base.py index d17234a..5bee027 100644 --- a/src/newsreader/conf/base.py +++ b/src/newsreader/conf/base.py @@ -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" diff --git a/src/newsreader/conf/production.py b/src/newsreader/conf/production.py index 8615aa2..ea22f30 100644 --- a/src/newsreader/conf/production.py +++ b/src/newsreader/conf/production.py @@ -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" diff --git a/src/newsreader/js/pages/homepage/App.js b/src/newsreader/js/pages/homepage/App.js index 08c0330..e840407 100644 --- a/src/newsreader/js/pages/homepage/App.js +++ b/src/newsreader/js/pages/homepage/App.js @@ -33,7 +33,6 @@ class App extends React.Component {