diff --git a/components/domains/DomainItem.tsx b/components/domains/DomainItem.tsx index 83a47c7..f89d91f 100644 --- a/components/domains/DomainItem.tsx +++ b/components/domains/DomainItem.tsx @@ -11,9 +11,10 @@ type DomainItemProps = { selected: boolean, isConsoleIntegrated: boolean, thumb: string, + updateThumb: Function, } -const DomainItem = ({ domain, selected, isConsoleIntegrated = false, thumb }: DomainItemProps) => { +const DomainItem = ({ domain, selected, isConsoleIntegrated = false, thumb, updateThumb }: DomainItemProps) => { const { keywordsUpdated, slug, keywordCount = 0, avgPosition = 0, scVisits = 0, scImpressions = 0, scPosition = 0 } = domain; // const router = useRouter(); return ( @@ -21,8 +22,20 @@ const DomainItem = ({ domain, selected, isConsoleIntegrated = false, thumb }: Do
-
- {thumb && {domain.domain}} +
+ + {domain.domain}

{domain.domain}

diff --git a/pages/api/settings.ts b/pages/api/settings.ts index 90db4cc..9b5e5a6 100644 --- a/pages/api/settings.ts +++ b/pages/api/settings.ts @@ -55,6 +55,7 @@ const updateSettings = async (req: NextApiRequest, res: NextApiResponse => { + const screenshotAPIKey = process.env.SCREENSHOT_API || '69408-serpbear'; try { const settingsRaw = await readFile(`${process.cwd()}/data/settings.json`, { encoding: 'utf-8' }); const failedQueueRaw = await readFile(`${process.cwd()}/data/failed_queue.json`, { encoding: 'utf-8' }); @@ -73,6 +74,7 @@ export const getAppSettings = async () : Promise => { search_console_integrated: !!(process.env.SEARCH_CONSOLE_PRIVATE_KEY && process.env.SEARCH_CONSOLE_CLIENT_EMAIL), available_scapers: allScrapers.map((scraper) => ({ label: scraper.name, value: scraper.id })), failed_queue: failedQueue, + screenshot_key: screenshotAPIKey, }; } catch (error) { console.log('Error Decrypting Settings API Keys!'); @@ -81,7 +83,7 @@ export const getAppSettings = async () : Promise => { return decryptedSettings; } catch (error) { console.log('[ERROR] Getting App Settings. ', error); - const settings = { + const settings: SettingsType = { scraper_type: 'none', notification_interval: 'never', notification_email: '', @@ -91,6 +93,7 @@ export const getAppSettings = async () : Promise => { smtp_username: '', smtp_password: '', scrape_retry: false, + screenshot_key: screenshotAPIKey, }; const otherSettings = { available_scapers: allScrapers.map((scraper) => ({ label: scraper.name, value: scraper.id })), diff --git a/pages/domains/index.tsx b/pages/domains/index.tsx index f9e2b44..2d1e29c 100644 --- a/pages/domains/index.tsx +++ b/pages/domains/index.tsx @@ -3,11 +3,12 @@ import type { NextPage } from 'next'; import Head from 'next/head'; import { useRouter } from 'next/router'; import { CSSTransition } from 'react-transition-group'; +import toast, { Toaster } from 'react-hot-toast'; import TopBar from '../../components/common/TopBar'; import AddDomain from '../../components/domains/AddDomain'; import Settings from '../../components/settings/Settings'; import { useFetchSettings } from '../../services/settings'; -import { useFetchDomains } from '../../services/domains'; +import { fetchDomainScreenshot, useFetchDomains } from '../../services/domains'; import DomainItem from '../../components/domains/DomainItem'; import Icon from '../../components/common/Icon'; @@ -23,32 +24,17 @@ const SingleDomain: NextPage = () => { const { data: domainsData, isLoading } = useFetchDomains(router, true); useEffect(() => { - // console.log('Domains Data: ', domainsData); - if (domainsData?.domains && domainsData.domains.length > 0) { - const domainThumbsRaw = localStorage.getItem('domainThumbs'); - const domThumbs = domainThumbsRaw ? JSON.parse(domainThumbsRaw) : {}; + if (domainsData?.domains && domainsData.domains.length > 0 && appSettings?.settings?.screenshot_key) { domainsData.domains.forEach(async (domain:DomainType) => { if (domain.domain) { - if (!domThumbs[domain.domain]) { - const domainImageBlob = await fetch(`https://image.thum.io/get/auth/66909-serpbear/maxAge/96/width/200/https://${domain.domain}`).then((res) => res.blob()); - if (domainImageBlob) { - const reader = new FileReader(); - await new Promise((resolve, reject) => { - reader.onload = resolve; - reader.onerror = reject; - reader.readAsDataURL(domainImageBlob); - }); - const imageBase: string = reader.result && typeof reader.result === 'string' ? reader.result : ''; - localStorage.setItem('domainThumbs', JSON.stringify({ ...domThumbs, [domain.domain]: imageBase })); - setDomainThumbs((currentThumbs) => ({ ...currentThumbs, [domain.domain]: imageBase })); - } - } else { - setDomainThumbs((currentThumbs) => ({ ...currentThumbs, [domain.domain]: domThumbs[domain.domain] })); + const domainThumb = await fetchDomainScreenshot(domain.domain, appSettings.settings.screenshot_key); + if (domainThumb) { + setDomainThumbs((currentThumbs) => ({ ...currentThumbs, [domain.domain]: domainThumb })); } } }); } - }, [domainsData]); + }, [domainsData, appSettings]); useEffect(() => { // console.log('appSettings.settings: ', appSettings && appSettings.settings); @@ -57,6 +43,18 @@ const SingleDomain: NextPage = () => { } }, [appSettings]); + const manuallyUpdateThumb = async (domain: string) => { + if (domain && appSettings?.settings?.screenshot_key) { + const domainThumb = await fetchDomainScreenshot(domain, appSettings.settings.screenshot_key, true); + if (domainThumb) { + toast(`${domain} Screenshot Updated Successfully!`, { icon: '✔️' }); + setDomainThumbs((currentThumbs) => ({ ...currentThumbs, [domain]: domainThumb })); + } else { + toast(`Failed to Fetch ${domain} Screenshot!`, { icon: '⚠️' }); + } + } + }; + return (
{noScrapprtError && ( @@ -90,6 +88,7 @@ const SingleDomain: NextPage = () => { selected={false} isConsoleIntegrated={!!(appSettings && appSettings?.settings?.search_console_integrated) } thumb={domainThumbs[domain.domain]} + updateThumb={manuallyUpdateThumb} // isConsoleIntegrated={false} />; })} @@ -115,6 +114,7 @@ const SingleDomain: NextPage = () => { +
); }; diff --git a/services/domains.tsx b/services/domains.tsx index a722ee3..4e73a51 100644 --- a/services/domains.tsx +++ b/services/domains.tsx @@ -19,6 +19,36 @@ export async function fetchDomains(router: NextRouter, withStats:boolean) { return res.json(); } +export async function fetchDomainScreenshot(domain: string, screenshot_key:string, forceFetch = false): Promise { + const domainThumbsRaw = localStorage.getItem('domainThumbs'); + const domThumbs = domainThumbsRaw ? JSON.parse(domainThumbsRaw) : {}; + if (!domThumbs[domain] || forceFetch) { + try { + const screenshotURL = `https://image.thum.io/get/auth/${screenshot_key}/maxAge/96/width/200/https://${domain}`; + const domainImageRes = await fetch(screenshotURL); + const domainImageBlob = domainImageRes.status === 200 ? await domainImageRes.blob() : false; + if (domainImageBlob) { + const reader = new FileReader(); + await new Promise((resolve, reject) => { + reader.onload = resolve; + reader.onerror = reject; + reader.readAsDataURL(domainImageBlob); + }); + const imageBase: string = reader.result && typeof reader.result === 'string' ? reader.result : ''; + localStorage.setItem('domainThumbs', JSON.stringify({ ...domThumbs, [domain]: imageBase })); + return imageBase; + } + return false; + } catch (error) { + return false; + } + } else if (domThumbs[domain]) { + return domThumbs[domain]; + } + + return false; +} + export function useFetchDomains(router: NextRouter, withStats:boolean = false) { return useQuery('domains', () => fetchDomains(router, withStats)); } diff --git a/types.d.ts b/types.d.ts index 366c4f3..957c1d8 100644 --- a/types.d.ts +++ b/types.d.ts @@ -83,7 +83,8 @@ type SettingsType = { scrape_delay?: string, scrape_retry?: boolean, failed_queue?: string[] - version?: string + version?: string, + screenshot_key?: string, } type KeywordSCDataChild = {