From fc7cbbb457399db12ad8eddbde5e7be922f11330 Mon Sep 17 00:00:00 2001 From: mgabdev <> Date: Fri, 6 Nov 2020 23:29:35 -0600 Subject: [PATCH] Added WIP for news redux actions (prev. gab actions) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Added: - WIP for news redux actions (prev. gab actions) - renamed gab redux actions to "news" • Todo: - Add RSS expanding in news action - Complete leadline setting in news reducer --- app/javascript/gabsocial/actions/gab.js | 79 ---------- app/javascript/gabsocial/actions/news.js | 152 +++++++++++++++++++ app/javascript/gabsocial/reducers/gab.js | 76 ---------- app/javascript/gabsocial/reducers/index.js | 4 +- app/javascript/gabsocial/reducers/news.js | 161 +++++++++++++++++++++ 5 files changed, 315 insertions(+), 157 deletions(-) delete mode 100644 app/javascript/gabsocial/actions/gab.js create mode 100644 app/javascript/gabsocial/actions/news.js delete mode 100644 app/javascript/gabsocial/reducers/gab.js create mode 100644 app/javascript/gabsocial/reducers/news.js diff --git a/app/javascript/gabsocial/actions/gab.js b/app/javascript/gabsocial/actions/gab.js deleted file mode 100644 index 502aef3d..00000000 --- a/app/javascript/gabsocial/actions/gab.js +++ /dev/null @@ -1,79 +0,0 @@ -import api from '../api' -import axios from 'axios' - -export const GAB_TRENDS_RESULTS_FETCH_REQUEST = 'GAB_TRENDS_RESULTS_FETCH_REQUEST' -export const GAB_TRENDS_RESULTS_FETCH_SUCCESS = 'GAB_TRENDS_RESULTS_FETCH_SUCCESS' -export const GAB_TRENDS_RESULTS_FETCH_FAIL = 'GAB_TRENDS_RESULTS_FETCH_FAIL' - -export const GAB_NEWS_RESULTS_FETCH_REQUEST = 'GAB_NEWS_RESULTS_FETCH_REQUEST' -export const GAB_NEWS_RESULTS_FETCH_SUCCESS = 'GAB_NEWS_RESULTS_FETCH_SUCCESS' -export const GAB_NEWS_RESULTS_FETCH_FAIL = 'GAB_NEWS_RESULTS_FETCH_FAIL' - -export const fetchGabTrends = (feedType) => { - return function (dispatch, getState) { - dispatch(fetchGabTrendsRequest(feedType)) - - const url = feedType === 'partner' ? 'https://trends.gab.com/partner' : 'https://trends.gab.com/trend-feed/json' - - axios.get(url).then((response) => { - dispatch(fetchGabTrendsSuccess(response.data, feedType)) - }).catch(function (error) { - dispatch(fetchGabTrendsFail(error, feedType)) - }) - } -} - -function fetchGabTrendsRequest(feedType) { - return { - type: GAB_TRENDS_RESULTS_FETCH_REQUEST, - feedType, - } -} - -function fetchGabTrendsSuccess(items, feedType) { - return { - type: GAB_TRENDS_RESULTS_FETCH_SUCCESS, - items, - feedType, - } -} - -function fetchGabTrendsFail(error, feedType) { - return { - type: GAB_TRENDS_RESULTS_FETCH_FAIL, - error, - feedType, - } -} - -export const fetchGabNews = () => { - return function (dispatch) { - dispatch(fetchGabNewsRequest()) - - axios.get('https://news.gab.com/feed/json').then((response) => { - dispatch(fetchGabNewsSuccess(response.data)) - }).catch(function (error) { - dispatch(fetchGabNewsFail(error)) - }) - } -} - -function fetchGabNewsRequest() { - return { - type: GAB_NEWS_RESULTS_FETCH_REQUEST, - } -} - -function fetchGabNewsSuccess(items) { - return { - type: GAB_NEWS_RESULTS_FETCH_SUCCESS, - items, - } -} - -function fetchGabNewsFail(error) { - return { - type: GAB_NEWS_RESULTS_FETCH_FAIL, - error, - } -} \ No newline at end of file diff --git a/app/javascript/gabsocial/actions/news.js b/app/javascript/gabsocial/actions/news.js new file mode 100644 index 00000000..84736ffc --- /dev/null +++ b/app/javascript/gabsocial/actions/news.js @@ -0,0 +1,152 @@ +import api from '../api' +import axios from 'axios' +import { importFetchedStatuses } from './importer' + +export const GAB_TRENDS_FETCH_REQUEST = 'GAB_TRENDS_FETCH_REQUEST' +export const GAB_TRENDS_FETCH_SUCCESS = 'GAB_TRENDS_FETCH_SUCCESS' +export const GAB_TRENDS_FETCH_FAIL = 'GAB_TRENDS_FETCH_FAIL' + +export const GAB_TREND_FEED_EXPAND_REQUEST = 'GAB_TREND_FEED_EXPAND_REQUEST' +export const GAB_TREND_FEED_EXPAND_SUCCESS = 'GAB_TREND_FEED_EXPAND_SUCCESS' +export const GAB_TREND_FEED_EXPAND_FAIL = 'GAB_TREND_FEED_EXPAND_FAIL' + +export const GAB_NEWS_FETCH_REQUEST = 'GAB_NEWS_FETCH_REQUEST' +export const GAB_NEWS_FETCH_SUCCESS = 'GAB_NEWS_FETCH_SUCCESS' +export const GAB_NEWS_FETCH_FAIL = 'GAB_NEWS_FETCH_FAIL' + +export const LATEST_GAB_STATUSES_FETCH_REQUEST = 'LATEST_GAB_STATUSES_FETCH_REQUEST' +export const LATEST_GAB_STATUSES_FETCH_SUCCESS = 'LATEST_GAB_STATUSES_FETCH_SUCCESS' +export const LATEST_GAB_STATUSES_FETCH_FAIL = 'LATEST_GAB_STATUSES_FETCH_FAIL' + +/** + * + */ +export const fetchGabTrends = () => (dispatch, getState) => { + // If fetched once, dont fetch again + const isFetched = getState().getIn(['news', 'trends_breaking', 'isFetched'], false) + if (isFetched) return + + dispatch(fetchGabTrendsRequest()) + + // const url = 'https://trends.gab.com/partner' + api(getState).get(`/api/v1/gab_trends?type=partner`).then((response) => { + // axios.get(url).then((response) => { + dispatch(fetchGabTrendsSuccess(response.data)) + }).catch((error) => { + dispatch(fetchGabTrendsFail(error)) + }) +} + +const fetchGabTrendsRequest = () => ({ + type: GAB_TRENDS_FETCH_REQUEST, +}) + +const fetchGabTrendsSuccess = (items) => ({ + type: GAB_TRENDS_FETCH_SUCCESS, + items, +}) + +const fetchGabTrendsFail = (error) => ({ + type: GAB_TRENDS_FETCH_FAIL, + error, +}) + +/** + * + */ +export const expandGabTrendsFeed = (feedId, page = 0) => (dispatch, getState) => { + dispatch(expandGabTrendsFeedRequest(feedId, page)) + + // const url = `http://trends.gab.com/feed/${feedId}?fmt=json` + api(getState).get(`/api/v1/gab_trends?type=rss`).then((response) => { + // axios.get(url).then((response) => { + dispatch(expandGabTrendsFeedSuccess(response.data, feedId, page)) + }).catch((error) => { + dispatch(expandGabTrendsFeedFail(error, feedId, page)) + }) +} + +const expandGabTrendsFeedRequest = (feedId, page) => ({ + type: GAB_TREND_FEED_EXPAND_REQUEST, + feedId, + page, +}) + +const expandGabTrendsFeedSuccess = (items, feedId, page) => ({ + type: GAB_TREND_FEED_EXPAND_SUCCESS, + items, + feedId, + page, +}) + +const expandGabTrendsFeedFail = (error, feedId, page) => ({ + type: GAB_TREND_FEED_EXPAND_FAIL, + error, + feedId, + page, +}) + +/** + * + */ +export const fetchGabNews = () => (dispatch, getState) => { + // If fetched once, dont fetch again + const isFetched = getState().getIn(['news', 'gab_news', 'isFetched'], false) + if (isFetched) return + + dispatch(fetchGabNewsRequest()) + + // const url = 'https://news.gab.com/feed/json' + api(getState).get(`/api/v1/gab_trends?type=news`).then((response) => { + // axios.get(url).then((response) => { + dispatch(fetchGabNewsSuccess(response.data.items)) + }).catch((error) => { + dispatch(fetchGabNewsFail(error)) + }) +} + +const fetchGabNewsRequest = () => ({ + type: GAB_NEWS_FETCH_REQUEST, +}) + +const fetchGabNewsSuccess = (items) => ({ + type: GAB_NEWS_FETCH_SUCCESS, + items, +}) + +const fetchGabNewsFail = (error) => ({ + type: GAB_NEWS_FETCH_FAIL, + error, +}) + +/** + * + */ +export const fetchLatestFromGabTimeline = () => (dispatch, getState) => { + // If fetched once, dont fetch again + const isFetched = getState().getIn(['news', 'latest_from_gab', 'isFetched'], false) + if (isFetched) return + + dispatch(fetchLatestFromGabTimelineRequest()) + + api(getState).get(`/api/v1/popular_links?type=gab`).then((response) => { + dispatch(importFetchedStatuses(response.data)) + dispatch(fetchLatestFromGabTimelineSuccess(response.data)) + }).catch((error) => { + dispatch(fetchLatestFromGabTimelineFail(error)) + }) +} + +const fetchLatestFromGabTimelineRequest = () => ({ + type: LATEST_GAB_STATUSES_FETCH_REQUEST +}) + +const fetchLatestFromGabTimelineSuccess = (statuses) => ({ + type: LATEST_GAB_STATUSES_FETCH_SUCCESS, + statuses, +}) + +const fetchLatestFromGabTimelineFail = (error) => ({ + type: LATEST_GAB_STATUSES_FETCH_FAIL, + error, +}) \ No newline at end of file diff --git a/app/javascript/gabsocial/reducers/gab.js b/app/javascript/gabsocial/reducers/gab.js deleted file mode 100644 index 77e08128..00000000 --- a/app/javascript/gabsocial/reducers/gab.js +++ /dev/null @@ -1,76 +0,0 @@ -import { - GAB_TRENDS_RESULTS_FETCH_REQUEST, - GAB_TRENDS_RESULTS_FETCH_SUCCESS, - GAB_TRENDS_RESULTS_FETCH_FAIL, - GAB_NEWS_RESULTS_FETCH_REQUEST, - GAB_NEWS_RESULTS_FETCH_SUCCESS, - GAB_NEWS_RESULTS_FETCH_FAIL, -} from '../actions/gab' -import { - Map as ImmutableMap, - List as ImmutableList, - fromJS, -} from 'immutable' - -const initialState = ImmutableMap({ - feed: ImmutableMap({ - items: ImmutableList(), - isLoading: false, - isError: false, - }), - partner: ImmutableMap({ - items: {}, - isLoading: false, - isError: false, - }), - news: ImmutableMap({ - items: {}, - isLoading: false, - isError: false, - }), -}) - -const normalizeList = (state, type, items) => { - return state.set(type, ImmutableMap({ - items: fromJS(items), - isLoading: false, - isError: false, - })) -} - -const setListFailed = (state, type) => { - return state.set(type, ImmutableMap({ - items: ImmutableList(), - isLoading: false, - isError: true, - })) -} - -export default function (state = initialState, action) { - switch (action.type) { - case GAB_TRENDS_RESULTS_FETCH_REQUEST: - return state.setIn([action.feedType, 'isLoading'], true); - case GAB_TRENDS_RESULTS_FETCH_SUCCESS: - if (action.feedType === 'feed') { - return normalizeList(state, action.feedType, action.items.items) - } else if (action.feedType === 'partner') { - return state.set('partner', ImmutableMap({ - items: action.items['trends'] || {}, - isLoading: false, - isError: false, - })) - } - - return state - case GAB_TRENDS_RESULTS_FETCH_FAIL: - return setListFailed(state, action.feedType) - case GAB_NEWS_RESULTS_FETCH_REQUEST: - return state.setIn(['news', 'isLoading'], true); - case GAB_NEWS_RESULTS_FETCH_SUCCESS: - return normalizeList(state, 'news', action.items) - case GAB_NEWS_RESULTS_FETCH_FAIL: - return setListFailed(state, 'news') - default: - return state - } -} \ No newline at end of file diff --git a/app/javascript/gabsocial/reducers/index.js b/app/javascript/gabsocial/reducers/index.js index 92fa9ddf..9195d1e4 100644 --- a/app/javascript/gabsocial/reducers/index.js +++ b/app/javascript/gabsocial/reducers/index.js @@ -7,7 +7,6 @@ import contexts from './contexts' import conversations from './conversations' import custom_emojis from './custom_emojis' import filters from './filters' -import gab from './gab' import groups from './groups' import group_categories from './group_categories' import group_editor from './group_editor' @@ -23,6 +22,7 @@ import media_attachments from './media_attachments' import meta from './meta' import modal from './modal' import mutes from './mutes' +import news from './news' import notifications from './notifications' import polls from './polls' import popover from './popover' @@ -52,7 +52,6 @@ const reducers = { conversations, custom_emojis, filters, - gab, groups, group_categories, group_editor, @@ -69,6 +68,7 @@ const reducers = { meta, modal, mutes, + news, notifications, polls, popover, diff --git a/app/javascript/gabsocial/reducers/news.js b/app/javascript/gabsocial/reducers/news.js new file mode 100644 index 00000000..6d951ef3 --- /dev/null +++ b/app/javascript/gabsocial/reducers/news.js @@ -0,0 +1,161 @@ +import { + GAB_TRENDS_FETCH_REQUEST, + GAB_TRENDS_FETCH_SUCCESS, + GAB_TRENDS_FETCH_FAIL, + GAB_TREND_FEED_EXPAND_REQUEST, + GAB_TREND_FEED_EXPAND_SUCCESS, + GAB_TREND_FEED_EXPAND_FAIL, + GAB_NEWS_FETCH_REQUEST, + GAB_NEWS_FETCH_SUCCESS, + GAB_NEWS_FETCH_FAIL, + LATEST_GAB_STATUSES_FETCH_REQUEST, + LATEST_GAB_STATUSES_FETCH_SUCCESS, + LATEST_GAB_STATUSES_FETCH_FAIL, +} from '../actions/news' +import { + Map as ImmutableMap, + List as ImmutableList, + fromJS, +} from 'immutable' + +const defaultMap = ImmutableMap({ + isLoading: false, + isFetched: false, + items: ImmutableList(), +}) + +const initialState = ImmutableMap({ + trends_leadline: ImmutableMap({ + title: null, + image: null, + trends_url: null, + }), + trends_headlines: defaultMap, + trends_breaking: defaultMap, + gab_news: defaultMap, + latest_from_gab: defaultMap, + trends_feeds: ImmutableMap(), // ex: { 'feed_id_1': defaultMap, 'feed_id_2': defaultMap, ... } +}) + +const normalizeHeadlineItem = (item) => { + return ImmutableMap({ + trend_id: item._id, + title: item.title, + trends_url: `https://trends.gab.com/trend?url=${item.href}`, + }) +} + +const normalizeTrendsItem = (item) => { + return ImmutableMap({ + title: `${item.pagePreview.title}`.trim(), + description: `${item.pagePreview.description}`.trim(), + publish_date: item.pubDate, + image: Array.isArray(item.pagePreview.images) ? item.pagePreview.images[0] : null, // : todo : proxy + feed_title: item.feed.title, + feed_slug: item.feed.slug, + feed_base_url: `${item.feed.url}`.replace('www.', '').replace('https://', '').replace('http://', '').replace('/', ''), + trend_feed_id: item.feed._id, + trend_id: item._id, + trends_url: `https://trends.gab.com/trend?url=${item.link}`, + }) +} + +const normalizeNewsItem = (item) => { + return ImmutableMap({ + id: item.id, + url: item.url, + title: item.title, + image: item.image, + publish_date: item.date_published, + }) +} + +const setStateKeysOnRequest = (state, keys) => { + return state.withMutations((map) => { + keys.map((key) => map.setIn([key, 'isLoading'], true)) + }) +} + +const setStateKeysOnFail = (state, keys) => { + return state.withMutations((map) => { + keys.map((key) => { + map.setIn([key, 'isLoading'], false) + map.setIn([key, 'isFetched'], true) + map.setIn([key, 'items'], ImmutableList()) + }) + }) +} + +const setStateKeysOnSuccess = (state, keysAndData) => { + return state.withMutations((map) => { + Object.keys(keysAndData).map((key) => { + map.setIn([key, 'isLoading'], false) + map.setIn([key, 'isFetched'], true) + map.setIn([key, 'items'], keysAndData[key]) + }) + }) +} + +export default function (state = initialState, action) { + switch (action.type) { + case GAB_TRENDS_FETCH_REQUEST: + return setStateKeysOnRequest(state, ['trends_headlines', 'trends_breaking']) + case GAB_TRENDS_FETCH_FAIL: + return setStateKeysOnFail(state, ['trends_headlines', 'trends_breaking']) + case GAB_TRENDS_FETCH_SUCCESS: + let trendsFetchData = {} + try { + trendsFetchData.trends_headlines = ImmutableList(action.items.trends.leadHeadlines.map((item) => normalizeHeadlineItem(item))) + trendsFetchData.trends_breaking = ImmutableList(action.items.trends.rssFeedItems.map((item) => normalizeTrendsItem(item))) + } catch (error) { + trendsFetchData = { + breakingItems: ImmutableList(), + headlineItems: ImmutableList(), + } + } + // : todo : + // trends_leadline: ImmutableMap({ + // title: null, + // image: null, + // trends_url: null, + // }), + + return setStateKeysOnSuccess(state, trendsFetchData) + + // + case LATEST_GAB_STATUSES_FETCH_REQUEST: + return setStateKeysOnRequest(state, ['latest_from_gab']) + case LATEST_GAB_STATUSES_FETCH_FAIL: + return setStateKeysOnFail(state, ['latest_from_gab']) + case LATEST_GAB_STATUSES_FETCH_SUCCESS: + let latestGabStatusData = {} + try { + latestGabStatusData.latest_from_gab = ImmutableList(action.statuses.map((status) => status.id)) + } catch (error) { + latestGabStatusData = { + latest_from_gab: ImmutableList(), + } + } + return setStateKeysOnSuccess(state, latestGabStatusData) + + // + case GAB_NEWS_FETCH_REQUEST: + return setStateKeysOnRequest(state, ['gab_news']) + case GAB_NEWS_FETCH_FAIL: + return setStateKeysOnFail(state, ['gab_news']) + case GAB_NEWS_FETCH_SUCCESS: + let latestGabNewsData = {} + try { + latestGabNewsData.gab_news = ImmutableList(action.items.map((item) => normalizeNewsItem(item))) + } catch (error) { + console.log("news reducer error: ", error) + latestGabNewsData = { + gab_news: ImmutableList(), + } + } + return setStateKeysOnSuccess(state, latestGabNewsData) + + default: + return state + } +}