diff --git a/.gitignore b/.gitignore index 4d29575..8a68fa5 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,10 @@ npm-debug.log* yarn-debug.log* yarn-error.log* +/.idea/.gitignore +/.idea/d.buzz-blog.iml +/.idea/inspectionProfiles/Project_Default.xml +/.idea/modules.xml +/.idea/vcs.xml +/.idea/codeStyles/codeStyleConfig.xml +/.idea/codeStyles/Project.xml diff --git a/package.json b/package.json index ff489ec..c9d9fac 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "crypto-js": "^4.0.0", "diff-match-patch": "^1.0.5", "emoji-mart": "^3.0.1", - "react-giphy-searchbox": "^1.5.4", "heic2any": "^0.0.4", "immutable": "^4.0.0-rc.12", "lottie-react": "^2.1.0", @@ -36,6 +35,7 @@ "react-dnd-html5-backend": "^3.0.2", "react-dom": "^16.13.1", "react-fastclick": "^3.0.2", + "react-giphy-searchbox": "^1.5.4", "react-helmet": "^6.1.0", "react-icons": "^4.2.0", "react-infinite-scroll-component": "^6.0.0", @@ -50,6 +50,7 @@ "react-router-dom": "^5.2.0", "react-router-last-location": "^2.0.1", "react-scripts": "^3.4.3", + "react-social-media-embed": "^2.5.9", "react-sticky": "^6.0.3", "react-tag-input": "^6.2.1", "react-textarea-autosize": "^8.3.0", diff --git a/src/components/common/MarkdownViewer/index.js b/src/components/common/MarkdownViewer/index.js index 05fe980..26fcb81 100644 --- a/src/components/common/MarkdownViewer/index.js +++ b/src/components/common/MarkdownViewer/index.js @@ -3,9 +3,14 @@ import { DefaultRenderer } from 'steem-content-renderer' import markdownLinkExtractor from 'markdown-link-extractor' import textParser from 'npm-text-parser' import classNames from 'classnames' -import { UrlVideoEmbed, TweetSkeleton } from 'components' +import { + UrlWithImageAndVideoEmbed, + TweetSkeleton, +} from 'components' import { createUseStyles } from 'react-jss' import { TwitterTweetEmbed } from 'react-twitter-embed' +import { parseUrls, generateUniqueId } from 'services/helper' +import { FacebookEmbed, TikTokEmbed } from "react-social-media-embed" const renderer = new DefaultRenderer({ baseUrl: "https://blog.d.buzz/", @@ -121,51 +126,27 @@ const useStyles = createUseStyles(theme => ({ const prepareTwitterEmbeds = (content) => { let body = content - const mainTwitterRegex = /(?:https?:\/\/(?:(?:twitter\.com\/(.*?)\/status\/(.*))))/i - const htmlReplacement = /]*?>]*?>(.*?)<\/p>.*?mdash; (.*)(.*?)<\/a><\/blockquote>/i - const links = textParser.getUrls(content) - const matchData = content.match(htmlReplacement) - if (matchData) { - const id = matchData[5] - let title = body - title = title.replace(htmlReplacement, '') - body = body.replace(body, `~~~~~~.^.~~~:twitter:${id}:~~~~~~.^.~~~`) - body = `${title} ${body}` - } else { - links.forEach((link) => { - try { - link = link.replace(/&/g, '&') - let match = '' - let id = '' - - if (link.match(mainTwitterRegex)) { - match = link.match(mainTwitterRegex) - id = match[2] - if (link.match(/(?:https?:\/\/(?:(?:twitter\.com\/(.*?)\/status\/(.*)?=(.*))))/i)) { - match = link.match(/(?:https?:\/\/(?:(?:twitter\.com\/(.*?)\/status\/(.*)?=(.*))))/i) - id = match[2] - id = id.slice(0, -2) - } - body = body.replace(link, `~~~~~~.^.~~~:twitter:${id}:~~~~~~.^.~~~`) - } - - if (match) { - const id = match[2] - body = body.replace(link, `~~~~~~.^.~~~:twitter:${id}:~~~~~~.^.~~~`) - } - } catch (e) { } - }) - } + links.forEach((link) => { + try { + // Use a regular expression to extract the numeric identifier + const match = link.match(/\/status\/(\d+)/) + console.log('prepareTwitterEmbeds', match) + if (match) { + const id = match[1] + body = body.replace(link, `~~~~~~.^.~~~:twitter:${id}:~~~~~~.^.~~~`) + } + } catch (e) { } + }) return body } const prepareVimmEmbeds = (content) => { - const vimmRegex = /(?:https?:\/\/(?:(?:www\.vimm\.tv\/(.*?))))/i - const vimmRegexEmbed = /(?:https?:\/\/(?:(?:www\.vimm\.tv\/(.*?)\/embed)))/i + const vimmRegex = /https?:\/\/www\.vimm\.tv\/(.*?)/i + const vimmRegexEmbed = /https?:\/\/www\.vimm\.tv\/(.*?)\/embed/i let body = content const links = textParser.getUrls(content) @@ -195,32 +176,42 @@ const prepareVimmEmbeds = (content) => { } const prepareThreeSpeakEmbeds = (content) => { - let body = content + try { + const link = (/\[!\[.*]\(.*\)]\(.*\)/).exec(content) + + // check if there is hyperlink with embedded image + if (link) { + const linkRegex = /\[!\[(.*?)]\((.*?)\)]\((.*?)\)/ + const bodyMatch = content.match(linkRegex) + const [wholeLink, , , videoLink] = bodyMatch + const platformMatch = videoLink.match(/(?:https?:\/\/(?:3speak\.online|3speak\.co|3speak\.tv)\/watch\?v=(.*))?/i) + + if (platformMatch) { + console.log('platformMatch', platformMatch) + const id = platformMatch[1] + return content.replace(wholeLink, `~~~~~~.^.~~~:threespeak:${id}:~~~~~~.^.~~~`) + } + } else { // this should filter all the hyperlink and normal link + const plainTextRegex = /https?:\/\/(?:3speak\.online|3speak\.co|3speak\.tv)\/watch\?v=([^\s()]+)/i + const plainTextMatch = content.match(plainTextRegex) - const links = markdownLinkExtractor(content) + if (plainTextMatch[0] === plainTextMatch.input) { + console.log('plainTextMatches', plainTextMatch) - links.forEach((link) => { - try { - link = link.replace(/&/g, '&') - let match = '' - if (link.includes('3speak.online/watch?v')) { - match = link.match(/(?:https?:\/\/(?:(?:3speak\.online\/watch\?v=(.*))))?/i) - } else if (link.includes('3speak.co/watch?v')) { - match = link.match(/(?:https?:\/\/(?:(?:3speak\.co\/watch\?v=(.*))))?/i) + if (plainTextMatch) { + const id = plainTextMatch[1] + return content.replace(plainTextRegex, `~~~~~~.^.~~~:threespeak:${id}:~~~~~~.^.~~~`) + } } + } + } catch (error) {} - if (match) { - const id = match[1] - body = body.replace(link, `~~~~~~.^.~~~:threespeak:${id}:~~~~~~.^.~~~`) - } - } catch (error) { } - }) - return body + return content } const prepareRumbleEmbed = (content) => { - const rumbleRegex = /(?:https?:\/\/(?:(?:rumble\.com\/(.*?))))/i - const rumbleRegexEmbed = /(?:https?:\/\/(?:(?:rumble\.com\/embed\/(.*?))))/i + const rumbleRegex = /https?:\/\/rumble\.com\/(.*?)/i + const rumbleRegexEmbed = /https?:\/\/rumble\.com\/embed\/(.*?)/i let body = content const links = textParser.getUrls(content) @@ -251,6 +242,7 @@ const prepareRumbleEmbed = (content) => { } } catch (error) { } }) + return body } @@ -328,50 +320,281 @@ const prepareBitchuteEmbeds = (content) => { return body } +const prepareBannedEmbeds = (content) => { + const bannedRegex = /https?:\/\/banned\.video\/watch\?id=(.*)/i + + let body = content + + const links = parseUrls(content) + + links.forEach((link) => { + try { + link = link.replace(/&/g, '&') + let match = '' + let id = '' + + if (link.match(bannedRegex)) { + const data = link.split('?id=') + match = link.match(bannedRegex) + if (data[1]) { + id = data[1] + } + } + + if (match) { + body = body.replace(link, `~~~~~~.^.~~~:banned:${id}:~~~~~~.^.~~~`) + } + } catch (error) { } + }) + + return body +} + +const prepareDollarVigilanteEmbeds = (content) => { + const dollarVigilanteRegex = /https?:\/\/(www\.)?vigilante\.tv\/w\/(.*)/i + + let body = content + + const links = parseUrls(content) + links.forEach((link) => { + try { + link = link.replace(/&/g, '&') + let match = '' + let id = '' + + if (link.match(dollarVigilanteRegex)) { + const data = link.split('/') + match = link.match(dollarVigilanteRegex) + if (data[4]) { + id = data[4] + } + } + + if (match) { + body = body.replace(link, `~~~~~~.^.~~~:dollarvigilante:${id}:~~~~~~.^.~~~`) + } + } catch (error) { } + }) + + return body +} + +const prepareSoundCloudEmbeds = (content) => { + const soundcloudRegex = /^https?:\/\/(soundcloud\.com|snd\.sc)\/(.*)$/ + let body = content + + const links = parseUrls(content) + + links.forEach((link) => { + link = link.replace(/&/g, '&') + let match = '' + let id = '' + + try { + if (link.match(soundcloudRegex)) { + const data = link.split('/') + match = link.match(soundcloudRegex) + id = `${data[3]}/${data[4]}` + } + + if (!id) { + id = '' + } + + if (match) { + body = body.replace(link, `~~~~~~.^.~~~:soundcloud:${id}:~~~~~~.^.~~~`) + } + } catch (error) { } + }) + + return body +} + +const prepareFacebookEmbeds = (content) => { + let body = content + + const links = parseUrls(content) + + links.forEach((link) => { + try { + body = body.replace(link, `~~~~~~.^.~~~:facebook:${link}:~~~~~~.^.~~~`) + } catch (error) { } + }) + + return body +} + +const prepareTiktokEmbeds = (content) => { + let body = content + const links = parseUrls(content) + + links.forEach((link) => { + body = body.replace(link, `~~~~~~.^.~~~:tiktok:${link}:~~~~~~.^.~~~`) + }) + + return body +} + +const prepareOdyseeEmbeds = (content) => { + const odyseeRegex = /^https:\/\/odysee\.com\/@([^/]+)\/([^:]+:\w+)/ + let body = content + + const links = parseUrls(content) + + links.forEach((link) => { + try { + const match = link.match(odyseeRegex) + + if (match) { + const id = `@${match[1]}/${match[2]}` + const modifiedString = id.replace(/:/g, "=====") + body = body.replace(link, `~~~~~~.^.~~~:odysee:${modifiedString}~~~~~~.^.~~~`) + } + } catch (error) { } + }) + + return body +} + +const prepareDTubeEmbeds = (content) => { + const dtubeEmbedRegex = /^(https?:\/\/)?(?:www\.)?(emb\.)?d\.tube\/v\/.*\/[a-zA-Z0-9-]+/gi + const dtubeVideoRegex = /^(https?:\/\/)?(?:www\.)?(d\.tube)\/#!\/v\/.*\/[a-zA-Z0-9-]+/gi + let body = content + + const links = parseUrls(content) + + links.forEach((link) => { + link = link.replace(/&/g, '&') + const matchEmbed = link.match(dtubeEmbedRegex) + const matchVideo = link.match(dtubeVideoRegex) + + if (matchEmbed) { + const data = link.split('/') + const id = link.includes('http') ? `${data[4]}/${data[5]}` : `${data[2]}/${data[3]}` + body = body.replace(link, `~~~~~~.^.~~~:dtube:${id}:~~~~~~.^.~~~`) + + } else if (matchVideo) { + const data = link.split('/') + const id = link.includes('http') ? `${data[5]}/${data[6]}` : `${data[3]}/${data[4]}` + body = body.replace(link, `~~~~~~.^.~~~:dtube:${id}:~~~~~~.^.~~~`) + } + }) + + return body +} + +const prepareAppleEmbeds = (content) => { + const appleRegex = /https?:\/\/music\.apple\.com\/(.*?)/i + const appleRegexEmbed = /https?:\/\/embed\.music\.apple\.com\/(.*?)/i + let body = content + + const links = parseUrls(content) + + links.forEach((link) => { + link = link.replace(/&/g, '&') + + const match = link.match(appleRegex) || link.match(appleRegexEmbed) + + if (match) { + const data = link.split('/') + const id = `${data[4]}/${data[5]}/${data[6]}` + body = body.replace(link, `~~~~~~.^.~~~:apple:${id}:~~~~~~.^.~~~`) + } + }) + + return body +} + +const prepareDBuzzVideos = (content) => { + const oldDbuzzVideos = /https:\/\/ipfs\.io\/ipfs\/(.*\?dbuzz_video)/i + const dbuzzVideos = /https:\/\/ipfs\.io\/ipfs\/.*\?dbuzz_video=https:\/\/ipfs\.io\/ipfs\/([a-zA-Z0-9]+)/i + let body = content + + const links = parseUrls(content) + + links.forEach((link) => { + link = link.replace(/&/g, '&') + + let match + + if (link.match(oldDbuzzVideos) && link.match(dbuzzVideos)) { + match = link.match(dbuzzVideos)[1] + } else if (link.match(oldDbuzzVideos) && !link.match(dbuzzVideos)) { + match = link.match(oldDbuzzVideos)[1].replace('?dbuzz_video', '') + } + + if (match) { + const id = match + body = body.replace(link, `~~~~~~.^.~~~:dbuzz-video:${id}:~~~~~~.^.~~~`) + } + }) + + return body +} + const render = (content, markdownClass, assetClass, scrollIndex, recomputeRowIndex) => { + const splitContent = content.split(':') + const embedTypes = [ + ':threespeak:', + ':vimm:', + ':rumble:', + ':lbry:', + ':bitchute:', + ':banned:', + ':dollarvigilante:', + ':soundcloud:', + // ':facebook:', + // ':tiktok:', + // :twitter:, + ':odysee:', + ':dtube:', + ':apple:', + ':dbuzz-video:', + ] if (content.includes(':twitter:')) { - const splitTwitter = content.split(':') try { - return recomputeRowIndex(scrollIndex)} placeholder={} /> - } catch (e) { console.log(e) } - } else if (content.includes(':threespeak:')) { - const splitThreeSpeak = content.split(':') - const url = `https://3speak.co/embed?v=${splitThreeSpeak[2]}` - return - } else if (content.includes(':vimm:')) { - const splitVimm = content.split(':') - const url = `https://www.vimm.tv/${splitVimm[2]}/embed?autoplay=0` - return - } else if (content.includes(':rumble:')) { - const splitRumble = content.split(':') - if (splitRumble[2]) { - const url = `https://rumble.com/embed/${splitRumble[2]}` - return + return ( + recomputeRowIndex(scrollIndex)} + placeholder={} + /> + ) + } catch (e) { + console.log(e) } - } else if (content.includes(':lbry:')) { - const splitLbry = content.split(':') - const url = `https://lbry.tv/$/embed/${splitLbry[2]}` - return - } else if (content.includes(':bitchute:')) { - const splitBitchute = content.split(':') - const url = `https://www.bitchute.com/embed/${splitBitchute[2]}` - return } else if (content.includes(':facebook:')) { - const splitFacebook = content.split(':') - const url = splitFacebook[4] ? `https:${splitFacebook[3]}` : `https://www.facebook.com/plugins/video.php?href=https%3A%2F%2Fwww.facebook.com%2F${splitFacebook[2]}%2Fvideos%2F${splitFacebook[3]}&width=500&show_text=false&height=300` - return + return + } else if (content.includes(':tiktok:')) { + return + } else if (embedTypes.some(type => content.includes(type))) { + const embed = { + app: splitContent[1], + id: splitContent[2], + domain: '', + } + return } else { // render normally - return
+ return ( +
+ ) } - } + const MarkdownViewer = React.memo((props) => { const classes = useStyles() const { @@ -379,28 +602,7 @@ const MarkdownViewer = React.memo((props) => { scrollIndex = -1, recomputeRowIndex = () => { }, } = props - let { content = '' } = props - const links = textParser.getUrls(content) - - links.forEach((link) => { - try { - link = link.replace(/&/g, '&') - - if (link.includes('twitter.com')) { - content = prepareTwitterEmbeds(content) - } else if (link.includes('3speak.co') || link.includes('3speak.online')) { - content = prepareThreeSpeakEmbeds(content) - } else if (link.includes('www.vimm.tv')) { - content = prepareVimmEmbeds(content) - } else if (link.includes('rumble.com')) { - content = prepareRumbleEmbed(content) - } else if (link.includes('lbry.tv') || link.includes('open.lbry.com')) { - content = prepareLbryEmbeds(content) - } else if (link.includes('www.bitchute.com')) { - content = prepareBitchuteEmbeds(content) - } - } catch (error) { } - }) + const { content = '' } = props let assetClass = classes.minified @@ -408,9 +610,54 @@ const MarkdownViewer = React.memo((props) => { assetClass = classes.full } + let splitContent = content.split(`\n`) + + splitContent = splitContent.map((item, index) => { + if (item.includes('twitter.com') || item.includes('x.com')) { + item = prepareTwitterEmbeds(item) + } else if (item.includes('3speak.co') || item.includes('3speak.online') || item.includes('3speak.tv')) { + item = prepareThreeSpeakEmbeds(item) + // } else if (item.includes('vimm.tv') || item.includes('Vimm.tv')) { + // item = prepareVimmEmbeds(item) + } else if (item.includes('rumble.com')) { + item = prepareRumbleEmbed(item) + // } else if (item.includes('lbry.tv') || item.includes('open.lbry.com')) { + // item = prepareLbryEmbeds(item) + } else if (item.includes('bitchute.com')) { + item = prepareBitchuteEmbeds(item) + } else if (item.includes('banned.video')) { + item = prepareBannedEmbeds(item) + } else if (item.includes('vigilante.tv')) { + item = prepareDollarVigilanteEmbeds(item) + } else if (item.includes('soundcloud.com')) { + item = prepareSoundCloudEmbeds(item) + } else if (item.includes('facebook.com') || item.includes('fb.watch')) { + item = prepareFacebookEmbeds(item) + } else if (item.includes('tiktok.com')) { + item = prepareTiktokEmbeds(item) + } else if (item.includes('odysee.com') || item.includes('lbry.tv') || item.includes('open.lbry.com')) { + item = prepareOdyseeEmbeds(item) + } else if (item.includes('music.apple.com')) { + item = prepareAppleEmbeds(item) + } else if (item.includes('d.tube')) { + item = prepareDTubeEmbeds(item) + } else if (item.includes('dbuzz_video')) { + item = prepareDBuzzVideos(item) + // } else if (hiveTubePattern.test(link)) { + // item = prepareHiveTubeVideoEmbeds(item) + // } else if (buzzImagesPattern.test(link)) { + // item = prepareBuzzImages(item) + } + + return item + }) + + const combinedString = splitContent.join('\n') - let splitContent = content.split(`~~~~~~.^.~~~`) + console.log('splitContent', splitContent) + console.log('combinedString', combinedString) + splitContent = combinedString.split(`~~~~~~.^.~~~`) splitContent = splitContent.filter((item) => item !== '') return ( diff --git a/src/components/common/UrlWithImageAndVideoEmbed/index.js b/src/components/common/UrlWithImageAndVideoEmbed/index.js new file mode 100644 index 0000000..c89bb1b --- /dev/null +++ b/src/components/common/UrlWithImageAndVideoEmbed/index.js @@ -0,0 +1,94 @@ +import React from 'react' +import { createUseStyles } from 'react-jss' + +const useStyles = createUseStyles({ + videoWrapper: { + marginTop: 26, + position: 'relative', + paddingBottom: '56.25%', + height: 0, + '& iframe': { + animation: 'skeleton-loading 1s linear infinite alternate', + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%', + }, + }, +}) + +const FACEBOOK_APP_ID = 236880454857514 + +const UrlWithImageAndVideoEmbed = (props) => { + const classes = useStyles() + const { embed } = props + const { app, id, domain } = embed || { app: '', id: '', domain: '' } + + console.log('UrlWithImageAndVideoEmbed', props) + + const getEmbedUrl = () => { + if(embed) { + switch (app) { + case 'youtube': + return `https://www.youtube.com/embed/${id}` + case 'vimm': + return `https://www.vimm.tv/${id}/embed?autoplay=0` + case 'threespeak': + return `//3speak.tv/embed?v=${id}` + case 'rumble': + return `https://rumble.com/embed/${id}` + case 'lbry': + return `https://lbry.tv/$/embed/${id}` + case 'bitchute': + return `https://www.bitchute.com/embed/${id}` + case 'banned': + return `https://api.banned.video/embed/${id}` + case 'dollarvigilante': + return `https://vigilante.tv/videos/embed/${id}` + case 'dapplr': + return `https://cdn.dapplr.in/file/dapplr-videos/${id}` + case 'freeworldnews': + return `https://api.banned.video/embed/${id}` + case 'dbuzz-video': + return `https://ipfs.io/ipfs/${id}` + case 'hive-tube-embed': + return `https://${domain}/videos/embed/${id}` + case 'facebook': + return `https://www.facebook.com/plugins/video.php?href=https%3A%2F%2Fwww.facebook.com%2Ffacebook%2Fvideos%2F${id}%2F&width=500&show_text=false&appId=${FACEBOOK_APP_ID}&height=360` + case 'tiktok': + return `https://www.tiktok.com/embed/v2/${id}?lang=en-US` + case 'odysee': + return `https://odysee.com/$/embed/${id.replace(/=====/g, ":")}` + case 'apple': + return `https://embed.music.apple.com/gb/${id}` + case 'dtube': + return `https://emb.d.tube/#!/${id}` + default: + return null + } + } + } + + return ( + + +
+ +
+
+
+ ) +} + +export default UrlWithImageAndVideoEmbed diff --git a/src/services/helper.js b/src/services/helper.js index f936205..268ee2a 100644 --- a/src/services/helper.js +++ b/src/services/helper.js @@ -1,10 +1,10 @@ -import { useState, useEffect } from 'react' +import {useEffect, useState} from 'react' import uuid from 'uuid-random' -import { encrypt, decrypt } from 'caesar-shift' -import CryptoJS from 'crypto-js' +import {decrypt, encrypt} from 'caesar-shift' +import CryptoJS from 'crypto-js' import sha256 from 'crypto-js/sha256' -import { Remarkable } from 'remarkable' -import { DefaultRenderer } from 'steem-content-renderer' +import {Remarkable} from 'remarkable' +import {DefaultRenderer} from 'steem-content-renderer' import markdownLinkExtractor from 'markdown-link-extractor' import diff_match_patch from 'diff-match-patch' import sanitize from 'sanitize-html' @@ -17,7 +17,7 @@ export const getUrls = (text) => { } export const calculateOverhead = (content) => { let urls = getUrls(content) || [] - + const markdown = content?.match(/#+\s|[*]|\s+ +\s|\s+$/gm) || [] let overhead = 0 @@ -30,11 +30,11 @@ export const calculateOverhead = (content) => { overhead += item.length }) } - + if((urls.length) > 3) { urls = urls.slice(0, 2) } - + if(urls && urls.length <= 3){ urls.forEach((item) => { // overheadItems.push(item) @@ -176,7 +176,7 @@ export const extractVideoLinks = (links) => { if (tempLink.includes('&')) { splitLink[1] = (tempLink.split('&'))[0] } - + videoLinks.push({ link, type: 'youtube', id: splitLink[1] }) } } else if (link.includes('3speak.online')) { @@ -193,18 +193,18 @@ export const extractImageLinks = (links) => { const imageLinks = [] links.forEach((link) => { - if ((link.includes('.jpg') + if ((link.includes('.jpg') || link.includes('.png') || link.includes('.JPEG') - || link.includes('youtu.be') - || link.includes('youtube')) + || link.includes('youtu.be') + || link.includes('youtube')) && !link.includes('img.3speakcontent.online')) { if (link.includes('youtube')) { const splitLink = link.includes('youtu.be') ? link.split('be/') : link.split('v=') link = `https://img.youtube.com/vi/${splitLink[1]}/hqdefault.jpg` - } - + } + imageLinks.push(link) } }) @@ -219,7 +219,7 @@ const prepareImages = (content) => { // remove 3speak thumbnails if((item.includes('.png') && item.includes('img.3speakcontent.online')) && !item.includes('https://images.hive.blog')) { splitContent[index] = '' - } + } }) return splitContent.join(' ') } @@ -244,7 +244,7 @@ const prepareEmbeds = (content) => { idToFormat = idToFormat.replace(/\)/g, '') idToFormat = idToFormat.replace('[Watch on', '') idToFormat = idToFormat.trim('') - + const videoLink = `https://3speak.online/embed?v=${idToFormat}` if(!visited.includes(videoLink)) { @@ -287,7 +287,7 @@ const render = (content) => { height='400' width='100%' loading='lazy' - >` + >` } else { contentBody = renderer.render(item) } @@ -581,6 +581,12 @@ export const truncateString = (str, num) => { } } +export const generateUniqueId = () => { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { + const r = (Math.random() * 16) | 0 + return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16) + }) +} export const proxyImage = (url) => { // const enabled = true @@ -622,4 +628,4 @@ export const getTheme =() => { } return mode -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index a63ac1b..c2233a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2691,6 +2691,11 @@ dependencies: "@types/yargs-parser" "*" +"@types/youtube-player@^5.5.5": + version "5.5.11" + resolved "https://registry.yarnpkg.com/@types/youtube-player/-/youtube-player-5.5.11.tgz#cc297e27151db946596d92fb7cfb837627e83be0" + integrity sha512-pM41CDBqJqBmTeJWnF7NOGz82IQoYOhqzMYXv5vKCXBqGiYSLldxMtpCk6KAEtADTy49S45AriYaCaZyeUX38Q== + "@typescript-eslint/eslint-plugin@^2.10.0": version "2.34.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9" @@ -3862,6 +3867,13 @@ braces@~3.0.2: dependencies: fill-range "^7.0.1" +bricks.js@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/bricks.js/-/bricks.js-1.8.0.tgz#8fdeb3c0226af251f4d5727a7df7f9ac0092b4b2" + integrity sha512-XJsIGxoixpMDo/KoLXR+uQizFVGWNAQy1lLoIwXKxm6/Zpd9QQLSUd0otybbK7wjqX23ZvCXFxnIw+uCXJHo0A== + dependencies: + knot.js "^1.1.5" + brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -4393,6 +4405,11 @@ classnames@^2.2.1, classnames@^2.2.6, classnames@^2.3.1, classnames@~2.3.1: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== +classnames@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== + clean-css@^4.2.3: version "4.2.4" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.4.tgz#733bf46eba4e607c6891ea57c24a989356831178" @@ -5234,7 +5251,7 @@ data-urls@^1.0.0, data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -5745,6 +5762,14 @@ elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.3, elliptic@^6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" +emoji-mart@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/emoji-mart/-/emoji-mart-3.0.1.tgz#9ce86706e02aea0506345f98464814a662ca54c6" + integrity sha512-sxpmMKxqLvcscu6mFn9ITHeZNkGzIvD0BSNFE/LJESPbCA8s1jM6bCDPjWbV31xHq7JXaxgpHxLB54RCbBZSlg== + dependencies: + "@babel/runtime" "^7.0.0" + prop-types "^15.6.0" + emoji-regex@^7.0.1, emoji-regex@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -6517,7 +6542,7 @@ fancy-log@^1.3.2: parse-node-version "^1.0.0" time-stamp "^1.0.0" -fast-deep-equal@^3.1.1: +fast-deep-equal@3.1.3, fast-deep-equal@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== @@ -9293,6 +9318,11 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +knot.js@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/knot.js/-/knot.js-1.1.5.tgz#28e72522f703f50fe98812fde224dd72728fef5d" + integrity sha512-ptGtvTrgLNtQj9ilUR+tSyHWTCPp2xu/EHkeo3OvpczzNqBSwjQKz8G7vUhzlRbasXVULBWSejsj6QRQb1pakw== + last-call-webpack-plugin@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" @@ -9415,6 +9445,11 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" +load-script@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/load-script/-/load-script-1.0.0.tgz#0491939e0bee5643ee494a7e3da3d2bac70c6ca4" + integrity sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA== + loader-fs-cache@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz#f08657646d607078be2f0a032f8bd69dd6f277d9" @@ -11759,7 +11794,7 @@ prop-types-extra@^1.1.0: react-is "^16.3.2" warning "^4.0.0" -prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@15.8.1, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -12097,6 +12132,14 @@ react-fastclick@^3.0.2: resolved "https://registry.yarnpkg.com/react-fastclick/-/react-fastclick-3.0.2.tgz#2994c60088cda90b0b2cbfac4b6e7c6bc73d6a3a" integrity sha512-ia0v5WamwSHmGsWaeKVvR79ubjpa5gIxm+ZFqzSbKrZrUfF4t3PF1+cvQzfbSe51muO7VwUHLBW4uu+oGIwEow== +react-giphy-searchbox@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/react-giphy-searchbox/-/react-giphy-searchbox-1.5.4.tgz#49c6f98bf1afefbbd3a9ab3c5f79709cb32f399b" + integrity sha512-5SCiT3Y/0aeJcFfd3yXwJ1LShmDTTSL/aKJUXu9t0eBvwUU5DSev/JvMx3ijedsWpHuMtkwHLy5jV3pBDdzPQw== + dependencies: + bricks.js "^1.8.0" + react-infinite-scroller "^1.2.4" + react-helmet@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726" @@ -12107,6 +12150,11 @@ react-helmet@^6.1.0: react-fast-compare "^3.1.1" react-side-effect "^2.1.0" +react-html-props@^2.0.3: + version "2.0.9" + resolved "https://registry.yarnpkg.com/react-html-props/-/react-html-props-2.0.9.tgz#0070476137ea0d6141e094b0d32521c173ed2c47" + integrity sha512-Q9wIP8hs4HFUb3CDh5tF1nKgZ4S9odU07tR/lZ+/9ePv+psxRy+mUn7ujjrCGwtrLA52AI41fXWr425yK1iyTA== + react-icons@^4.2.0: version "4.6.0" resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.6.0.tgz#f83eda179af5d02c047449a20b702c858653d397" @@ -12119,6 +12167,13 @@ react-infinite-scroll-component@^6.0.0: dependencies: throttle-debounce "^2.1.0" +react-infinite-scroller@^1.2.4: + version "1.2.6" + resolved "https://registry.yarnpkg.com/react-infinite-scroller/-/react-infinite-scroller-1.2.6.tgz#8b80233226dc753a597a0eb52621247f49b15f18" + integrity sha512-mGdMyOD00YArJ1S1F3TVU9y4fGSfVVl6p5gh/Vt4u99CJOptfVu/q5V/Wlle72TMgYlBwIhbxK5wF0C/R33PXQ== + dependencies: + prop-types "^15.5.8" + react-is@^16.12.0, react-is@^16.13.1, react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.4, react-is@^16.8.6: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -12318,6 +12373,18 @@ react-side-effect@^2.1.0: resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.2.tgz#dc6345b9e8f9906dc2eeb68700b615e0b4fe752a" integrity sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw== +react-social-media-embed@^2.5.9: + version "2.5.9" + resolved "https://registry.yarnpkg.com/react-social-media-embed/-/react-social-media-embed-2.5.9.tgz#f56ecb6bc27db68430f4ab8ace8426a6317c8f0f" + integrity sha512-fbUeEqlTqst0z7DUDvZ5CkQTQ6jXsoP6w144Qh559OryL/DlusXNtIPU3iQPmS37zHthv/RVo1YKp/dislNklw== + dependencies: + "@types/youtube-player" "^5.5.5" + classnames "^2.5.1" + react-html-props "^2.0.3" + react-sub-unsub "^2.2.1" + react-twitter-embed "^4.0.4" + react-youtube "^10.1.0" + react-sticky@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/react-sticky/-/react-sticky-6.0.3.tgz#7a18b643e1863da113d7f7036118d2a75d9ecde4" @@ -12326,6 +12393,11 @@ react-sticky@^6.0.3: prop-types "^15.5.8" raf "^3.3.0" +react-sub-unsub@^2.2.1: + version "2.2.7" + resolved "https://registry.yarnpkg.com/react-sub-unsub/-/react-sub-unsub-2.2.7.tgz#d755ea40ab61ff64bc8c73a9013efa910472629d" + integrity sha512-b2o0mIW8G4Yb3aaKxFB9iiCCHxCDGmogy+493oQpEJHjBy/hl6uf+6RhAinqKWRwi1fvO6mGIMVGsf2XYLL38g== + react-tag-input@^6.2.1: version "6.8.1" resolved "https://registry.yarnpkg.com/react-tag-input/-/react-tag-input-6.8.1.tgz#bbf6e4e0765c0565470cc48a44dc4757c75784b9" @@ -12374,6 +12446,13 @@ react-twitter-embed@^3.0.3: react-proptype-conditional-require "^1.0.4" scriptjs "^2.5.9" +react-twitter-embed@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/react-twitter-embed/-/react-twitter-embed-4.0.4.tgz#4a6b8354acc266876ff1110b9f648518ea20db6d" + integrity sha512-2JIL7qF+U62zRzpsh6SZDXNI3hRNVYf5vOZ1WRcMvwKouw+xC00PuFaD0aEp2wlyGaZ+f4x2VvX+uDadFQ3HVA== + dependencies: + scriptjs "^2.5.9" + react-virtualized@^9.18.5: version "9.22.3" resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.22.3.tgz#f430f16beb0a42db420dbd4d340403c0de334421" @@ -12386,6 +12465,15 @@ react-virtualized@^9.18.5: prop-types "^15.7.2" react-lifecycles-compat "^3.0.4" +react-youtube@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/react-youtube/-/react-youtube-10.1.0.tgz#7e5670c764f12eb408166e8eb438d788dc64e8b5" + integrity sha512-ZfGtcVpk0SSZtWCSTYOQKhfx5/1cfyEW1JN/mugGNfAxT3rmVJeMbGpA9+e78yG21ls5nc/5uZJETE3cm3knBg== + dependencies: + fast-deep-equal "3.1.3" + prop-types "15.8.1" + youtube-player "5.5.2" + react@^16.13.1, react@^16.8.6: version "16.14.0" resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" @@ -13362,6 +13450,11 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" +sister@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/sister/-/sister-3.0.2.tgz#bb3e39f07b1f75bbe1945f29a27ff1e5a2f26be4" + integrity sha512-p19rtTs+NksBRKW9qn0UhZ8/TUI9BPw9lmtHny+Y3TinWlOa9jWh9xB0AtPSdmOy49NJJJSSe0Ey4C7h0TrcYA== + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -15763,3 +15856,12 @@ yargs@^7.1.0: which-module "^1.0.0" y18n "^3.2.1" yargs-parser "^5.0.1" + +youtube-player@5.5.2: + version "5.5.2" + resolved "https://registry.yarnpkg.com/youtube-player/-/youtube-player-5.5.2.tgz#052b86b1eabe21ff331095ffffeae285fa7f7cb5" + integrity sha512-ZGtsemSpXnDky2AUYWgxjaopgB+shFHgXVpiJFeNB5nWEugpW1KWYDaHKuLqh2b67r24GtP6HoSW5swvf0fFIQ== + dependencies: + debug "^2.6.6" + load-script "^1.0.0" + sister "^3.0.0"