rss-reader
106 строк · 3.6 Кб
1import uniqueId from 'lodash/uniqueId';2import axios from 'axios';3import urlValidator from './validator';4import parserRss from './parser';5import watcher from './view';6
7const refreshTiming = 5000;8
9const errorMessage = (error) => {10switch (error.name) {11case 'ParsingError':12return 'errors.incorrectRss';13case 'AxiosError':14return 'errors.networkError';15default:16return error.message;17}18};19
20const addProxy = (url) => {21const proxyUrl = new URL('/get', 'https://allorigins.hexlet.app');22proxyUrl.searchParams.append('disableCache', 'true');23proxyUrl.searchParams.append('url', url);24return proxyUrl.toString();25};26
27const getData = (url) => axios.get(addProxy(url), { timeout: 5000 })28.catch((error) => { throw error; });29
30const getPosts = (feedId, data) => {31const posts = [];32data.items.forEach((item) => posts.unshift({ id: uniqueId(), feedId, ...item }));33return posts;34};35
36const updateRss = (watchedState) => {37const { feeds, posts } = watchedState.data;38feeds.forEach((feed) => {39const feedPosts = posts.filter((post) => post.feedId === feed.id);40const feedId = feed.id;41getData(feed.link)42.then((rss) => parserRss(rss))43.then((data) => {44const newPosts = getPosts(feedId, data);45const isNewPost = (newPost, oldPosts) => !oldPosts.some((old) => old.link === newPost.link);46const resultPost = newPosts.filter((newPost) => isNewPost(newPost, feedPosts));47watchedState.data.posts.unshift(...resultPost);48})49.catch((error) => { console.error(error); });50});51setTimeout(() => updateRss(watchedState), refreshTiming);52};53
54const processRssData = (watchedState) => {55watchedState.state = 'processing';56watchedState.formState.isValid = 'waiting';57const url = watchedState.currentUrl;58return getData(url)59.then((rss) => parserRss(rss))60.then((data) => {61const feedId = uniqueId();62watchedState.data.feeds.push({ id: feedId, ...data.feeds, link: url });63const currentPosts = getPosts(feedId, data);64watchedState.data.posts = [...currentPosts, ...watchedState.data.posts];65watchedState.formState.isValid = 'valid';66watchedState.state = 'processed';67});68};69
70export default (state, i18next) => {71const elements = {72rssForm: document.querySelector('.rss-form'),73input: document.querySelector('input[id="url-input"]'),74button: document.querySelector('button[aria-label="add"]'),75modal: document.querySelector('div[id="modal"]'),76feeds: document.querySelector('.feeds'),77posts: document.querySelector('.posts'),78};79const watchedState = watcher(state, i18next, elements);80const handleSubmit = (event) => {81event.preventDefault();82const formData = new FormData(elements.rssForm);83const inputUrl = formData.get('url');84watchedState.currentUrl = inputUrl;85urlValidator(watchedState.data.feeds, inputUrl)86.then(() => processRssData(watchedState))87.catch((error) => {88watchedState.formState.errors.push(errorMessage(error));89watchedState.formState.isValid = 'invalid';90watchedState.state = 'failed';91console.error(error);92});93};94const handlePostClick = (event) => {95const element = event.target;96const postId = event.target.dataset.id;97if (element.type === 'button') {98const newViewedPost = state.data.posts.find((obj) => obj.id === postId);99watchedState.uiState.vievedPost = newViewedPost;100}101watchedState.uiState.viewedPostsId.add(postId);102};103elements.rssForm.addEventListener('submit', handleSubmit);104elements.posts.addEventListener('click', handlePostClick);105updateRss(watchedState);106};107