serpbear/pages/api/domains.ts
towfiqi b2e97b2ebe feat: Adds the Ability to set Search Console Property type via Domain Settings.
- Previously only domain properties worked with SerpBear. This feature adds the ability to add URL properties as well.
- Adds a new field "search_console" in Domain Table.
- Adds a new Search Console option in Domain Settings Modal UI.
- When the  new "This is a URL Property" option is enabled, the exact Property URL should be provided.

closes #50
2024-02-06 23:42:28 +06:00

125 lines
4.7 KiB
TypeScript

import type { NextApiRequest, NextApiResponse } from 'next';
import db from '../../database/database';
import Domain from '../../database/models/domain';
import Keyword from '../../database/models/keyword';
import getdomainStats from '../../utils/domains';
import verifyUser from '../../utils/verifyUser';
import { removeLocalSCData } from '../../utils/searchConsole';
type DomainsGetRes = {
domains: DomainType[]
error?: string|null,
}
type DomainsAddResponse = {
domains: DomainType[]|null,
error?: string|null,
}
type DomainsDeleteRes = {
domainRemoved: number,
keywordsRemoved: number,
SCDataRemoved: boolean,
error?: string|null,
}
type DomainsUpdateRes = {
domain: Domain|null,
error?: string|null,
}
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
await db.sync();
const authorized = verifyUser(req, res);
if (authorized !== 'authorized') {
return res.status(401).json({ error: authorized });
}
if (req.method === 'GET') {
return getDomains(req, res);
}
if (req.method === 'POST') {
return addDomain(req, res);
}
if (req.method === 'DELETE') {
return deleteDomain(req, res);
}
if (req.method === 'PUT') {
return updateDomain(req, res);
}
return res.status(502).json({ error: 'Unrecognized Route.' });
}
export const getDomains = async (req: NextApiRequest, res: NextApiResponse<DomainsGetRes>) => {
const withStats = !!req?.query?.withstats;
try {
const allDomains: Domain[] = await Domain.findAll();
const formattedDomains: DomainType[] = allDomains.map((el) => el.get({ plain: true }));
const theDomains: DomainType[] = withStats ? await getdomainStats(formattedDomains) : allDomains;
return res.status(200).json({ domains: theDomains });
} catch (error) {
return res.status(400).json({ domains: [], error: 'Error Getting Domains.' });
}
};
const addDomain = async (req: NextApiRequest, res: NextApiResponse<DomainsAddResponse>) => {
const { domains } = req.body;
if (domains && Array.isArray(domains) && domains.length > 0) {
const domainsToAdd: any = [];
domains.forEach((domain: string) => {
domainsToAdd.push({
domain: domain.trim(),
slug: domain.trim().replaceAll('-', '_').replaceAll('.', '-').replaceAll('/', '-'),
lastUpdated: new Date().toJSON(),
added: new Date().toJSON(),
});
});
try {
const newDomains:Domain[] = await Domain.bulkCreate(domainsToAdd);
const formattedDomains = newDomains.map((el) => el.get({ plain: true }));
return res.status(201).json({ domains: formattedDomains });
} catch (error) {
console.log('[ERROR] Adding New Domain ', error);
return res.status(400).json({ domains: [], error: 'Error Adding Domain.' });
}
} else {
return res.status(400).json({ domains: [], error: 'Necessary data missing.' });
}
};
export const deleteDomain = async (req: NextApiRequest, res: NextApiResponse<DomainsDeleteRes>) => {
if (!req.query.domain && typeof req.query.domain !== 'string') {
return res.status(400).json({ domainRemoved: 0, keywordsRemoved: 0, SCDataRemoved: false, error: 'Domain is Required!' });
}
try {
const { domain } = req.query || {};
const removedDomCount: number = await Domain.destroy({ where: { domain } });
const removedKeywordCount: number = await Keyword.destroy({ where: { domain } });
const SCDataRemoved = await removeLocalSCData(domain as string);
return res.status(200).json({ domainRemoved: removedDomCount, keywordsRemoved: removedKeywordCount, SCDataRemoved });
} catch (error) {
console.log('[ERROR] Deleting Domain: ', req.query.domain, error);
return res.status(400).json({ domainRemoved: 0, keywordsRemoved: 0, SCDataRemoved: false, error: 'Error Deleting Domain' });
}
};
export const updateDomain = async (req: NextApiRequest, res: NextApiResponse<DomainsUpdateRes>) => {
if (!req.query.domain) {
return res.status(400).json({ domain: null, error: 'Domain is Required!' });
}
const { domain } = req.query || {};
const { notification_interval, notification_emails, search_console } = req.body as DomainSettings;
try {
const domainToUpdate: Domain|null = await Domain.findOne({ where: { domain } });
if (domainToUpdate) {
domainToUpdate.set({ notification_interval, notification_emails, search_console: JSON.stringify(search_console) });
await domainToUpdate.save();
}
return res.status(200).json({ domain: domainToUpdate });
} catch (error) {
console.log('[ERROR] Updating Domain: ', req.query.domain, error);
return res.status(400).json({ domain: null, error: 'Error Updating Domain' });
}
};