2022-09-12 12:45:19 +02:00
|
|
|
import { ApplicationFunction } from 'probot';
|
|
|
|
|
2022-09-13 10:03:48 +02:00
|
|
|
const bot: ApplicationFunction = (app) => {
|
2022-09-12 20:58:06 +02:00
|
|
|
app.on(
|
|
|
|
['pull_request.opened', 'pull_request.synchronize'],
|
|
|
|
async (context) => {
|
|
|
|
const registryDirectoryPath = 'playlists/registry/';
|
|
|
|
const siQueryStart = '?si=';
|
2022-09-13 15:32:52 +02:00
|
|
|
|
2022-09-12 20:58:06 +02:00
|
|
|
const pull_number = context.payload.number;
|
2022-09-14 06:53:05 +02:00
|
|
|
const currentRepoData = {
|
2022-09-13 10:03:48 +02:00
|
|
|
owner: context.payload.repository.owner.login,
|
|
|
|
repo: context.payload.repository.name
|
2022-09-12 20:58:06 +02:00
|
|
|
};
|
|
|
|
|
2022-09-14 06:53:05 +02:00
|
|
|
const repoAllowlist = [
|
|
|
|
{ owner: 'mackorone', repo: 'spotify-playlist-archive' },
|
|
|
|
{ owner: 'maciejpedzich', repo: 'bot-testing-ground' }
|
|
|
|
];
|
2022-09-13 15:32:52 +02:00
|
|
|
|
2022-09-12 20:58:06 +02:00
|
|
|
const removePathFromFilename = (filename: string) =>
|
|
|
|
filename.replace(registryDirectoryPath, '');
|
|
|
|
|
2022-09-13 15:32:52 +02:00
|
|
|
const upsertReview = async (body: string, review_id?: number) => {
|
2022-09-12 20:58:06 +02:00
|
|
|
if (review_id) {
|
|
|
|
await context.octokit.pulls.updateReview({
|
2022-09-14 06:53:05 +02:00
|
|
|
...currentRepoData,
|
2022-09-12 20:58:06 +02:00
|
|
|
pull_number,
|
|
|
|
review_id,
|
|
|
|
body
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
await context.octokit.pulls.createReview({
|
2022-09-14 06:53:05 +02:00
|
|
|
...currentRepoData,
|
2022-09-12 20:58:06 +02:00
|
|
|
pull_number,
|
|
|
|
event: 'REQUEST_CHANGES',
|
2022-09-14 06:53:05 +02:00
|
|
|
body: `Hey there, thank you for taking interest in this project!\n${body}`
|
2022-09-12 20:58:06 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
2022-09-14 06:53:05 +02:00
|
|
|
const isAllowlistedRepo = repoAllowlist.find(
|
|
|
|
({ owner, repo }) =>
|
|
|
|
currentRepoData.owner === owner && currentRepoData.repo === repo
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!isAllowlistedRepo) return;
|
|
|
|
|
2022-09-12 20:58:06 +02:00
|
|
|
const { data: prFiles } = await context.octokit.pulls.listFiles({
|
2022-09-14 06:53:05 +02:00
|
|
|
...currentRepoData,
|
2022-09-12 20:58:06 +02:00
|
|
|
pull_number
|
|
|
|
});
|
|
|
|
|
|
|
|
const filesToVerify = prFiles.filter(
|
|
|
|
({ status, filename }) =>
|
|
|
|
status === 'added' && filename.startsWith(registryDirectoryPath)
|
|
|
|
);
|
|
|
|
|
|
|
|
const filesWithSiQuery = filesToVerify.filter(({ filename }) =>
|
|
|
|
filename.includes(siQueryStart)
|
|
|
|
);
|
|
|
|
|
|
|
|
const playlistLookupResults = await Promise.all(
|
|
|
|
filesToVerify.map(async ({ filename }) => {
|
|
|
|
const filenameWithoutPath = removePathFromFilename(filename);
|
|
|
|
const spotifyResponse = await fetch(
|
|
|
|
`https://open.spotify.com/playlist/${filenameWithoutPath}`
|
|
|
|
);
|
|
|
|
|
|
|
|
return {
|
|
|
|
filename: removePathFromFilename(filename),
|
|
|
|
found: spotifyResponse.status === 200
|
|
|
|
};
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
const notFoundPlaylists = playlistLookupResults.filter(
|
|
|
|
({ found }) => !found
|
|
|
|
);
|
|
|
|
|
|
|
|
const { data: priorReviews } = await context.octokit.pulls.listReviews({
|
2022-09-14 06:53:05 +02:00
|
|
|
...currentRepoData,
|
2022-09-12 20:58:06 +02:00
|
|
|
pull_number
|
|
|
|
});
|
|
|
|
|
|
|
|
const [existingReview] = priorReviews;
|
|
|
|
|
|
|
|
if (notFoundPlaylists.length > 0) {
|
|
|
|
const renameList = notFoundPlaylists
|
|
|
|
.map(({ filename }) => `- ${filename}`)
|
|
|
|
.join('\n');
|
|
|
|
|
2022-09-13 10:03:48 +02:00
|
|
|
const body = `It looks like the following playlists don't exist:\n${renameList}`;
|
|
|
|
|
|
|
|
await upsertReview(body, existingReview?.id);
|
|
|
|
} else if (filesWithSiQuery.length > 0) {
|
|
|
|
const renameList = filesWithSiQuery
|
|
|
|
.map(({ filename }) => {
|
|
|
|
const filenameWithoutPath = removePathFromFilename(filename);
|
|
|
|
const [targetFilename] = filenameWithoutPath.split(siQueryStart);
|
|
|
|
|
|
|
|
return `- Rename ${filenameWithoutPath} to **${targetFilename}**`;
|
|
|
|
})
|
|
|
|
.join('\n');
|
|
|
|
|
2022-09-16 06:07:55 +02:00
|
|
|
const body = `All new files point to existing playlists, but you have to:\n${renameList}`;
|
2022-09-12 20:58:06 +02:00
|
|
|
|
|
|
|
await upsertReview(body, existingReview?.id);
|
|
|
|
} else {
|
2022-09-13 10:03:48 +02:00
|
|
|
if (existingReview) {
|
|
|
|
await context.octokit.pulls.dismissReview({
|
2022-09-14 06:53:05 +02:00
|
|
|
...currentRepoData,
|
2022-09-13 10:03:48 +02:00
|
|
|
pull_number,
|
|
|
|
review_id: existingReview.id,
|
2022-09-16 06:07:55 +02:00
|
|
|
message: '🎉 Your pull request can be merged! 🎉'
|
2022-09-12 20:58:06 +02:00
|
|
|
});
|
|
|
|
}
|
2022-09-13 10:03:48 +02:00
|
|
|
|
2022-09-14 06:53:05 +02:00
|
|
|
// TODO: Change successful validation handling
|
|
|
|
// await context.octokit.pulls.merge({
|
|
|
|
// ...currentRepoData,
|
|
|
|
// pull_number
|
|
|
|
// });
|
2022-09-12 20:58:06 +02:00
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
await context.octokit.pulls.createReview({
|
2022-09-14 06:53:05 +02:00
|
|
|
...currentRepoData,
|
2022-09-12 20:58:06 +02:00
|
|
|
pull_number,
|
|
|
|
event: 'COMMENT',
|
2022-09-14 06:53:05 +02:00
|
|
|
body: 'Something went wrong while verifying your entries! @mackorone should handle it shortly.'
|
2022-09-12 20:58:06 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2022-09-12 12:45:19 +02:00
|
|
|
};
|
|
|
|
|
2022-09-13 10:03:48 +02:00
|
|
|
export = bot;
|