feat(api): add new issues endpoint to retrieve ongoing GitHub issues and their details
This commit is contained in:
parent
8368706525
commit
71bf318c8a
@ -8,6 +8,7 @@ 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 environment from 'services/environment';
|
import environment from 'services/environment';
|
||||||
|
|
||||||
@ -34,6 +35,7 @@ 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.listen({ host: '0.0.0.0', port: environment.port }, (error, address) => {
|
server.listen({ host: '0.0.0.0', port: environment.port }, (error, address) => {
|
||||||
|
@ -5,7 +5,7 @@ import { validatorCompiler } from 'services/validation';
|
|||||||
import { UAParser } from 'ua-parser-js';
|
import { UAParser } from 'ua-parser-js';
|
||||||
import * as yup from 'yup';
|
import * as yup from 'yup';
|
||||||
|
|
||||||
const PostBodyReportSchema = yup.object().shape({
|
const PostReportBodySchema = yup.object().shape({
|
||||||
reason: yup.string().min(10).max(1000).required(),
|
reason: yup.string().min(10).max(1000).required(),
|
||||||
url: yup.string().max(1000).url().required(),
|
url: yup.string().max(1000).url().required(),
|
||||||
userAgent: yup.string().max(1000).optional(),
|
userAgent: yup.string().max(1000).optional(),
|
||||||
@ -16,14 +16,14 @@ const PostBodyReportSchema = yup.object().shape({
|
|||||||
.required(),
|
.required(),
|
||||||
});
|
});
|
||||||
|
|
||||||
type PostReportBody = yup.InferType<typeof PostBodyReportSchema>;
|
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/',
|
||||||
{
|
{
|
||||||
schema: {
|
schema: {
|
||||||
body: PostBodyReportSchema,
|
body: PostReportBodySchema,
|
||||||
},
|
},
|
||||||
validatorCompiler,
|
validatorCompiler,
|
||||||
},
|
},
|
||||||
|
@ -5,7 +5,7 @@ import { validatorCompiler } from 'services/validation';
|
|||||||
import { UAParser } from 'ua-parser-js';
|
import { UAParser } from 'ua-parser-js';
|
||||||
import * as yup from 'yup';
|
import * as yup from 'yup';
|
||||||
|
|
||||||
const PostBodyReportSchema = yup.object().shape({
|
const PostReportBodySchema = yup.object().shape({
|
||||||
reason: yup.string().min(10).max(1000).required(),
|
reason: yup.string().min(10).max(1000).required(),
|
||||||
url: yup.string().max(1000).url().required(),
|
url: yup.string().max(1000).url().required(),
|
||||||
userAgent: yup.string().max(1000).optional(),
|
userAgent: yup.string().max(1000).optional(),
|
||||||
@ -16,27 +16,24 @@ const PostBodyReportSchema = yup.object().shape({
|
|||||||
.required(),
|
.required(),
|
||||||
});
|
});
|
||||||
|
|
||||||
type PostReportBody = yup.InferType<typeof PostBodyReportSchema>;
|
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/',
|
||||||
{
|
{
|
||||||
schema: {
|
schema: {
|
||||||
body: PostBodyReportSchema,
|
body: PostReportBodySchema,
|
||||||
},
|
},
|
||||||
validatorCompiler,
|
validatorCompiler,
|
||||||
},
|
},
|
||||||
async (request, reply) => {
|
async (request, reply) => {
|
||||||
const ua = new UAParser(request.body.userAgent ?? '').getResult();
|
const { url, userAgent } = request.body;
|
||||||
const url = new URL(request.body.url).hostname
|
const ua = new UAParser(userAgent ?? '').getResult();
|
||||||
.split('.')
|
const hostname = new URL(url).hostname.split('.').slice(-3).join('.').replace('www.', '');
|
||||||
.slice(-3)
|
|
||||||
.join('.')
|
|
||||||
.replace('www.', '');
|
|
||||||
const existingIssues = await octokit.request('GET /search/issues', {
|
const existingIssues = await octokit.request('GET /search/issues', {
|
||||||
per_page: 1,
|
per_page: 1,
|
||||||
q: `in:title+is:issue+repo:${environment.github.owner}/${environment.github.repo}+${url}`,
|
q: `in:title+is:issue+repo:${environment.github.owner}/${environment.github.repo}+${hostname}`,
|
||||||
});
|
});
|
||||||
const existingIssue = existingIssues.data.items[0];
|
const existingIssue = existingIssues.data.items[0];
|
||||||
|
|
||||||
|
60
packages/api/src/routes/v4/issues.ts
Normal file
60
packages/api/src/routes/v4/issues.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { FastifyInstance, RouteShorthandOptions } from 'fastify';
|
||||||
|
import environment from 'services/environment';
|
||||||
|
import { octokit } from 'services/octokit';
|
||||||
|
import { validatorCompiler } from 'services/validation';
|
||||||
|
import * as yup from 'yup';
|
||||||
|
|
||||||
|
const GetIssuesParamsSchema = yup.object().shape({
|
||||||
|
hostname: yup.string().required(),
|
||||||
|
});
|
||||||
|
|
||||||
|
type GetIssuesParams = yup.InferType<typeof GetIssuesParamsSchema>;
|
||||||
|
|
||||||
|
export default (server: FastifyInstance, _options: RouteShorthandOptions, done: () => void) => {
|
||||||
|
server.get<{ Params: GetIssuesParams }>(
|
||||||
|
'/issues/:hostname',
|
||||||
|
{
|
||||||
|
schema: {
|
||||||
|
params: GetIssuesParamsSchema,
|
||||||
|
},
|
||||||
|
validatorCompiler,
|
||||||
|
},
|
||||||
|
async (request, reply) => {
|
||||||
|
try {
|
||||||
|
const { hostname } = request.params;
|
||||||
|
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];
|
||||||
|
|
||||||
|
if (
|
||||||
|
existingIssue &&
|
||||||
|
(existingIssue.state === 'open' ||
|
||||||
|
(existingIssue.state === 'closed' &&
|
||||||
|
existingIssue.labels.some((label) => label.name === 'wontfix')))
|
||||||
|
) {
|
||||||
|
reply.send({
|
||||||
|
data: {
|
||||||
|
flags: existingIssue.labels.map((label) => label.name),
|
||||||
|
url: existingIssue.html_url,
|
||||||
|
},
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
reply.send({
|
||||||
|
data: {},
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
reply.send({
|
||||||
|
errors: [error.message],
|
||||||
|
success: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user