Rework message format and handling valid playlists

This commit is contained in:
Maciej Pędzich 2022-09-21 22:39:54 +02:00
parent 27e2eec422
commit 724a52a28e

143
bot.ts
View File

@ -1,4 +1,5 @@
import { ApplicationFunction } from 'probot'; import { ApplicationFunction } from 'probot';
import getMetaData from 'metadata-scraper';
const bot: ApplicationFunction = (app) => { const bot: ApplicationFunction = (app) => {
app.on( app.on(
@ -8,7 +9,7 @@ const bot: ApplicationFunction = (app) => {
const siQueryStart = '?si='; const siQueryStart = '?si=';
const pull_number = context.payload.number; const pull_number = context.payload.number;
const currentRepoData = { const workingRepo = {
owner: context.payload.repository.owner.login, owner: context.payload.repository.owner.login,
repo: context.payload.repository.name repo: context.payload.repository.name
}; };
@ -21,34 +22,42 @@ const bot: ApplicationFunction = (app) => {
const removePathFromFilename = (filename: string) => const removePathFromFilename = (filename: string) =>
filename.replace(registryDirectoryPath, ''); filename.replace(registryDirectoryPath, '');
const upsertReview = async (body: string, review_id?: number) => { const upsertReview = async (
review_id: number | undefined,
body: string,
event: 'REQUEST_CHANGES' | 'COMMENT'
) => {
if (review_id) { if (review_id) {
await context.octokit.pulls.updateReview({ const { data } = await context.octokit.pulls.updateReview({
...currentRepoData, ...workingRepo,
pull_number, pull_number,
review_id, review_id,
body body
}); });
return data.id;
} else { } else {
await context.octokit.pulls.createReview({ const { data } = await context.octokit.pulls.createReview({
...currentRepoData, ...workingRepo,
pull_number, pull_number,
event: 'REQUEST_CHANGES', event,
body: `Hey there, thank you for taking interest in this project!\n${body}` body
}); });
return data.id;
} }
}; };
try { try {
const isAllowlistedRepo = repoAllowlist.find( const allowlistedRepo = repoAllowlist.find(
({ owner, repo }) => ({ owner, repo }) =>
currentRepoData.owner === owner && currentRepoData.repo === repo workingRepo.owner === owner && workingRepo.repo === repo
); );
if (!isAllowlistedRepo) return; if (!allowlistedRepo) return;
const { data: prFiles } = await context.octokit.pulls.listFiles({ const { data: prFiles } = await context.octokit.pulls.listFiles({
...currentRepoData, ...workingRepo,
pull_number pull_number
}); });
@ -57,78 +66,124 @@ const bot: ApplicationFunction = (app) => {
status === 'added' && filename.startsWith(registryDirectoryPath) status === 'added' && filename.startsWith(registryDirectoryPath)
); );
const filesWithSiQuery = filesToVerify.filter(({ filename }) =>
filename.includes(siQueryStart)
);
const playlistLookupResults = await Promise.all( const playlistLookupResults = await Promise.all(
filesToVerify.map(async ({ filename }) => { filesToVerify.map(async ({ filename }) => {
const filenameWithoutPath = removePathFromFilename(filename); const filenameWithoutPath = removePathFromFilename(filename);
const spotifyResponse = await fetch( const url = `https://open.spotify.com/playlist/${filenameWithoutPath}`;
`https://open.spotify.com/playlist/${filenameWithoutPath}`
); const spotifyResponse = await fetch(url);
const found = spotifyResponse.status === 200;
let info: string | null = null;
if (found) {
const html = await spotifyResponse.text();
const { title, description } = await getMetaData({ html });
const playlistMeta = (description || '')
.split(' · ')
.filter((text) => text !== 'Playlist');
info = [title, ...playlistMeta].join(' · ');
}
return { return {
filename: removePathFromFilename(filename), filename: removePathFromFilename(filename),
found: spotifyResponse.status === 200 found,
info,
url
}; };
}) })
); );
const validEntries = playlistLookupResults.filter(
({ found, filename }) => found && !filename.includes(siQueryStart)
);
const entriesWithSiQuery = playlistLookupResults.filter(
({ found, filename }) => found && filename.includes(siQueryStart)
);
const notFoundPlaylists = playlistLookupResults.filter( const notFoundPlaylists = playlistLookupResults.filter(
({ found }) => !found ({ found }) => !found
); );
const { data: priorReviews } = await context.octokit.pulls.listReviews({ const { data: priorReviews } = await context.octokit.pulls.listReviews({
...currentRepoData, ...workingRepo,
pull_number pull_number
}); });
const [existingReview] = priorReviews; const [existingReview] = priorReviews;
const canMergeMessage = `🎉 @${workingRepo.owner} can merge your pull request! 🎉`;
let identifiedPlaylistsText = '';
let renameRequiredText = '';
let notFoundText = '';
let successText = canMergeMessage;
let reviewEvent: 'REQUEST_CHANGES' | 'COMMENT' = 'COMMENT';
if (validEntries.length > 0) {
const playlistLinks = validEntries
.map(({ url, info }) => `- [${info}](${url})`)
.join('\n');
identifiedPlaylistsText = `### ✅ These playlists were indentified:\n${playlistLinks}`;
}
if (notFoundPlaylists.length > 0) { if (notFoundPlaylists.length > 0) {
const renameList = notFoundPlaylists const renameList = notFoundPlaylists
.map(({ filename }) => `- ${filename}`) .map(({ filename }) => `- ${filename}`)
.join('\n'); .join('\n');
const body = `It looks like the following playlists don't exist:\n${renameList}`; successText = '';
reviewEvent = 'REQUEST_CHANGES';
notFoundText = `### ❌ Playlists for these entries were not found:\n${renameList}`;
}
await upsertReview(body, existingReview?.id); if (entriesWithSiQuery.length > 0) {
} else if (filesWithSiQuery.length > 0) { const renameList = entriesWithSiQuery
const renameList = filesWithSiQuery
.map(({ filename }) => { .map(({ filename }) => {
const filenameWithoutPath = removePathFromFilename(filename); const filenameWithoutPath = removePathFromFilename(filename);
const [targetFilename] = filenameWithoutPath.split(siQueryStart); const [targetFilename] = filenameWithoutPath.split(siQueryStart);
return `- Rename ${filenameWithoutPath} to **${targetFilename}**`; return `- From ${filenameWithoutPath} to **${targetFilename}**`;
}) })
.join('\n'); .join('\n');
const body = `All new files point to existing playlists, but you have to:\n${renameList}`; successText = '';
reviewEvent = 'REQUEST_CHANGES';
renameRequiredText = `### ⚠️ These entries have to be renamed:\n${renameList}`;
}
await upsertReview(body, existingReview?.id); const reviewBody = [
} else { identifiedPlaylistsText,
if (existingReview) { renameRequiredText,
await context.octokit.pulls.dismissReview({ notFoundText,
...currentRepoData, successText
pull_number, ]
review_id: existingReview.id, .filter(Boolean)
message: '🎉 Your pull request can be merged! 🎉' .join('\n\n');
});
}
// TODO: Change successful validation handling await upsertReview(existingReview?.id, reviewBody, reviewEvent);
// await context.octokit.pulls.merge({
// ...currentRepoData, if (
// pull_number renameRequiredText === '' &&
// }); notFoundText === '' &&
existingReview?.id
) {
await context.octokit.pulls.dismissReview({
...workingRepo,
pull_number,
review_id: existingReview.id,
message: 'All new entries are now valid!'
});
} }
} catch (error) { } catch (error) {
console.error(error);
await context.octokit.pulls.createReview({ await context.octokit.pulls.createReview({
...currentRepoData, ...workingRepo,
pull_number, pull_number,
event: 'COMMENT', event: 'COMMENT',
body: 'Something went wrong while verifying your entries! @mackorone should handle it shortly.' body: `Something went wrong while verifying new entries! @${workingRepo.owner} should handle it shortly...`
}); });
} }
} }