feat(api): add issues and version endpoints
This commit is contained in:
parent
34df85f8b9
commit
deea21126b
@ -8,8 +8,11 @@ import v2ReportRoutes from 'routes/v2/report';
|
|||||||
import v3DataRoutes from 'routes/v3/data';
|
import v3DataRoutes from 'routes/v3/data';
|
||||||
import v3ReportRoutes from 'routes/v3/report';
|
import v3ReportRoutes from 'routes/v3/report';
|
||||||
import v4DataRoutes from 'routes/v4/data';
|
import v4DataRoutes from 'routes/v4/data';
|
||||||
import v4IssuesRoutes from 'routes/v4/issues';
|
|
||||||
import v4ReportRoutes from 'routes/v4/report';
|
import v4ReportRoutes from 'routes/v4/report';
|
||||||
|
import v5DataRoutes from 'routes/v5/data';
|
||||||
|
import v5IssuesRoutes from 'routes/v5/issues';
|
||||||
|
import v5ReportRoutes from 'routes/v5/report';
|
||||||
|
import v5VersionRoutes from 'routes/v5/version';
|
||||||
import environment from 'services/environment';
|
import environment from 'services/environment';
|
||||||
|
|
||||||
const server = fastify({ logger: true });
|
const server = fastify({ logger: true });
|
||||||
@ -35,8 +38,11 @@ server.register(v2ReportRoutes, { prefix: '/rest/v2' });
|
|||||||
server.register(v3DataRoutes, { prefix: '/rest/v3' });
|
server.register(v3DataRoutes, { prefix: '/rest/v3' });
|
||||||
server.register(v3ReportRoutes, { prefix: '/rest/v3' });
|
server.register(v3ReportRoutes, { prefix: '/rest/v3' });
|
||||||
server.register(v4DataRoutes, { prefix: '/rest/v4' });
|
server.register(v4DataRoutes, { prefix: '/rest/v4' });
|
||||||
server.register(v4IssuesRoutes, { prefix: '/rest/v4' });
|
|
||||||
server.register(v4ReportRoutes, { prefix: '/rest/v4' });
|
server.register(v4ReportRoutes, { prefix: '/rest/v4' });
|
||||||
|
server.register(v5DataRoutes, { prefix: '/rest/v5' });
|
||||||
|
server.register(v5IssuesRoutes, { prefix: '/rest/v5' });
|
||||||
|
server.register(v5ReportRoutes, { prefix: '/rest/v5' });
|
||||||
|
server.register(v5VersionRoutes, { prefix: '/rest/v5' });
|
||||||
|
|
||||||
server.listen({ host: '0.0.0.0', port: environment.port }, (error, address) => {
|
server.listen({ host: '0.0.0.0', port: environment.port }, (error, address) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -3,8 +3,8 @@ import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
|||||||
/**
|
/**
|
||||||
* @deprecated This API route is no longer supported. Please use a newer version
|
* @deprecated This API route is no longer supported. Please use a newer version
|
||||||
*/
|
*/
|
||||||
export default (server: FastifyInstance, options: RouteShorthandOptions, done: () => void) => {
|
export default (server: FastifyInstance, _options: RouteShorthandOptions, done: () => void) => {
|
||||||
server.get('/entries/', async (request, reply) => {
|
server.get('/entries/', async (_request, reply) => {
|
||||||
reply.send({
|
reply.send({
|
||||||
success: false,
|
success: false,
|
||||||
errors: ['This API route is no longer supported. Please use a newer version'],
|
errors: ['This API route is no longer supported. Please use a newer version'],
|
||||||
|
@ -3,7 +3,7 @@ import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
|||||||
/**
|
/**
|
||||||
* @deprecated This API route is no longer supported. Please use a newer version
|
* @deprecated This API route is no longer supported. Please use a newer version
|
||||||
*/
|
*/
|
||||||
export default (server: FastifyInstance, options: RouteShorthandOptions, done: () => void) => {
|
export default (server: FastifyInstance, _options: RouteShorthandOptions, done: () => void) => {
|
||||||
server.post('/report/', {}, async (_request, reply) => {
|
server.post('/report/', {}, async (_request, reply) => {
|
||||||
reply.send({
|
reply.send({
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import { parseNewFix } from 'services/compatibility';
|
import { parseNewFix } from 'services/compatibility';
|
||||||
|
import environment from 'services/environment';
|
||||||
|
|
||||||
export default (server: FastifyInstance, options: RouteShorthandOptions, done: () => void) => {
|
export default (server: FastifyInstance, _options: RouteShorthandOptions, done: () => void) => {
|
||||||
server.get('/data/', async (request, reply) => {
|
server.get('/data/', async (_request, reply) => {
|
||||||
try {
|
try {
|
||||||
const databaseUrl =
|
const url = `${environment.github.files}/database.json`;
|
||||||
'https://raw.githubusercontent.com/wanhose/cookie-dialog-monster/main/database.json';
|
const result = await (await fetch(url)).json();
|
||||||
const result = await (await fetch(databaseUrl)).json();
|
|
||||||
|
|
||||||
reply.send({
|
reply.send({
|
||||||
data: {
|
data: {
|
||||||
|
@ -18,7 +18,7 @@ const PostReportBodySchema = yup.object().shape({
|
|||||||
|
|
||||||
type PostReportBody = yup.InferType<typeof PostReportBodySchema>;
|
type PostReportBody = yup.InferType<typeof PostReportBodySchema>;
|
||||||
|
|
||||||
export default (server: FastifyInstance, options: RouteShorthandOptions, done: () => void) => {
|
export default (server: FastifyInstance, _options: RouteShorthandOptions, done: () => void) => {
|
||||||
server.post<{ Body: PostReportBody }>(
|
server.post<{ Body: PostReportBody }>(
|
||||||
'/report/',
|
'/report/',
|
||||||
{
|
{
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import { parseNewFix } from 'services/compatibility';
|
import { parseNewFix } from 'services/compatibility';
|
||||||
|
import environment from 'services/environment';
|
||||||
|
|
||||||
export default (server: FastifyInstance, _options: RouteShorthandOptions, done: () => void) => {
|
export default (server: FastifyInstance, _options: RouteShorthandOptions, done: () => void) => {
|
||||||
server.get('/data/', async (_request, reply) => {
|
server.get('/data/', async (_request, reply) => {
|
||||||
try {
|
try {
|
||||||
const databaseUrl =
|
const url = `${environment.github.files}/database.json`;
|
||||||
'https://raw.githubusercontent.com/wanhose/cookie-dialog-monster/main/database.json';
|
const result = await (await fetch(url)).json();
|
||||||
const result = await (await fetch(databaseUrl)).json();
|
|
||||||
|
|
||||||
reply.send({
|
reply.send({
|
||||||
data: {
|
data: {
|
||||||
|
@ -1,38 +1,18 @@
|
|||||||
import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
|
import environment from 'services/environment';
|
||||||
|
|
||||||
export default (server: FastifyInstance, _options: RouteShorthandOptions, done: () => void) => {
|
export default (server: FastifyInstance, _options: RouteShorthandOptions, done: () => void) => {
|
||||||
server.get('/data/', async (_request, reply) => {
|
server.get('/data/', async (_request, reply) => {
|
||||||
try {
|
try {
|
||||||
const databaseUrl =
|
const options = { headers: { 'Cache-Control': 'no-cache' } };
|
||||||
'https://raw.githubusercontent.com/wanhose/cookie-dialog-monster/main/database.json';
|
const url = `${environment.github.files}/database.json`;
|
||||||
const fetchOptions = {
|
const { rules, ...result } = await (await fetch(url, options)).json();
|
||||||
headers: { 'Cache-Control': 'no-cache' },
|
|
||||||
};
|
|
||||||
const { rules, ...result } = await (await fetch(databaseUrl, fetchOptions)).json();
|
|
||||||
|
|
||||||
reply.send({
|
reply.send({
|
||||||
data: {
|
data: {
|
||||||
...result,
|
...result,
|
||||||
rules: (rules as readonly string[]).map((urlFilter, index) => ({
|
rules: rules.map(toDeclarativeNetRequestRule),
|
||||||
id: index + 1,
|
|
||||||
priority: 1,
|
|
||||||
action: {
|
|
||||||
type: 'block',
|
|
||||||
},
|
|
||||||
condition: {
|
|
||||||
resourceTypes: [
|
|
||||||
'font',
|
|
||||||
'image',
|
|
||||||
'media',
|
|
||||||
'object',
|
|
||||||
'script',
|
|
||||||
'stylesheet',
|
|
||||||
'xmlhttprequest',
|
|
||||||
],
|
|
||||||
urlFilter,
|
|
||||||
},
|
|
||||||
})),
|
|
||||||
},
|
},
|
||||||
success: true,
|
success: true,
|
||||||
});
|
});
|
||||||
@ -46,3 +26,17 @@ export default (server: FastifyInstance, _options: RouteShorthandOptions, done:
|
|||||||
|
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function toDeclarativeNetRequestRule(urlFilter: string, index: number) {
|
||||||
|
return {
|
||||||
|
action: {
|
||||||
|
type: 'block',
|
||||||
|
},
|
||||||
|
condition: {
|
||||||
|
resourceTypes: ['font', 'image', 'media', 'object', 'script', 'stylesheet', 'xmlhttprequest'],
|
||||||
|
urlFilter,
|
||||||
|
},
|
||||||
|
id: index + 1,
|
||||||
|
priority: 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
1
packages/api/src/routes/v5/data.ts
Normal file
1
packages/api/src/routes/v5/data.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as default } from '../v4/data';
|
90
packages/api/src/routes/v5/report.ts
Normal file
90
packages/api/src/routes/v5/report.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
||||||
|
import environment from 'services/environment';
|
||||||
|
import { octokit } from 'services/octokit';
|
||||||
|
import { validatorCompiler } from 'services/validation';
|
||||||
|
import { UAParser } from 'ua-parser-js';
|
||||||
|
import * as yup from 'yup';
|
||||||
|
|
||||||
|
const PostReportBodySchema = yup.object().shape({
|
||||||
|
reason: yup.string().min(10).max(1000).required(),
|
||||||
|
url: yup.string().max(1000).url().required(),
|
||||||
|
userAgent: yup.string().max(1000).optional(),
|
||||||
|
version: yup
|
||||||
|
.string()
|
||||||
|
.max(10)
|
||||||
|
.matches(/^\d+(\.\d+){0,3}$/)
|
||||||
|
.required(),
|
||||||
|
});
|
||||||
|
|
||||||
|
type PostReportBody = yup.InferType<typeof PostReportBodySchema>;
|
||||||
|
|
||||||
|
export default (server: FastifyInstance, _options: RouteShorthandOptions, done: () => void) => {
|
||||||
|
server.post<{ Body: PostReportBody }>(
|
||||||
|
'/report/',
|
||||||
|
{
|
||||||
|
schema: {
|
||||||
|
body: PostReportBodySchema,
|
||||||
|
},
|
||||||
|
validatorCompiler,
|
||||||
|
},
|
||||||
|
async (request, reply) => {
|
||||||
|
const { url, userAgent } = request.body;
|
||||||
|
const ua = new UAParser(userAgent ?? '').getResult();
|
||||||
|
const hostname = new URL(url).hostname.split('.').slice(-3).join('.').replace('www.', '');
|
||||||
|
const existingIssues = await octokit.request('GET /search/issues', {
|
||||||
|
per_page: 1,
|
||||||
|
q: `in:title+is:issue+repo:${environment.github.owner}/${environment.github.repo}+${hostname}`,
|
||||||
|
});
|
||||||
|
const existingIssue = existingIssues.data.items[0];
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (existingIssue) {
|
||||||
|
reply.send({
|
||||||
|
errors: [`Issue already exists, ${existingIssue.html_url}`],
|
||||||
|
success: false,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await octokit.request('POST /repos/{owner}/{repo}/issues', {
|
||||||
|
assignees: [environment.github.owner],
|
||||||
|
body: generateText(request.body, ua),
|
||||||
|
labels: ['bug'],
|
||||||
|
owner: environment.github.owner,
|
||||||
|
repo: environment.github.repo,
|
||||||
|
title: url,
|
||||||
|
});
|
||||||
|
|
||||||
|
reply.send({
|
||||||
|
data: response.data.html_url,
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
reply.send({
|
||||||
|
errors: [error.message],
|
||||||
|
success: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
|
||||||
|
function generateText(body: PostReportBody, ua: UAParser.IResult): string {
|
||||||
|
return [
|
||||||
|
'## Issue information',
|
||||||
|
...(ua.browser.name && ua.browser.version
|
||||||
|
? ['#### 🖥️ Browser', `${ua.browser.name} (${ua.browser.version})`]
|
||||||
|
: []),
|
||||||
|
...(ua.device.type && ua.device.vendor
|
||||||
|
? ['#### 📱 Device', `${ua.device.vendor} (${ua.device.type})`]
|
||||||
|
: []),
|
||||||
|
'#### 📝 Reason',
|
||||||
|
body.reason,
|
||||||
|
'#### 🔗 URL',
|
||||||
|
body.url,
|
||||||
|
'#### 🏷️ Version',
|
||||||
|
body.version,
|
||||||
|
].join('\n');
|
||||||
|
}
|
27
packages/api/src/routes/v5/version.ts
Normal file
27
packages/api/src/routes/v5/version.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
||||||
|
import fetch from 'node-fetch';
|
||||||
|
import environment from 'services/environment';
|
||||||
|
|
||||||
|
export default (server: FastifyInstance, _options: RouteShorthandOptions, done: () => void) => {
|
||||||
|
server.get('/version/', async (_request, reply) => {
|
||||||
|
try {
|
||||||
|
const options = { headers: { 'Cache-Control': 'no-cache' } };
|
||||||
|
const url = `${environment.github.files}/packages/browser-extension/src/manifest.json`;
|
||||||
|
const { version } = await (await fetch(url, options)).json();
|
||||||
|
|
||||||
|
reply.send({
|
||||||
|
data: {
|
||||||
|
version,
|
||||||
|
},
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
reply.send({
|
||||||
|
errors: [error.message],
|
||||||
|
success: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
done();
|
||||||
|
};
|
@ -1,5 +1,6 @@
|
|||||||
export default {
|
export default {
|
||||||
github: {
|
github: {
|
||||||
|
files: 'https://raw.githubusercontent.com/wanhose/cookie-dialog-monster/main',
|
||||||
owner: 'wanhose',
|
owner: 'wanhose',
|
||||||
repo: 'cookie-dialog-monster',
|
repo: 'cookie-dialog-monster',
|
||||||
token: process.env.GITHUB_TOKEN ?? '',
|
token: process.env.GITHUB_TOKEN ?? '',
|
||||||
|
Loading…
Reference in New Issue
Block a user