From fbc1e0d6cc2b8f6a4ffd037a4719142063de6daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=83=AC=E3=82=AF=E3=82=B5=E3=83=B3=E3=83=80?= =?UTF-8?q?=E3=83=BC=2Eeth?= Date: Fri, 7 Jul 2023 15:15:04 +0900 Subject: [PATCH 01/88] chore: sync upstream --- package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 8d05c1033..08f125862 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,10 @@ "start:serverless": "tsx src/adapters/github/github-actions.ts", "start:watch": "nodemon --exec 'yarn start'", "start": "probot run ./lib/index.js", - "prepare": "husky install" + "prepare": "husky install", + "utils:sync-upstream-1": "git fetch upstream", + "utils:sync-upstream-2": "git merge upstream/development", + "utils:sync-upstream-3": "git push origin development" }, "dependencies": { "@actions/core": "^1.10.0", From 25a928bb3a327721173e00d154fbfcfce454a23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=83=AC=E3=82=AF=E3=82=B5=E3=83=B3=E3=83=80?= =?UTF-8?q?=E3=83=BC=2Eeth?= Date: Sun, 20 Aug 2023 20:39:59 +0900 Subject: [PATCH 02/88] refactor: remove unused declaration --- src/adapters/supabase/helpers/client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapters/supabase/helpers/client.ts b/src/adapters/supabase/helpers/client.ts index d0610c090..c914c1843 100644 --- a/src/adapters/supabase/helpers/client.ts +++ b/src/adapters/supabase/helpers/client.ts @@ -169,13 +169,13 @@ export const upsertWalletAddress = async (username: string, address: string): Pr }); logger.info(`Upserting a wallet address done, { data: ${data}, error: ${error} }`); } else { - const { data: _data, error: _error } = await supabase.from("wallets").insert({ + const { error } = await supabase.from("wallets").insert({ user_name: username, wallet_address: address, created_at: new Date().toUTCString(), updated_at: new Date().toUTCString(), }); - logger.info(`Creating a new wallet_table record done, { error: ${_error?.message} }`); + logger.info(`Creating a new wallet_table record done, { error: ${error?.message} }`); } }; From 4b973fc281d8b6b6164f422d8177a5efd514079f Mon Sep 17 00:00:00 2001 From: HARALD Date: Wed, 23 Aug 2023 11:05:24 +0900 Subject: [PATCH 03/88] feat: incentiveForPullRequest reviewers --- package.json | 3 +- src/handlers/payout/post.ts | 144 +++++++++++++++++++++++++++++++++++- src/handlers/processors.ts | 4 +- 3 files changed, 147 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index bf2367eb1..fa7b7a601 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "@sinclair/typebox": "^0.25.9", "@supabase/supabase-js": "^2.4.0", "@types/ms": "^0.7.31", + "@types/parse5": "^7.0.0", "@typescript-eslint/eslint-plugin": "^5.59.11", "@typescript-eslint/parser": "^5.59.11", "@uniswap/permit2-sdk": "^1.2.0", @@ -41,8 +42,8 @@ "ajv": "^8.11.2", "ajv-formats": "^2.1.1", "axios": "^1.3.2", - "decimal.js": "^10.4.3", "copyfiles": "^2.4.1", + "decimal.js": "^10.4.3", "ethers": "^5.7.2", "husky": "^8.0.2", "jimp": "^0.22.4", diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index 17c8eb4ad..4a9171520 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -1,6 +1,16 @@ import { getWalletAddress } from "../../adapters/supabase"; import { getBotConfig, getBotContext, getLogger } from "../../bindings"; -import { addCommentToIssue, generatePermit2Signature, getAllIssueComments, getIssueDescription, getTokenSymbol, parseComments } from "../../helpers"; +import { + addCommentToIssue, + generatePermit2Signature, + getAllIssueComments, + getAllPullRequestReviews, + getAllPullRequests, + getIssueDescription, + getTokenSymbol, + parseComments, +} from "../../helpers"; +import { gitLinkedIssueParser } from "../../helpers/parser"; import { Incentives, Payload, StateReason, UserType } from "../../types"; import { commentParser } from "../comment"; import Decimal from "decimal.js"; @@ -121,6 +131,138 @@ export const incentivizeComments = async () => { await addCommentToIssue(comment, issue.number); }; +export const incentivizePullRequestReviews = async () => { + const logger = getLogger(); + const { + mode: { incentiveMode, paymentPermitMaxPrice }, + price: { baseMultiplier, incentives }, + payout: { paymentToken, rpc }, + } = getBotConfig(); + if (!incentiveMode) { + logger.info(`No incentive mode. skipping to process`); + // return; + } + const context = getBotContext(); + const payload = context.payload as Payload; + const issue = payload.issue; + if (!issue) { + logger.info(`Incomplete payload. issue: ${issue}`); + return; + } + + if (issue.state_reason !== StateReason.COMPLETED) { + logger.info("incentivizeComments: comment incentives skipped because the issue was not closed as completed"); + // return; + } + + if (paymentPermitMaxPrice == 0 || !paymentPermitMaxPrice) { + logger.info(`incentivizeComments: skipping to generate permit2 url, reason: { paymentPermitMaxPrice: ${paymentPermitMaxPrice}}`); + // return; + } + + const issueDetailed = bountyInfo(issue); + if (!issueDetailed.isBounty) { + logger.info(`incentivizeComments: its not a bounty`); + // return; + } + + const pulls = await getAllPullRequests(context, "closed"); + if (pulls.length === 0) { + logger.debug(`No pull requests found at this time`); + return; + } + + let linkedPull; + + for (const pull of pulls) { + const pullRequestLinked = await gitLinkedIssueParser({ + owner: payload.repository.owner.login, + repo: payload.repository.name, + issue_number: pull.number, + }); + const linkedIssueNumber = pullRequestLinked.substring(pullRequestLinked.lastIndexOf("/") + 1); + if (linkedIssueNumber === issue.number.toString()) { + linkedPull = pull; + break; + } + } + + if (!linkedPull) { + logger.debug(`No linked pull requests found`); + return; + } + + const comments = await getAllIssueComments(issue.number); + const permitComments = comments.filter( + (content) => content.body.includes("Reviewer Rewards") && content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot + ); + if (permitComments.length > 0) { + logger.info(`incentivizePullRequestReviews: skip to generate a permit url because it has been already posted`); + return; + } + + const assignees = issue?.assignees ?? []; + const assignee = assignees.length > 0 ? assignees[0] : undefined; + if (!assignee) { + logger.info("incentivizePullRequestReviews: skipping payment permit generation because `assignee` is `undefined`."); + return; + } + + const prReviews = await getAllPullRequestReviews(context, linkedPull.number); + logger.info(`Getting the PR reviews done. comments: ${JSON.stringify(prReviews)}`); + const prReviewsByUser: Record = {}; + for (const review of prReviews) { + const user = review.user; + if (!user) continue; + if (user.type == UserType.Bot || user.login == assignee) continue; + if (!review.body) { + logger.info(`Skipping to parse the comment because body_html is undefined. comment: ${JSON.stringify(review)}`); + continue; + } + if (!prReviewsByUser[user.login]) { + prReviewsByUser[user.login] = []; + } + prReviewsByUser[user.login].push(review.body); + } + const tokenSymbol = await getTokenSymbol(paymentToken, rpc); + logger.info(`Filtering by the user type done. commentsByUser: ${JSON.stringify(prReviewsByUser)}`); + + // The mapping between gh handle and comment with a permit url + const reward: Record = {}; + + // The mapping between gh handle and amount in ETH + const fallbackReward: Record = {}; + let comment = `#### Reviewer Rewards\n`; + for (const user of Object.keys(prReviewsByUser)) { + const comments = prReviewsByUser[user]; + const commentsByNode = await parseComments(comments, ItemsToExclude); + const rewardValue = calculateRewardValue(commentsByNode, incentives); + if (rewardValue.equals(0)) { + logger.info(`Skipping to generate a permit url because the reward value is 0. user: ${user}`); + continue; + } + logger.info(`Comment parsed for the user: ${user}. comments: ${JSON.stringify(commentsByNode)}, sum: ${rewardValue}`); + const account = await getWalletAddress(user); + const amountInETH = rewardValue.mul(baseMultiplier).div(1000); + if (amountInETH.gt(paymentPermitMaxPrice)) { + logger.info(`Skipping comment reward for user ${user} because reward is higher than payment permit max price`); + continue; + } + if (account) { + const { payoutUrl } = await generatePermit2Signature(account, amountInETH, issue.node_id); + comment = `${comment}### [ **${user}: [ CLAIM ${amountInETH} ${tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n`; + reward[user] = payoutUrl; + } else { + fallbackReward[user] = amountInETH; + } + } + + logger.info(`Permit url generated for contributors. reward: ${JSON.stringify(reward)}`); + logger.info(`Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(fallbackReward)}`); + + await addCommentToIssue(comment, issue.number); +}; + export const incentivizeCreatorComment = async () => { const logger = getLogger(); const { diff --git a/src/handlers/processors.ts b/src/handlers/processors.ts index d64e07eaa..1c274db02 100644 --- a/src/handlers/processors.ts +++ b/src/handlers/processors.ts @@ -7,7 +7,7 @@ import { handleComment, issueClosedCallback, issueReopenedCallback } from "./com import { checkPullRequests } from "./assign/auto"; import { createDevPoolPR } from "./pull-request"; import { runOnPush } from "./push"; -import { incentivizeComments, incentivizeCreatorComment } from "./payout"; +import { incentivizeComments, incentivizeCreatorComment, incentivizePullRequestReviews } from "./payout"; export const processors: Record = { [GithubEvent.ISSUES_OPENED]: { @@ -53,7 +53,7 @@ export const processors: Record = { [GithubEvent.ISSUES_CLOSED]: { pre: [nullHandler], action: [issueClosedCallback], - post: [incentivizeCreatorComment, incentivizeComments], + post: [incentivizeCreatorComment, incentivizeComments, incentivizePullRequestReviews], }, [GithubEvent.PULL_REQUEST_OPENED]: { pre: [nullHandler], From aa84e7d641a89ea5c50d8734ef1b980079febc80 Mon Sep 17 00:00:00 2001 From: HARALD Date: Wed, 23 Aug 2023 11:26:28 +0900 Subject: [PATCH 04/88] feat: minor fix --- src/handlers/payout/post.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index 4a9171520..89095d55e 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -151,24 +151,24 @@ export const incentivizePullRequestReviews = async () => { } if (issue.state_reason !== StateReason.COMPLETED) { - logger.info("incentivizeComments: comment incentives skipped because the issue was not closed as completed"); + logger.info("incentivizePullRequestReviews: comment incentives skipped because the issue was not closed as completed"); // return; } if (paymentPermitMaxPrice == 0 || !paymentPermitMaxPrice) { - logger.info(`incentivizeComments: skipping to generate permit2 url, reason: { paymentPermitMaxPrice: ${paymentPermitMaxPrice}}`); + logger.info(`incentivizePullRequestReviews: skipping to generate permit2 url, reason: { paymentPermitMaxPrice: ${paymentPermitMaxPrice}}`); // return; } const issueDetailed = bountyInfo(issue); if (!issueDetailed.isBounty) { - logger.info(`incentivizeComments: its not a bounty`); + logger.info(`incentivizePullRequestReviews: its not a bounty`); // return; } const pulls = await getAllPullRequests(context, "closed"); if (pulls.length === 0) { - logger.debug(`No pull requests found at this time`); + logger.debug(`incentivizePullRequestReviews: No pull requests found at this time`); return; } @@ -188,7 +188,7 @@ export const incentivizePullRequestReviews = async () => { } if (!linkedPull) { - logger.debug(`No linked pull requests found`); + logger.debug(`incentivizePullRequestReviews: No linked pull requests found`); return; } @@ -216,7 +216,7 @@ export const incentivizePullRequestReviews = async () => { if (!user) continue; if (user.type == UserType.Bot || user.login == assignee) continue; if (!review.body) { - logger.info(`Skipping to parse the comment because body_html is undefined. comment: ${JSON.stringify(review)}`); + logger.info(`incentivizePullRequestReviews: Skipping to parse the comment because body_html is undefined. comment: ${JSON.stringify(review)}`); continue; } if (!prReviewsByUser[user.login]) { @@ -225,7 +225,7 @@ export const incentivizePullRequestReviews = async () => { prReviewsByUser[user.login].push(review.body); } const tokenSymbol = await getTokenSymbol(paymentToken, rpc); - logger.info(`Filtering by the user type done. commentsByUser: ${JSON.stringify(prReviewsByUser)}`); + logger.info(`incentivizePullRequestReviews: Filtering by the user type done. commentsByUser: ${JSON.stringify(prReviewsByUser)}`); // The mapping between gh handle and comment with a permit url const reward: Record = {}; @@ -238,14 +238,14 @@ export const incentivizePullRequestReviews = async () => { const commentsByNode = await parseComments(comments, ItemsToExclude); const rewardValue = calculateRewardValue(commentsByNode, incentives); if (rewardValue.equals(0)) { - logger.info(`Skipping to generate a permit url because the reward value is 0. user: ${user}`); + logger.info(`incentivizePullRequestReviews: Skipping to generate a permit url because the reward value is 0. user: ${user}`); continue; } - logger.info(`Comment parsed for the user: ${user}. comments: ${JSON.stringify(commentsByNode)}, sum: ${rewardValue}`); + logger.info(`incentivizePullRequestReviews: Comment parsed for the user: ${user}. comments: ${JSON.stringify(commentsByNode)}, sum: ${rewardValue}`); const account = await getWalletAddress(user); const amountInETH = rewardValue.mul(baseMultiplier).div(1000); if (amountInETH.gt(paymentPermitMaxPrice)) { - logger.info(`Skipping comment reward for user ${user} because reward is higher than payment permit max price`); + logger.info(`incentivizePullRequestReviews: Skipping comment reward for user ${user} because reward is higher than payment permit max price`); continue; } if (account) { @@ -257,8 +257,8 @@ export const incentivizePullRequestReviews = async () => { } } - logger.info(`Permit url generated for contributors. reward: ${JSON.stringify(reward)}`); - logger.info(`Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(fallbackReward)}`); + logger.info(`incentivizePullRequestReviews: Permit url generated for pull request reviewers. reward: ${JSON.stringify(reward)}`); + logger.info(`incentivizePullRequestReviews: Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(fallbackReward)}`); await addCommentToIssue(comment, issue.number); }; From 109758e19bbef1309fe6dff5e2d97105f9233d0b Mon Sep 17 00:00:00 2001 From: HARALD Date: Wed, 23 Aug 2023 11:36:09 +0900 Subject: [PATCH 05/88] feat: slight change --- src/handlers/payout/post.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index 89095d55e..be3104fb7 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -131,7 +131,7 @@ export const incentivizeComments = async () => { await addCommentToIssue(comment, issue.number); }; -export const incentivizePullRequestReviews = async () => { +export async function incentivizePullRequestReviews() { const logger = getLogger(); const { mode: { incentiveMode, paymentPermitMaxPrice }, @@ -261,7 +261,7 @@ export const incentivizePullRequestReviews = async () => { logger.info(`incentivizePullRequestReviews: Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(fallbackReward)}`); await addCommentToIssue(comment, issue.number); -}; +} export const incentivizeCreatorComment = async () => { const logger = getLogger(); From 12bccaeea35636665f31e859fe011527801d8004 Mon Sep 17 00:00:00 2001 From: HARALD Date: Wed, 23 Aug 2023 11:37:01 +0900 Subject: [PATCH 06/88] feat: fix function declaration --- src/handlers/payout/post.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index be3104fb7..ac423fda7 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -21,7 +21,7 @@ const ItemsToExclude: string[] = ["blockquote"]; * Incentivize the contributors based on their contribution. * The default formula has been defined in https://github.com/ubiquity/ubiquibot/issues/272 */ -export const incentivizeComments = async () => { +export async function incentivizeComments() { const logger = getLogger(); const { mode: { incentiveMode, paymentPermitMaxPrice }, @@ -129,7 +129,7 @@ export const incentivizeComments = async () => { logger.info(`Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(fallbackReward)}`); await addCommentToIssue(comment, issue.number); -}; +} export async function incentivizePullRequestReviews() { const logger = getLogger(); From 25c4da5e4eacb131963949f7739ec2c2003301ed Mon Sep 17 00:00:00 2001 From: HARALD Date: Wed, 23 Aug 2023 18:25:33 +0900 Subject: [PATCH 07/88] feat: renamed some variables --- src/helpers/parser.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/helpers/parser.ts b/src/helpers/parser.ts index b05411fee..fed365efd 100644 --- a/src/helpers/parser.ts +++ b/src/helpers/parser.ts @@ -25,19 +25,19 @@ export const gitIssueParser = async ({ owner, repo, issue_number }: GitParser): } }; -export const gitLinkedIssueParser = async ({ owner, repo, issue_number }: GitParser): Promise => { +export const gitLinkedIssueParser = async ({ owner, repo, issue_number: pull_number }: GitParser): Promise => { try { - const { data } = await axios.get(`https://github.com/${owner}/${repo}/pull/${issue_number}`); + const { data } = await axios.get(`https://github.com/${owner}/${repo}/pull/${pull_number}`); const dom = parse(data); const devForm = dom.querySelector("[data-target='create-branch.developmentForm']") as HTMLElement; - const linkedPRs = devForm.querySelectorAll(".my-1"); + const linkedIssues = devForm.querySelectorAll(".my-1"); - if (linkedPRs.length === 0) { + if (linkedIssues.length === 0) { return ""; } - const prUrl = linkedPRs[0].querySelector("a")?.attrs?.href || ""; - return prUrl; + const issueUrl = linkedIssues[0].querySelector("a")?.attrs?.href || ""; + return issueUrl; } catch (error) { return ""; } From efb941d8e933676384195f90024aea14c2e5ddd8 Mon Sep 17 00:00:00 2001 From: HARALD Date: Wed, 23 Aug 2023 18:31:28 +0900 Subject: [PATCH 08/88] feat: get comments as markdown --- src/helpers/issue.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/helpers/issue.ts b/src/helpers/issue.ts index 5127c1c6c..7e86f3fb1 100644 --- a/src/helpers/issue.ts +++ b/src/helpers/issue.ts @@ -506,13 +506,13 @@ export const closePullRequest = async (pull_number: number) => { } }; -export const getAllPullRequestReviews = async (context: Context, pull_number: number) => { +export const getAllPullRequestReviews = async (context: Context, pull_number: number, format: "raw" | "html" | "text" | "full" = "raw") => { const prArr = []; let fetchDone = false; const perPage = 30; let curPage = 1; while (!fetchDone) { - const prs = await getPullRequestReviews(context, pull_number, perPage, curPage); + const prs = await getPullRequestReviews(context, pull_number, perPage, curPage, format); // push the objects to array prArr.push(...prs); @@ -523,7 +523,13 @@ export const getAllPullRequestReviews = async (context: Context, pull_number: nu return prArr; }; -export const getPullRequestReviews = async (context: Context, pull_number: number, per_page: number, page: number) => { +export const getPullRequestReviews = async ( + context: Context, + pull_number: number, + per_page: number, + page: number, + format: "raw" | "html" | "text" | "full" = "raw" +) => { const logger = getLogger(); const payload = context.payload as Payload; try { @@ -533,6 +539,9 @@ export const getPullRequestReviews = async (context: Context, pull_number: numbe pull_number, per_page, page, + mediaType: { + format, + }, }); return reviews; } catch (e: unknown) { From 06d688a84d443012b9e180892d7ce8c0583bb1b0 Mon Sep 17 00:00:00 2001 From: HARALD Date: Thu, 24 Aug 2023 17:14:50 +0900 Subject: [PATCH 09/88] feat: revert changing function names --- src/handlers/payout/post.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index ac423fda7..89095d55e 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -21,7 +21,7 @@ const ItemsToExclude: string[] = ["blockquote"]; * Incentivize the contributors based on their contribution. * The default formula has been defined in https://github.com/ubiquity/ubiquibot/issues/272 */ -export async function incentivizeComments() { +export const incentivizeComments = async () => { const logger = getLogger(); const { mode: { incentiveMode, paymentPermitMaxPrice }, @@ -129,9 +129,9 @@ export async function incentivizeComments() { logger.info(`Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(fallbackReward)}`); await addCommentToIssue(comment, issue.number); -} +}; -export async function incentivizePullRequestReviews() { +export const incentivizePullRequestReviews = async () => { const logger = getLogger(); const { mode: { incentiveMode, paymentPermitMaxPrice }, @@ -261,7 +261,7 @@ export async function incentivizePullRequestReviews() { logger.info(`incentivizePullRequestReviews: Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(fallbackReward)}`); await addCommentToIssue(comment, issue.number); -} +}; export const incentivizeCreatorComment = async () => { const logger = getLogger(); From 07b2275e03f84fa649013f3dc39ae7d067c67ee8 Mon Sep 17 00:00:00 2001 From: HARALD Date: Thu, 24 Aug 2023 21:03:43 +0900 Subject: [PATCH 10/88] feat: minor fix --- src/handlers/payout/post.ts | 4 ++-- src/helpers/parser.ts | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index bcd502c32..348f12a47 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -215,14 +215,14 @@ export const incentivizePullRequestReviews = async () => { const user = review.user; if (!user) continue; if (user.type == UserType.Bot || user.login == assignee) continue; - if (!review.body) { + if (!review.body_html) { logger.info(`incentivizePullRequestReviews: Skipping to parse the comment because body_html is undefined. comment: ${JSON.stringify(review)}`); continue; } if (!prReviewsByUser[user.login]) { prReviewsByUser[user.login] = []; } - prReviewsByUser[user.login].push(review.body); + prReviewsByUser[user.login].push(review.body_html); } const tokenSymbol = await getTokenSymbol(paymentToken, rpc); logger.info(`incentivizePullRequestReviews: Filtering by the user type done. commentsByUser: ${JSON.stringify(prReviewsByUser)}`); diff --git a/src/helpers/parser.ts b/src/helpers/parser.ts index fed365efd..ceb08fbcf 100644 --- a/src/helpers/parser.ts +++ b/src/helpers/parser.ts @@ -4,7 +4,8 @@ import { HTMLElement, parse } from "node-html-parser"; interface GitParser { owner: string; repo: string; - issue_number: number; + issue_number?: number; + pull_number?: number; } export const gitIssueParser = async ({ owner, repo, issue_number }: GitParser): Promise => { @@ -25,7 +26,7 @@ export const gitIssueParser = async ({ owner, repo, issue_number }: GitParser): } }; -export const gitLinkedIssueParser = async ({ owner, repo, issue_number: pull_number }: GitParser): Promise => { +export const gitLinkedIssueParser = async ({ owner, repo, pull_number }: GitParser): Promise => { try { const { data } = await axios.get(`https://github.com/${owner}/${repo}/pull/${pull_number}`); const dom = parse(data); From 7104dd39b2e8da61e171b48513fee3b3d609f8b4 Mon Sep 17 00:00:00 2001 From: HARALD Date: Thu, 24 Aug 2023 21:29:44 +0900 Subject: [PATCH 11/88] feat: minor fix --- src/handlers/payout/post.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index 348f12a47..57e472893 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -178,7 +178,7 @@ export const incentivizePullRequestReviews = async () => { const pullRequestLinked = await gitLinkedIssueParser({ owner: payload.repository.owner.login, repo: payload.repository.name, - issue_number: pull.number, + pull_number: pull.number, }); const linkedIssueNumber = pullRequestLinked.substring(pullRequestLinked.lastIndexOf("/") + 1); if (linkedIssueNumber === issue.number.toString()) { @@ -208,7 +208,7 @@ export const incentivizePullRequestReviews = async () => { return; } - const prReviews = await getAllPullRequestReviews(context, linkedPull.number); + const prReviews = await getAllPullRequestReviews(context, linkedPull.number, "full"); logger.info(`Getting the PR reviews done. comments: ${JSON.stringify(prReviews)}`); const prReviewsByUser: Record = {}; for (const review of prReviews) { From 66d2d7b2d7a61eee271123a77afc1d6bff09e567 Mon Sep 17 00:00:00 2001 From: HARALD Date: Sat, 26 Aug 2023 00:27:02 +0900 Subject: [PATCH 12/88] feat: slight change --- src/handlers/payout/post.ts | 38 ++++++++++--------------------------- src/helpers/parser.ts | 13 +++++++++++++ 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index 95b17caea..ffeaee275 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -5,12 +5,11 @@ import { generatePermit2Signature, getAllIssueComments, getAllPullRequestReviews, - getAllPullRequests, getIssueDescription, getTokenSymbol, parseComments, } from "../../helpers"; -import { gitLinkedIssueParser } from "../../helpers/parser"; +import { gitLinkedPrParser } from "../../helpers/parser"; import { Incentives, MarkdownItem, Payload, StateReason, UserType } from "../../types"; import { commentParser } from "../comment"; import Decimal from "decimal.js"; @@ -140,7 +139,7 @@ export const incentivizePullRequestReviews = async () => { } = getBotConfig(); if (!incentiveMode) { logger.info(`No incentive mode. skipping to process`); - // return; + return; } const context = getBotContext(); const payload = context.payload as Payload; @@ -152,46 +151,29 @@ export const incentivizePullRequestReviews = async () => { if (issue.state_reason !== StateReason.COMPLETED) { logger.info("incentivizePullRequestReviews: comment incentives skipped because the issue was not closed as completed"); - // return; + return; } if (paymentPermitMaxPrice == 0 || !paymentPermitMaxPrice) { logger.info(`incentivizePullRequestReviews: skipping to generate permit2 url, reason: { paymentPermitMaxPrice: ${paymentPermitMaxPrice}}`); - // return; + return; } const issueDetailed = bountyInfo(issue); if (!issueDetailed.isBounty) { logger.info(`incentivizePullRequestReviews: its not a bounty`); - // return; - } - - const pulls = await getAllPullRequests(context, "closed"); - if (pulls.length === 0) { - logger.debug(`incentivizePullRequestReviews: No pull requests found at this time`); return; } - let linkedPull; + const pullRequestLinked = await gitLinkedPrParser({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: issue.number }); - for (const pull of pulls) { - const pullRequestLinked = await gitLinkedIssueParser({ - owner: payload.repository.owner.login, - repo: payload.repository.name, - pull_number: pull.number, - }); - const linkedIssueNumber = pullRequestLinked.substring(pullRequestLinked.lastIndexOf("/") + 1); - if (linkedIssueNumber === issue.number.toString()) { - linkedPull = pull; - break; - } - } - - if (!linkedPull) { + if (pullRequestLinked === "") { logger.debug(`incentivizePullRequestReviews: No linked pull requests found`); return; } + const linkedPullNumber = pullRequestLinked.substring(pullRequestLinked.lastIndexOf("/") + 1); + const comments = await getAllIssueComments(issue.number); const permitComments = comments.filter( (content) => content.body.includes("Reviewer Rewards") && content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot @@ -208,7 +190,7 @@ export const incentivizePullRequestReviews = async () => { return; } - const prReviews = await getAllPullRequestReviews(context, linkedPull.number, "full"); + const prReviews = await getAllPullRequestReviews(context, Number(linkedPullNumber), "full"); logger.info(`Getting the PR reviews done. comments: ${JSON.stringify(prReviews)}`); const prReviewsByUser: Record = {}; for (const review of prReviews) { @@ -243,7 +225,7 @@ export const incentivizePullRequestReviews = async () => { } logger.info(`incentivizePullRequestReviews: Comment parsed for the user: ${user}. comments: ${JSON.stringify(commentsByNode)}, sum: ${rewardValue}`); const account = await getWalletAddress(user); - const amountInETH = rewardValue.mul(baseMultiplier).div(1000); + const amountInETH = rewardValue.mul(baseMultiplier); if (amountInETH.gt(paymentPermitMaxPrice)) { logger.info(`incentivizePullRequestReviews: Skipping comment reward for user ${user} because reward is higher than payment permit max price`); continue; diff --git a/src/helpers/parser.ts b/src/helpers/parser.ts index ceb08fbcf..b7080f9a7 100644 --- a/src/helpers/parser.ts +++ b/src/helpers/parser.ts @@ -43,3 +43,16 @@ export const gitLinkedIssueParser = async ({ owner, repo, pull_number }: GitPars return ""; } }; + +export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser): Promise => { + try { + const { data } = await axios.get(`https://github.com/${owner}/${repo}/issues/${issue_number}`); + const dom = parse(data); + const devForm = dom.querySelector("[data-target='create-branch.developmentForm']") as HTMLElement; + const linkedPRs = devForm.querySelectorAll(".my-1"); + if (linkedPRs.length === 0) return ""; + return linkedPRs[linkedPRs.length - 1].querySelector("a")?.attrs?.href || ""; + } catch (error) { + return ""; + } +}; From 70ca321f6c646907c8537634dcc998a845d4f719 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sat, 26 Aug 2023 00:12:49 +0100 Subject: [PATCH 13/88] fix: stale bounty ready to start message in /start response --- src/bindings/config.ts | 1 + src/handlers/comment/handlers/assign.ts | 7 ++++++- src/handlers/comment/handlers/table.ts | 7 ++++--- src/types/config.ts | 1 + 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/bindings/config.ts b/src/bindings/config.ts index e7cdf8bea..f918f60e9 100644 --- a/src/bindings/config.ts +++ b/src/bindings/config.ts @@ -76,6 +76,7 @@ export const loadConfig = async (context: Context): Promise => { command: commandSettings, assign: { bountyHunterMax: bountyHunterMax, + staleBountyTime: ms(process.env.STALE_BOUNTY_TIME || "30d"), }, sodium: { privateKey: process.env.X25519_PRIVATE_KEY ?? "", diff --git a/src/handlers/comment/handlers/assign.ts b/src/handlers/comment/handlers/assign.ts index 82d73768f..f08501929 100644 --- a/src/handlers/comment/handlers/assign.ts +++ b/src/handlers/comment/handlers/assign.ts @@ -18,8 +18,11 @@ export const assign = async (body: string) => { const id = organization?.id || repository?.id; // repository?.id as fallback + const staleBounty = config.assign.staleBountyTime; + logger.info(`Received '/start' command from user: ${payload.sender.login}, body: ${body}`); const issue = (_payload as Payload).issue; + if (!issue) { logger.info(`Skipping '/start' because of no issue instance`); return "Skipping '/start' because of no issue instance"; @@ -109,6 +112,8 @@ export const assign = async (body: string) => { await addAssignees(issue.number, [payload.sender.login]); } + const isBountyStale = new Date().getTime() - new Date(issue.created_at).getTime() > staleBounty; + // double check whether the assign message has been already posted or not logger.info(`Creating an issue comment: ${comment.commit}`); const issueComments = await getAllIssueComments(issue.number); @@ -116,7 +121,7 @@ export const assign = async (body: string) => { const latestComment = comments.length > 0 ? comments[0].body : undefined; if (latestComment && comment.commit != latestComment) { const { multiplier, reason, bounty } = await getMultiplierInfoToDisplay(payload.sender.login, id?.toString(), issue); - return tableComment({ ...comment, multiplier, reason, bounty }) + comment.tips; + return tableComment({ ...comment, multiplier, reason, bounty, isBountyStale }) + comment.tips; } return; }; diff --git a/src/handlers/comment/handlers/table.ts b/src/handlers/comment/handlers/table.ts index 13bed9e88..c8d025d80 100644 --- a/src/handlers/comment/handlers/table.ts +++ b/src/handlers/comment/handlers/table.ts @@ -4,20 +4,21 @@ export const tableComment = ({ multiplier, reason, bounty, + isBountyStale, }: { deadline: string; wallet: string; multiplier?: string; reason?: string; bounty?: string; + isBountyStale?: boolean; }) => { return ` - - - + + ${!isBountyStale ? `` : ``} diff --git a/src/types/config.ts b/src/types/config.ts index 97d844ab6..373262377 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -69,6 +69,7 @@ export const ModeSchema = Type.Object({ export const AssignSchema = Type.Object({ bountyHunterMax: Type.Number(), + staleBountyTime: Type.Number(), }); export const LogConfigSchema = Type.Object({ From 517a3e526d63609faab70b96bb39d78a148b192f Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sat, 26 Aug 2023 23:09:39 +0100 Subject: [PATCH 14/88] fix: requested changes made fix config and warning --- src/bindings/config.ts | 4 ++-- src/configs/shared.ts | 1 + src/handlers/comment/handlers/assign.ts | 4 +++- src/handlers/comment/handlers/table.ts | 4 +++- src/utils/private.ts | 1 + ubiquibot-config-default.json | 21 +++++++++++++-------- 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/bindings/config.ts b/src/bindings/config.ts index f918f60e9..83718e1a1 100644 --- a/src/bindings/config.ts +++ b/src/bindings/config.ts @@ -1,7 +1,7 @@ import ms from "ms"; import { BotConfig, BotConfigSchema } from "../types"; -import { DEFAULT_BOT_DELAY, DEFAULT_DISQUALIFY_TIME, DEFAULT_FOLLOWUP_TIME, DEFAULT_PERMIT_BASE_URL } from "../configs"; +import { DEFAULT_BOT_DELAY, DEFAULT_DISQUALIFY_TIME, DEFAULT_FOLLOWUP_TIME, DEFAULT_PERMIT_BASE_URL, STALE_BOUNTY_TIME } from "../configs"; import { getPayoutConfigByNetworkId } from "../helpers"; import { ajv } from "../utils"; import { Context } from "probot"; @@ -76,7 +76,7 @@ export const loadConfig = async (context: Context): Promise => { command: commandSettings, assign: { bountyHunterMax: bountyHunterMax, - staleBountyTime: ms(process.env.STALE_BOUNTY_TIME || "30d"), + staleBountyTime: ms(STALE_BOUNTY_TIME), }, sodium: { privateKey: process.env.X25519_PRIVATE_KEY ?? "", diff --git a/src/configs/shared.ts b/src/configs/shared.ts index 2d817b7a0..25af7325c 100644 --- a/src/configs/shared.ts +++ b/src/configs/shared.ts @@ -22,6 +22,7 @@ export const ASSIGN_COMMAND_ENABLED = true; */ export const DEFAULT_FOLLOWUP_TIME = "4 days"; // 4 days export const DEFAULT_DISQUALIFY_TIME = "7 days"; // 7 days +export const STALE_BOUNTY_TIME = "30d"; // 2 minutes export const DEFAULT_NETWORK_ID = 1; // ethereum export const DEFAULT_RPC_ENDPOINT = "https://rpc-bot.ubq.fi/v1/mainnet"; diff --git a/src/handlers/comment/handlers/assign.ts b/src/handlers/comment/handlers/assign.ts index f08501929..04f295010 100644 --- a/src/handlers/comment/handlers/assign.ts +++ b/src/handlers/comment/handlers/assign.ts @@ -7,6 +7,7 @@ import { tableComment } from "./table"; import { bountyInfo } from "../../wildcard"; import { ASSIGN_COMMAND_ENABLED, GLOBAL_STRINGS } from "../../../configs"; import { isParentIssue } from "../../pricing"; +import ms from "ms"; export const assign = async (body: string) => { const { payload: _payload } = getBotContext(); @@ -113,6 +114,7 @@ export const assign = async (body: string) => { } const isBountyStale = new Date().getTime() - new Date(issue.created_at).getTime() > staleBounty; + const days = Math.floor((new Date().getTime() - new Date(issue.created_at).getTime()) / (1000 * 60 * 60 * 24)); // double check whether the assign message has been already posted or not logger.info(`Creating an issue comment: ${comment.commit}`); @@ -121,7 +123,7 @@ export const assign = async (body: string) => { const latestComment = comments.length > 0 ? comments[0].body : undefined; if (latestComment && comment.commit != latestComment) { const { multiplier, reason, bounty } = await getMultiplierInfoToDisplay(payload.sender.login, id?.toString(), issue); - return tableComment({ ...comment, multiplier, reason, bounty, isBountyStale }) + comment.tips; + return tableComment({ ...comment, multiplier, reason, bounty, isBountyStale, days }) + comment.tips; } return; }; diff --git a/src/handlers/comment/handlers/table.ts b/src/handlers/comment/handlers/table.ts index c8d025d80..a84517589 100644 --- a/src/handlers/comment/handlers/table.ts +++ b/src/handlers/comment/handlers/table.ts @@ -5,6 +5,7 @@ export const tableComment = ({ reason, bounty, isBountyStale, + days, }: { deadline: string; wallet: string; @@ -12,13 +13,14 @@ export const tableComment = ({ reason?: string; bounty?: string; isBountyStale?: boolean; + days?: number; }) => { return `
Ready to begin?You can start right away!Please wait for confirmation first.
Deadline
- ${!isBountyStale ? `` : ``} + ${!isBountyStale ? `` : ``} diff --git a/src/utils/private.ts b/src/utils/private.ts index 1b6147b0a..2e01d61a9 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -21,6 +21,7 @@ import { } from "./helpers"; import DEFAULT_CONFIG_JSON from "../../ubiquibot-config-default.json"; +import ms from "ms"; const CONFIG_REPO = "ubiquibot-config"; const CONFIG_PATH = ".github/ubiquibot-config.yml"; diff --git a/ubiquibot-config-default.json b/ubiquibot-config-default.json index b859c45f0..98c119890 100644 --- a/ubiquibot-config-default.json +++ b/ubiquibot-config-default.json @@ -62,35 +62,40 @@ "command-settings": [ { "name": "start", - "enabled": false + "enabled": true }, { "name": "stop", - "enabled": false + "enabled": true }, { "name": "wallet", - "enabled": false + "enabled": true }, { "name": "payout", - "enabled": false + "enabled": true }, { "name": "multiplier", - "enabled": false + "enabled": true }, { "name": "query", - "enabled": false + "enabled": true }, { "name": "allow", - "enabled": false + "enabled": true }, { "name": "autopay", - "enabled": false + "enabled": true + }, + { + "name": "assign", + "enabled": true, + "staleBountyTime": 120000 } ], "incentives": { From 5a38700325b6fc3a76bc9a5a8c5ae34369b9b053 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sat, 26 Aug 2023 23:32:32 +0100 Subject: [PATCH 15/88] fix: pulls from default uses default json first unless 0 then uses 30d --- src/bindings/config.ts | 3 ++- src/configs/shared.ts | 2 +- src/handlers/comment/handlers/assign.ts | 3 ++- src/utils/private.ts | 3 +++ ubiquibot-config-default.json | 6 +----- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/bindings/config.ts b/src/bindings/config.ts index 83718e1a1..66cf7e64e 100644 --- a/src/bindings/config.ts +++ b/src/bindings/config.ts @@ -26,6 +26,7 @@ export const loadConfig = async (context: Context): Promise => { commandSettings, assistivePricing, registerWalletWithVerification, + staleBountyTime, } = await getWideConfig(context); const publicKey = await getScalarKey(process.env.X25519_PRIVATE_KEY); @@ -76,7 +77,7 @@ export const loadConfig = async (context: Context): Promise => { command: commandSettings, assign: { bountyHunterMax: bountyHunterMax, - staleBountyTime: ms(STALE_BOUNTY_TIME), + staleBountyTime: staleBountyTime ? staleBountyTime : ms(STALE_BOUNTY_TIME), }, sodium: { privateKey: process.env.X25519_PRIVATE_KEY ?? "", diff --git a/src/configs/shared.ts b/src/configs/shared.ts index 25af7325c..b90b587ff 100644 --- a/src/configs/shared.ts +++ b/src/configs/shared.ts @@ -22,7 +22,7 @@ export const ASSIGN_COMMAND_ENABLED = true; */ export const DEFAULT_FOLLOWUP_TIME = "4 days"; // 4 days export const DEFAULT_DISQUALIFY_TIME = "7 days"; // 7 days -export const STALE_BOUNTY_TIME = "30d"; // 2 minutes +export const STALE_BOUNTY_TIME = "30d"; // 30 days export const DEFAULT_NETWORK_ID = 1; // ethereum export const DEFAULT_RPC_ENDPOINT = "https://rpc-bot.ubq.fi/v1/mainnet"; diff --git a/src/handlers/comment/handlers/assign.ts b/src/handlers/comment/handlers/assign.ts index 04f295010..20be74f7d 100644 --- a/src/handlers/comment/handlers/assign.ts +++ b/src/handlers/comment/handlers/assign.ts @@ -7,7 +7,6 @@ import { tableComment } from "./table"; import { bountyInfo } from "../../wildcard"; import { ASSIGN_COMMAND_ENABLED, GLOBAL_STRINGS } from "../../../configs"; import { isParentIssue } from "../../pricing"; -import ms from "ms"; export const assign = async (body: string) => { const { payload: _payload } = getBotContext(); @@ -21,6 +20,8 @@ export const assign = async (body: string) => { const staleBounty = config.assign.staleBountyTime; + console.log("staleBounty", staleBounty); + logger.info(`Received '/start' command from user: ${payload.sender.login}, body: ${body}`); const issue = (_payload as Payload).issue; diff --git a/src/utils/private.ts b/src/utils/private.ts index 2e01d61a9..d10ac378e 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -21,6 +21,7 @@ import { } from "./helpers"; import DEFAULT_CONFIG_JSON from "../../ubiquibot-config-default.json"; +import { STALE_BOUNTY_TIME } from "../configs"; import ms from "ms"; const CONFIG_REPO = "ubiquibot-config"; @@ -83,6 +84,7 @@ export interface WideConfig { "comment-incentives"?: boolean; "assistive-pricing"?: boolean; "max-concurrent-assigns"?: number; + "stale-bounty-time"?: string; incentives?: Incentives; "default-labels"?: string[]; "register-wallet-with-verification"?: boolean; @@ -185,6 +187,7 @@ export const getWideConfig = async (context: Context) => { defaultLabels: getDefaultLabels(configs), promotionComment: getPromotionComment(configs), registerWalletWithVerification: getRegisterWalletWithVerification(configs), + staleBountyTime: parsedDefault["stale-bounty-time"] == "0" ? ms(STALE_BOUNTY_TIME) : parsedDefault["stale-bounty-time"], }; return configData; diff --git a/ubiquibot-config-default.json b/ubiquibot-config-default.json index 98c119890..5271a5d7f 100644 --- a/ubiquibot-config-default.json +++ b/ubiquibot-config-default.json @@ -8,6 +8,7 @@ "disable-analytics": false, "comment-incentives": false, "register-wallet-with-verification": false, + "stale-bounty-time": 42060, "promotion-comment": "\n
If you enjoy the DevPool experience, please follow Ubiquity on GitHub and star this repo to show your support. It helps a lot!
", "default-labels": [], "time-labels": [ @@ -91,11 +92,6 @@ { "name": "autopay", "enabled": true - }, - { - "name": "assign", - "enabled": true, - "staleBountyTime": 120000 } ], "incentives": { From 5a41966d6ca92f9f7b0f8226098d0c904d80188a Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sat, 26 Aug 2023 23:36:51 +0100 Subject: [PATCH 16/88] fix: remove console log remove console log and adjust warning --- src/handlers/comment/handlers/assign.ts | 2 -- src/handlers/comment/handlers/table.ts | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/handlers/comment/handlers/assign.ts b/src/handlers/comment/handlers/assign.ts index 20be74f7d..cbb7df465 100644 --- a/src/handlers/comment/handlers/assign.ts +++ b/src/handlers/comment/handlers/assign.ts @@ -20,8 +20,6 @@ export const assign = async (body: string) => { const staleBounty = config.assign.staleBountyTime; - console.log("staleBounty", staleBounty); - logger.info(`Received '/start' command from user: ${payload.sender.login}, body: ${body}`); const issue = (_payload as Payload).issue; diff --git a/src/handlers/comment/handlers/table.ts b/src/handlers/comment/handlers/table.ts index a84517589..bc2349cdf 100644 --- a/src/handlers/comment/handlers/table.ts +++ b/src/handlers/comment/handlers/table.ts @@ -20,7 +20,11 @@ export const tableComment = ({
Ready to begin?You can start right away!Please wait for confirmation first.You can start right away!This task was created over ${days} days ago. Please verify that it is still current.
Deadline
- ${!isBountyStale ? `` : ``} + ${ + !isBountyStale + ? `` + : `` + } From dda1cbb15efffba1b46cc12e4d89d299226d485e Mon Sep 17 00:00:00 2001 From: whilefoo Date: Sun, 27 Aug 2023 16:09:37 +0200 Subject: [PATCH 17/88] fix: getBotConfig instead of loadConfig --- src/helpers/issue.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/helpers/issue.ts b/src/helpers/issue.ts index 00ccd0e93..abaa9e73a 100644 --- a/src/helpers/issue.ts +++ b/src/helpers/issue.ts @@ -1,5 +1,5 @@ import { Context } from "probot"; -import { getBotContext, getLogger, loadConfig } from "../bindings"; +import { getBotConfig, getBotContext, getLogger } from "../bindings"; import { AssignEvent, Comment, IssueType, Payload } from "../types"; import { checkRateLimitGit } from "../utils"; @@ -641,8 +641,10 @@ export const getCommitsOnPullRequest = async (pullNumber: number) => { export const getAvailableOpenedPullRequests = async (username: string) => { const context = getBotContext(); - const botConfig = await loadConfig(context); - if (!botConfig.unassign.timeRangeForMaxIssueEnabled) return []; + const { + unassign: { timeRangeForMaxIssue, timeRangeForMaxIssueEnabled }, + } = await getBotConfig(); + if (!timeRangeForMaxIssueEnabled) return []; const opened_prs = await getOpenedPullRequests(username); @@ -657,7 +659,7 @@ export const getAvailableOpenedPullRequests = async (username: string) => { if (approvedReviews) result.push(pr); } - if (reviews.length === 0 && (new Date().getTime() - new Date(pr.created_at).getTime()) / (1000 * 60 * 60) >= botConfig.unassign.timeRangeForMaxIssue) { + if (reviews.length === 0 && (new Date().getTime() - new Date(pr.created_at).getTime()) / (1000 * 60 * 60) >= timeRangeForMaxIssue) { result.push(pr); } } From bdb691768bc2c5a78c7ea145c70f4d37c6d95e0c Mon Sep 17 00:00:00 2001 From: whilefoo Date: Sun, 27 Aug 2023 16:13:56 +0200 Subject: [PATCH 18/88] feat: log config errors --- src/bindings/event.ts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/bindings/event.ts b/src/bindings/event.ts index 3ea42f287..3422cb526 100644 --- a/src/bindings/event.ts +++ b/src/bindings/event.ts @@ -34,7 +34,12 @@ export const bindEvents = async (context: Context): Promise => { botContext = context; const payload = context.payload as Payload; - botConfig = await loadConfig(context); + let botConfigError; + try { + botConfig = await loadConfig(context); + } catch (err) { + botConfigError = err; + } adapters = createAdapters(botConfig); @@ -48,6 +53,19 @@ export const bindEvents = async (context: Context): Promise => { return; } + if (botConfigError) { + logger.error( + `Error loading config: ${botConfigError}. Config: ${JSON.stringify({ + price: botConfig.price, + unassign: botConfig.unassign, + mode: botConfig.mode, + log: botConfig.log, + wallet: botConfig.wallet, + })}` + ); + return; + } + // Create adapters for telegram, supabase, twitter, discord, etc logger.info("Creating adapters for supabase, telegram, twitter, etc..."); From 01fb81791edbb8dc23e450487b99b8376f2a7c28 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Mon, 28 Aug 2023 08:22:25 +0200 Subject: [PATCH 19/88] feat: validate config on push event --- package.json | 2 +- src/handlers/processors.ts | 4 +- src/handlers/push/index.ts | 52 ++++++++++++++++++++++ src/helpers/file.ts | 52 ++++++++++++++++++++++ src/utils/private.ts | 89 +++++++++++++++++++++----------------- yarn.lock | 31 +++++++------ 6 files changed, 174 insertions(+), 56 deletions(-) diff --git a/package.json b/package.json index e64d64e99..a839a4e3b 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@netlify/functions": "^1.4.0", "@probot/adapter-aws-lambda-serverless": "^3.0.2", "@probot/adapter-github-actions": "^3.1.3", - "@sinclair/typebox": "^0.25.9", + "@sinclair/typebox": "^0.31.5", "@supabase/supabase-js": "^2.4.0", "@types/ms": "^0.7.31", "@typescript-eslint/eslint-plugin": "^5.59.11", diff --git a/src/handlers/processors.ts b/src/handlers/processors.ts index 16f89a535..745d45e45 100644 --- a/src/handlers/processors.ts +++ b/src/handlers/processors.ts @@ -6,7 +6,7 @@ import { nullHandler } from "./shared"; import { handleComment, issueClosedCallback, issueReopenedCallback } from "./comment"; import { checkPullRequests } from "./assign/auto"; import { createDevPoolPR } from "./pull-request"; -import { runOnPush } from "./push"; +import { runOnPush, validateConfigChange } from "./push"; import { incentivizeComments, incentivizeCreatorComment } from "./payout"; import { findDuplicateOne } from "./issue"; @@ -68,7 +68,7 @@ export const processors: Record = { }, [GithubEvent.PUSH_EVENT]: { pre: [nullHandler], - action: [runOnPush], + action: [validateConfigChange, runOnPush], post: [nullHandler], }, }; diff --git a/src/handlers/push/index.ts b/src/handlers/push/index.ts index 4cd4775ae..6fb269859 100644 --- a/src/handlers/push/index.ts +++ b/src/handlers/push/index.ts @@ -1,6 +1,10 @@ import { getBotContext, getLogger } from "../../bindings"; +import { getFileContent } from "../../helpers"; import { CommitsPayload, PushPayload } from "../../types"; +import { ajv } from "../../utils"; +import { parseYAML } from "../../utils/private"; import { updateBaseRate } from "./update-base"; +import { WideOrgConfigSchema } from "../../utils/private"; const ZERO_SHA = "0000000000000000000000000000000000000000"; const BASE_RATE_FILE = ".github/ubiquibot-config.yml"; @@ -45,3 +49,51 @@ export const runOnPush = async () => { await updateBaseRate(context, payload, BASE_RATE_FILE); } }; + +export const validateConfigChange = async () => { + const logger = getLogger(); + + const context = getBotContext(); + const payload = context.payload as PushPayload; + + if (!payload.ref.startsWith("refs/heads/")) { + logger.debug("Skipping push events, not a branch"); + return; + } + + const changes = getCommitChanges(payload.commits); + + // skip if empty + if (changes && changes.length === 0) { + logger.debug("Skipping push events, file change empty"); + return; + } + + // check for modified or added files and check for specified file + if (changes.includes(BASE_RATE_FILE)) { + const latestCommitSha = payload.after; + const configFileContent = await getFileContent( + payload.repository.owner.login, + payload.repository.name, + payload.ref.split("refs/heads/")[1], + BASE_RATE_FILE, + latestCommitSha + ); + if (configFileContent) { + const decodedConfig = Buffer.from(configFileContent, "base64").toString(); + const config = parseYAML(decodedConfig); + const valid = ajv.validate(WideOrgConfigSchema, config); // additionalProperties: false is required to prevent unknown properties from being allowed + if (!valid) { + // post commit comment + const commitSha = payload.commits.filter((commit) => commit.modified.includes(BASE_RATE_FILE) || commit.added.includes(BASE_RATE_FILE))[0]?.id; + await context.octokit.rest.repos.createCommitComment({ + owner: payload.repository.owner.login, + repo: payload.repository.name, + commit_sha: commitSha, + body: `@${payload.sender.login} Config validation failed! Error: ${ajv.errorsText()}`, + path: BASE_RATE_FILE, + }); + } + } + } +}; diff --git a/src/helpers/file.ts b/src/helpers/file.ts index f32a64e31..b21905098 100644 --- a/src/helpers/file.ts +++ b/src/helpers/file.ts @@ -59,3 +59,55 @@ export async function getPreviousFileContent(owner: string, repo: string, branch return ""; } } + +export async function getFileContent(owner: string, repo: string, branch: string, filePath: string, commitSha?: string): Promise { + const logger = getLogger(); + const context = getBotContext(); + + try { + if (!commitSha) { + // Get the latest commit of the branch + const branchData = await context.octokit.repos.getBranch({ + owner, + repo, + branch, + }); + commitSha = branchData.data.commit.sha; + } + + // Get the commit details + const commitData = await context.octokit.repos.getCommit({ + owner, + repo, + ref: commitSha, + }); + + // Find the file in the commit tree + const file = commitData.data.files ? commitData.data.files.find((file) => file.filename === filePath) : undefined; + if (file) { + // Retrieve the file tree + const tree = await context.octokit.git.getTree({ + owner, + repo, + tree_sha: commitData.data.commit.tree.sha, + recursive: "true", + }); + + // Find the previous file content in the tree + const file = tree.data.tree.find((item) => item.path === filePath); + if (file && file.sha) { + // Get the previous file content + const fileContent = await context.octokit.git.getBlob({ + owner, + repo, + file_sha: file.sha, + }); + return fileContent.data.content; + } + } + return null; + } catch (error: unknown) { + logger.debug(`Error retrieving previous file content. error: ${error}`); + return null; + } +} diff --git a/src/utils/private.ts b/src/utils/private.ts index 36ff92f8c..2ef5e0073 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -21,6 +21,7 @@ import { } from "./helpers"; import DEFAULT_CONFIG_JSON from "../../ubiquibot-config-default.json"; +import { Static, Type } from "@sinclair/typebox"; const CONFIG_REPO = "ubiquibot-config"; const CONFIG_PATH = ".github/ubiquibot-config.yml"; @@ -47,49 +48,57 @@ export const getConfigSuperset = async (context: Context, type: "org" | "repo", } }; -export interface WideLabel { - name: string; -} - -export interface CommentIncentives { - elements: Record; - totals: { - word: number; - }; -} - -export interface Incentives { - comment: CommentIncentives; -} - -export interface CommandObj { - name: string; - enabled: boolean; -} - -export interface WideConfig { - "evm-network-id"?: number; - "price-multiplier"?: number; - "issue-creator-multiplier": number; - "time-labels"?: WideLabel[]; - "priority-labels"?: WideLabel[]; - "payment-permit-max-price"?: number; - "command-settings"?: CommandObj[]; - "promotion-comment"?: string; - "disable-analytics"?: boolean; - "comment-incentives"?: boolean; - "assistive-pricing"?: boolean; - "max-concurrent-assigns"?: number; - incentives?: Incentives; - "default-labels"?: string[]; - "register-wallet-with-verification"?: boolean; -} +const WideLabelSchema = Type.Object({ + name: Type.String(), +}); + +export type WideLabel = Static; + +const CommandObjSchema = Type.Object({ + name: Type.String(), + enabled: Type.Boolean(), +}); + +export type CommandObj = Static; + +const IncentivesSchema = Type.Object({ + comment: Type.Object({ + elements: Type.Record(Type.String(), Type.Number()), + totals: Type.Object({ + word: Type.Number(), + }), + }), +}); + +export type Incentives = Static; + +export const WideConfigSchema = Type.Object({ + "evm-network-id": Type.Optional(Type.Number()), + "price-multiplier": Type.Optional(Type.Number()), + "issue-creator-multiplier": Type.Number(), + "time-labels": Type.Optional(Type.Array(WideLabelSchema)), + "priority-labels": Type.Optional(Type.Array(WideLabelSchema)), + "payment-permit-max-price": Type.Optional(Type.Number()), + "command-settings": Type.Optional(Type.Array(CommandObjSchema)), + "promotion-comment": Type.Optional(Type.String()), + "disable-analytics": Type.Optional(Type.Boolean()), + "comment-incentives": Type.Optional(Type.Boolean()), + "assistive-pricing": Type.Optional(Type.Boolean()), + "max-concurrent-assigns": Type.Optional(Type.Number()), + incentives: Type.Optional(IncentivesSchema), + "default-labels": Type.Optional(Type.Array(Type.String())), + "register-wallet-with-verification": Type.Optional(Type.Boolean()), +}); + +export type WideConfig = Static; export type WideRepoConfig = WideConfig; -export interface WideOrgConfig extends WideConfig { - "private-key-encrypted"?: string; -} +export const WideOrgConfigSchema = Type.Composite([Type.Object({ "private-key-encrypted": Type.Optional(Type.String()) }), WideConfigSchema], { + additionalProperties: false, +}); + +export type WideOrgConfig = Static; export const parseYAML = (data?: string): WideConfig | undefined => { try { diff --git a/yarn.lock b/yarn.lock index 2d930cf18..60ee62730 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1928,10 +1928,10 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== -"@sinclair/typebox@^0.25.9": - version "0.25.24" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718" - integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ== +"@sinclair/typebox@^0.31.5": + version "0.31.5" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.31.5.tgz#10ae6c60fc523d7d695a730df1ac3dd9725ce207" + integrity sha512-4fbqH1ONle98ULTQakJFVNwGwSx+rv90HEnjZGt1GoApMKooUw1WXw3ub+Ew7rInmyDcwsjIxiHt39bkWzeCBA== "@sinonjs/commons@^1.7.0": version "1.8.6" @@ -1968,10 +1968,10 @@ dependencies: cross-fetch "^3.1.5" -"@supabase/realtime-js@^2.7.3": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.7.3.tgz#cbcb84181add681ab99c87032bfe88101c6863b3" - integrity sha512-c7TzL81sx2kqyxsxcDduJcHL9KJdCOoKimGP6lQSqiZKX42ATlBZpWbyy9KFGFBjAP4nyopMf5JhPi2ZH9jyNw== +"@supabase/realtime-js@^2.7.4": + version "2.7.4" + resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.7.4.tgz#de41195bd3f2cdd6db82d9f93c4c5b8fae9f809b" + integrity sha512-FzSzs1k9ruh/uds5AJ95Nc3beiMCCIhougExJ3O98CX1LMLAKUKFy5FivKLvcNhXnNfUEL0XUfGMb4UH2J7alg== dependencies: "@types/phoenix" "^1.5.4" "@types/websocket" "^1.0.3" @@ -1984,15 +1984,15 @@ dependencies: cross-fetch "^3.1.5" -"@supabase/supabase-js@^2.32.0": - version "2.32.0" - resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.32.0.tgz#863c636d83232c6a2e9ba5932e0d7c1bf80bc436" - integrity sha512-1ShFhuOI5Du7604nlCelBsRD61daXk2O0qwjumoz35bqrYThnSPPtpJqZOHw6Mg6o7mLjIInYLh/DBlh8UvzRg== +"@supabase/supabase-js@^2.4.0": + version "2.33.1" + resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.33.1.tgz#2407861afe63c2817d030514c87a745f78dfe68a" + integrity sha512-jA00rquPTppPOHpBB6KABW98lfg0gYXcuGqP3TB1iiduznRVsi3GGk2qBKXPDLMYSe0kRlQp5xCwWWthaJr8eA== dependencies: "@supabase/functions-js" "^2.1.0" "@supabase/gotrue-js" "^2.46.1" "@supabase/postgrest-js" "^1.8.0" - "@supabase/realtime-js" "^2.7.3" + "@supabase/realtime-js" "^2.7.4" "@supabase/storage-js" "^2.5.1" cross-fetch "^3.1.5" @@ -4189,6 +4189,11 @@ expect@^28.0.0: jest-message-util "^28.1.3" jest-util "^28.1.3" +exponential-backoff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" + integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== + express-handlebars@^6.0.3: version "6.0.7" resolved "https://registry.yarnpkg.com/express-handlebars/-/express-handlebars-6.0.7.tgz#f779254664eff0e250362ef1c2b30587059c212a" From 7be47680ff5044e166596bfb471babe5e5bad9cd Mon Sep 17 00:00:00 2001 From: whilefoo Date: Mon, 28 Aug 2023 10:07:04 +0200 Subject: [PATCH 20/88] feat: find correct commit hash --- src/handlers/push/index.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/handlers/push/index.ts b/src/handlers/push/index.ts index 6fb269859..63c6d5516 100644 --- a/src/handlers/push/index.ts +++ b/src/handlers/push/index.ts @@ -71,21 +71,22 @@ export const validateConfigChange = async () => { // check for modified or added files and check for specified file if (changes.includes(BASE_RATE_FILE)) { - const latestCommitSha = payload.after; + const commitSha = payload.commits.filter((commit) => commit.modified.includes(BASE_RATE_FILE) || commit.added.includes(BASE_RATE_FILE)).reverse()[0]?.id; + const configFileContent = await getFileContent( payload.repository.owner.login, payload.repository.name, payload.ref.split("refs/heads/")[1], BASE_RATE_FILE, - latestCommitSha + commitSha ); + if (configFileContent) { const decodedConfig = Buffer.from(configFileContent, "base64").toString(); const config = parseYAML(decodedConfig); const valid = ajv.validate(WideOrgConfigSchema, config); // additionalProperties: false is required to prevent unknown properties from being allowed if (!valid) { // post commit comment - const commitSha = payload.commits.filter((commit) => commit.modified.includes(BASE_RATE_FILE) || commit.added.includes(BASE_RATE_FILE))[0]?.id; await context.octokit.rest.repos.createCommitComment({ owner: payload.repository.owner.login, repo: payload.repository.name, From a6cf47efee00caa7ce82907f29796f68dab16653 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Mon, 28 Aug 2023 10:54:10 +0200 Subject: [PATCH 21/88] feat: log invalid config --- src/adapters/index.ts | 4 ++-- src/bindings/event.ts | 19 ++++++++---------- src/utils/private.ts | 46 +++++++++++++++++++++++++++---------------- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/adapters/index.ts b/src/adapters/index.ts index c5d85b7eb..5279a354a 100644 --- a/src/adapters/index.ts +++ b/src/adapters/index.ts @@ -6,7 +6,7 @@ export * from "./telegram"; export const createAdapters = (config: BotConfig): Adapters => { return { - supabase: supabase(config.supabase.url, config.supabase.key), - telegram: new Telegraf(config.telegram.token).telegram, + supabase: supabase(config?.supabase?.url ?? process.env.SUPABASE_URL, config?.supabase?.key ?? process.env.SUPABASE_KEY), + telegram: new Telegraf(config?.telegram?.token ?? process.env.TELEGRAM_BOT_TOKEN).telegram, }; }; diff --git a/src/bindings/event.ts b/src/bindings/event.ts index 3422cb526..616580a1a 100644 --- a/src/bindings/event.ts +++ b/src/bindings/event.ts @@ -6,7 +6,7 @@ import { BotConfig, GithubEvent, Payload, PayloadSchema } from "../types"; import { Adapters } from "../types/adapters"; import { ajv } from "../utils"; import { loadConfig } from "./config"; -import { GitHubLogger } from "../adapters/supabase"; +import { GitHubLogger, Level } from "../adapters/supabase"; let botContext: Context = {} as Context; export const getBotContext = () => botContext; @@ -48,21 +48,18 @@ export const bindEvents = async (context: Context): Promise => { // level: botConfig.log.level, }; - logger = new GitHubLogger(options.app, botConfig.log.logEnvironment, botConfig.log.level, botConfig.log.retryLimit); // contributors will see logs in console while on development env + logger = new GitHubLogger( + options.app, + botConfig?.log?.logEnvironment ?? "development", + botConfig?.log?.level ?? Level.DEBUG, + botConfig?.log?.retryLimit ?? 0 + ); // contributors will see logs in console while on development env if (!logger) { return; } if (botConfigError) { - logger.error( - `Error loading config: ${botConfigError}. Config: ${JSON.stringify({ - price: botConfig.price, - unassign: botConfig.unassign, - mode: botConfig.mode, - log: botConfig.log, - wallet: botConfig.wallet, - })}` - ); + logger.error(botConfigError); return; } diff --git a/src/utils/private.ts b/src/utils/private.ts index 2ef5e0073..ca4175058 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -22,6 +22,7 @@ import { import DEFAULT_CONFIG_JSON from "../../ubiquibot-config-default.json"; import { Static, Type } from "@sinclair/typebox"; +import { ajv } from "./ajv"; const CONFIG_REPO = "ubiquibot-config"; const CONFIG_PATH = ".github/ubiquibot-config.yml"; @@ -72,23 +73,28 @@ const IncentivesSchema = Type.Object({ export type Incentives = Static; -export const WideConfigSchema = Type.Object({ - "evm-network-id": Type.Optional(Type.Number()), - "price-multiplier": Type.Optional(Type.Number()), - "issue-creator-multiplier": Type.Number(), - "time-labels": Type.Optional(Type.Array(WideLabelSchema)), - "priority-labels": Type.Optional(Type.Array(WideLabelSchema)), - "payment-permit-max-price": Type.Optional(Type.Number()), - "command-settings": Type.Optional(Type.Array(CommandObjSchema)), - "promotion-comment": Type.Optional(Type.String()), - "disable-analytics": Type.Optional(Type.Boolean()), - "comment-incentives": Type.Optional(Type.Boolean()), - "assistive-pricing": Type.Optional(Type.Boolean()), - "max-concurrent-assigns": Type.Optional(Type.Number()), - incentives: Type.Optional(IncentivesSchema), - "default-labels": Type.Optional(Type.Array(Type.String())), - "register-wallet-with-verification": Type.Optional(Type.Boolean()), -}); +export const WideConfigSchema = Type.Object( + { + "evm-network-id": Type.Optional(Type.Number()), + "price-multiplier": Type.Optional(Type.Number()), + "issue-creator-multiplier": Type.Number(), + "time-labels": Type.Optional(Type.Array(WideLabelSchema)), + "priority-labels": Type.Optional(Type.Array(WideLabelSchema)), + "payment-permit-max-price": Type.Optional(Type.Number()), + "command-settings": Type.Optional(Type.Array(CommandObjSchema)), + "promotion-comment": Type.Optional(Type.String()), + "disable-analytics": Type.Optional(Type.Boolean()), + "comment-incentives": Type.Optional(Type.Boolean()), + "assistive-pricing": Type.Optional(Type.Boolean()), + "max-concurrent-assigns": Type.Optional(Type.Number()), + incentives: Type.Optional(IncentivesSchema), + "default-labels": Type.Optional(Type.Array(Type.String())), + "register-wallet-with-verification": Type.Optional(Type.Boolean()), + }, + { + additionalProperties: false, + } +); export type WideConfig = Static; @@ -169,7 +175,13 @@ export const getWideConfig = async (context: Context) => { const repoConfig = await getConfigSuperset(context, "repo", CONFIG_PATH); const parsedOrg: WideOrgConfig | undefined = parseYAML(orgConfig); + if (parsedOrg !== undefined && !ajv.validate(WideOrgConfigSchema, parsedOrg)) { + throw new Error(`Invalid org config: ${ajv.errorsText()}`); + } const parsedRepo: WideRepoConfig | undefined = parseYAML(repoConfig); + if (parsedRepo !== undefined && !ajv.validate(WideConfigSchema, parsedRepo)) { + throw new Error(`Invalid repo config: ${ajv.errorsText()}`); + } const parsedDefault: WideRepoConfig = DEFAULT_CONFIG_JSON; const privateKeyDecrypted = parsedOrg && parsedOrg[KEY_NAME] ? await getPrivateKey(parsedOrg[KEY_NAME]) : undefined; From 5a61607972014c522aa37d740b542a90d426c338 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Mon, 28 Aug 2023 12:14:58 +0200 Subject: [PATCH 22/88] feat: list unnecessary properties --- src/handlers/push/index.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/handlers/push/index.ts b/src/handlers/push/index.ts index 63c6d5516..532f7961a 100644 --- a/src/handlers/push/index.ts +++ b/src/handlers/push/index.ts @@ -87,11 +87,18 @@ export const validateConfigChange = async () => { const valid = ajv.validate(WideOrgConfigSchema, config); // additionalProperties: false is required to prevent unknown properties from being allowed if (!valid) { // post commit comment + const additionalProperties = ajv.errors?.map((error) => { + if (error.keyword === "additionalProperties") { + return error.params.additionalProperty; + } + }); await context.octokit.rest.repos.createCommitComment({ owner: payload.repository.owner.login, repo: payload.repository.name, commit_sha: commitSha, - body: `@${payload.sender.login} Config validation failed! Error: ${ajv.errorsText()}`, + body: `@${payload.sender.login} Config validation failed! Error: ${ajv.errorsText()}. ${ + additionalProperties && additionalProperties.length > 0 ? `Unnecessary properties: ${additionalProperties.join(", ")}` : "" + }`, path: BASE_RATE_FILE, }); } From b1250cdfab084c231437b4178c2815ab5d37f448 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Mon, 28 Aug 2023 12:44:09 +0200 Subject: [PATCH 23/88] fix: additional properties --- src/bindings/event.ts | 2 +- src/handlers/push/index.ts | 4 ++++ src/utils/private.ts | 45 +++++++++++++++++++++++++------------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/bindings/event.ts b/src/bindings/event.ts index 616580a1a..56019fefd 100644 --- a/src/bindings/event.ts +++ b/src/bindings/event.ts @@ -59,7 +59,7 @@ export const bindEvents = async (context: Context): Promise => { } if (botConfigError) { - logger.error(botConfigError); + logger.error(botConfigError.toString()); return; } diff --git a/src/handlers/push/index.ts b/src/handlers/push/index.ts index 532f7961a..ed110afda 100644 --- a/src/handlers/push/index.ts +++ b/src/handlers/push/index.ts @@ -72,6 +72,10 @@ export const validateConfigChange = async () => { // check for modified or added files and check for specified file if (changes.includes(BASE_RATE_FILE)) { const commitSha = payload.commits.filter((commit) => commit.modified.includes(BASE_RATE_FILE) || commit.added.includes(BASE_RATE_FILE)).reverse()[0]?.id; + if (!commitSha) { + logger.debug("Skipping push events, commit sha not found"); + return; + } const configFileContent = await getFileContent( payload.repository.owner.login, diff --git a/src/utils/private.ts b/src/utils/private.ts index ca4175058..d6027c53f 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -49,27 +49,42 @@ export const getConfigSuperset = async (context: Context, type: "org" | "repo", } }; -const WideLabelSchema = Type.Object({ - name: Type.String(), -}); +const WideLabelSchema = Type.Object( + { + name: Type.String(), + }, + { additionalProperties: false } +); export type WideLabel = Static; -const CommandObjSchema = Type.Object({ - name: Type.String(), - enabled: Type.Boolean(), -}); +const CommandObjSchema = Type.Object( + { + name: Type.String(), + enabled: Type.Boolean(), + }, + { additionalProperties: false } +); export type CommandObj = Static; -const IncentivesSchema = Type.Object({ - comment: Type.Object({ - elements: Type.Record(Type.String(), Type.Number()), - totals: Type.Object({ - word: Type.Number(), - }), - }), -}); +const IncentivesSchema = Type.Object( + { + comment: Type.Object( + { + elements: Type.Record(Type.String(), Type.Number()), + totals: Type.Object( + { + word: Type.Number(), + }, + { additionalProperties: false } + ), + }, + { additionalProperties: false } + ), + }, + { additionalProperties: false } +); export type Incentives = Static; From 5ec2d6abc39646f36c388ddc90a1b09e6df15148 Mon Sep 17 00:00:00 2001 From: HARALD Date: Tue, 29 Aug 2023 00:59:49 +0900 Subject: [PATCH 24/88] feat: get correct linked pull request --- src/handlers/payout/post.ts | 8 +++----- src/helpers/parser.ts | 20 ++++++++++++++++++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index ffeaee275..dd61d8b23 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -165,15 +165,13 @@ export const incentivizePullRequestReviews = async () => { return; } - const pullRequestLinked = await gitLinkedPrParser({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: issue.number }); + const linkedPullRequest = await gitLinkedPrParser({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: issue.number }); - if (pullRequestLinked === "") { + if (!linkedPullRequest) { logger.debug(`incentivizePullRequestReviews: No linked pull requests found`); return; } - const linkedPullNumber = pullRequestLinked.substring(pullRequestLinked.lastIndexOf("/") + 1); - const comments = await getAllIssueComments(issue.number); const permitComments = comments.filter( (content) => content.body.includes("Reviewer Rewards") && content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot @@ -190,7 +188,7 @@ export const incentivizePullRequestReviews = async () => { return; } - const prReviews = await getAllPullRequestReviews(context, Number(linkedPullNumber), "full"); + const prReviews = await getAllPullRequestReviews(context, linkedPullRequest.number, "full"); logger.info(`Getting the PR reviews done. comments: ${JSON.stringify(prReviews)}`); const prReviewsByUser: Record = {}; for (const review of prReviews) { diff --git a/src/helpers/parser.ts b/src/helpers/parser.ts index b7080f9a7..9bd668b7f 100644 --- a/src/helpers/parser.ts +++ b/src/helpers/parser.ts @@ -1,5 +1,7 @@ import axios from "axios"; import { HTMLElement, parse } from "node-html-parser"; +import { getPullByNumber } from "./issue"; +import { getBotContext } from "../bindings"; interface GitParser { owner: string; @@ -44,14 +46,28 @@ export const gitLinkedIssueParser = async ({ owner, repo, pull_number }: GitPars } }; -export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser): Promise => { +export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser) => { try { const { data } = await axios.get(`https://github.com/${owner}/${repo}/issues/${issue_number}`); const dom = parse(data); const devForm = dom.querySelector("[data-target='create-branch.developmentForm']") as HTMLElement; const linkedPRs = devForm.querySelectorAll(".my-1"); if (linkedPRs.length === 0) return ""; - return linkedPRs[linkedPRs.length - 1].querySelector("a")?.attrs?.href || ""; + let linkedPullRequest; + for (const linkedPr of linkedPRs) { + const prHref = linkedPr.querySelector("a")?.attrs?.href || ""; + const prNumber = prHref.substring(prHref.lastIndexOf("/") + 1); + const pr = await getPullByNumber(getBotContext(), Number(prNumber)); + if (!pr || !pr.merged) continue; + + if (!linkedPullRequest) linkedPullRequest = pr; + else if (linkedPullRequest.merged_at && pr.merged_at && new Date(linkedPullRequest.merged_at) < new Date(pr.merged_at)) { + linkedPullRequest = pr; + } + } + console.log("---------------------------"); + console.log(linkedPullRequest); + return linkedPullRequest; } catch (error) { return ""; } From d0f1b0611eecb96250307c56bac8c52ef5acce21 Mon Sep 17 00:00:00 2001 From: HARALD Date: Tue, 29 Aug 2023 01:20:55 +0900 Subject: [PATCH 25/88] feat: check the organization and repo name --- src/helpers/parser.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/helpers/parser.ts b/src/helpers/parser.ts index 9bd668b7f..82563657c 100644 --- a/src/helpers/parser.ts +++ b/src/helpers/parser.ts @@ -2,6 +2,7 @@ import axios from "axios"; import { HTMLElement, parse } from "node-html-parser"; import { getPullByNumber } from "./issue"; import { getBotContext } from "../bindings"; +import { Payload } from "../types"; interface GitParser { owner: string; @@ -49,6 +50,8 @@ export const gitLinkedIssueParser = async ({ owner, repo, pull_number }: GitPars export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser) => { try { const { data } = await axios.get(`https://github.com/${owner}/${repo}/issues/${issue_number}`); + const context = getBotContext(); + const payload = context.payload as Payload; const dom = parse(data); const devForm = dom.querySelector("[data-target='create-branch.developmentForm']") as HTMLElement; const linkedPRs = devForm.querySelectorAll(".my-1"); @@ -56,8 +59,14 @@ export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser let linkedPullRequest; for (const linkedPr of linkedPRs) { const prHref = linkedPr.querySelector("a")?.attrs?.href || ""; + const parts = prHref.split("/"); + // extract the organization name and repo name from the link:(e.g. "https://github.com/wannacfuture/ubiquibot/pull/5";) + const organization = parts[parts.length - 4]; + const repository = parts[parts.length - 3]; + + if (`${organization}/${repository}` !== payload.repository.full_name) continue; const prNumber = prHref.substring(prHref.lastIndexOf("/") + 1); - const pr = await getPullByNumber(getBotContext(), Number(prNumber)); + const pr = await getPullByNumber(context, Number(prNumber)); if (!pr || !pr.merged) continue; if (!linkedPullRequest) linkedPullRequest = pr; @@ -65,8 +74,6 @@ export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser linkedPullRequest = pr; } } - console.log("---------------------------"); - console.log(linkedPullRequest); return linkedPullRequest; } catch (error) { return ""; From 743a4777607bf861e8aa969c859451ef34a7aac1 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Tue, 29 Aug 2023 18:43:17 +0100 Subject: [PATCH 26/88] chore: merged repo and org config --- package.json | 4 +++- src/utils/helpers.ts | 6 +++++- yarn.lock | 28 +++++++++++++++++++--------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index e64d64e99..f6bcd54f2 100644 --- a/package.json +++ b/package.json @@ -41,8 +41,8 @@ "ajv": "^8.11.2", "ajv-formats": "^2.1.1", "axios": "^1.3.2", - "decimal.js": "^10.4.3", "copyfiles": "^2.4.1", + "decimal.js": "^10.4.3", "ethers": "^5.7.2", "exponential-backoff": "^3.1.1", "husky": "^8.0.2", @@ -50,6 +50,7 @@ "js-yaml": "^4.1.0", "libsodium-wrappers": "^0.7.11", "lint-staged": "^13.1.0", + "lodash": "^4.17.21", "ms": "^2.1.3", "node-html-parser": "^6.1.5", "node-html-to-image": "^3.3.0", @@ -65,6 +66,7 @@ "@types/eslint": "^8.40.2", "@types/jest": "^28.1.0", "@types/libsodium-wrappers": "^0.7.10", + "@types/lodash": "^4.14.197", "@types/node": "^14.18.37", "@types/source-map-support": "^0.5.6", "eslint": "^8.43.0", diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index e3965208b..534281d65 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -1,6 +1,7 @@ import { Incentives } from "./private"; import { Level } from "../adapters/supabase"; import { CommandObj, WideLabel, WideOrgConfig, WideRepoConfig } from "./private"; +import _ from "lodash"; interface Configs { parsedRepo?: WideRepoConfig; @@ -95,7 +96,10 @@ export const getPriorityLabels = ({ parsedRepo, parsedOrg, parsedDefault }: Conf }; export const getIncentives = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): Incentives => { - if (parsedRepo && parsedRepo["incentives"]) { + if (parsedRepo && parsedRepo["incentives"] && parsedOrg && parsedOrg["incentives"]) { + const mergedIncentives = _.merge({}, parsedOrg["incentives"], parsedRepo["incentives"]); + return mergedIncentives; + } else if (parsedRepo && parsedRepo["incentives"]) { return parsedRepo["incentives"]; } else if (parsedOrg && parsedOrg["incentives"]) { return parsedOrg["incentives"]; diff --git a/yarn.lock b/yarn.lock index 2d930cf18..23e875b72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1968,10 +1968,10 @@ dependencies: cross-fetch "^3.1.5" -"@supabase/realtime-js@^2.7.3": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.7.3.tgz#cbcb84181add681ab99c87032bfe88101c6863b3" - integrity sha512-c7TzL81sx2kqyxsxcDduJcHL9KJdCOoKimGP6lQSqiZKX42ATlBZpWbyy9KFGFBjAP4nyopMf5JhPi2ZH9jyNw== +"@supabase/realtime-js@^2.7.4": + version "2.7.4" + resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.7.4.tgz#de41195bd3f2cdd6db82d9f93c4c5b8fae9f809b" + integrity sha512-FzSzs1k9ruh/uds5AJ95Nc3beiMCCIhougExJ3O98CX1LMLAKUKFy5FivKLvcNhXnNfUEL0XUfGMb4UH2J7alg== dependencies: "@types/phoenix" "^1.5.4" "@types/websocket" "^1.0.3" @@ -1984,15 +1984,15 @@ dependencies: cross-fetch "^3.1.5" -"@supabase/supabase-js@^2.32.0": - version "2.32.0" - resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.32.0.tgz#863c636d83232c6a2e9ba5932e0d7c1bf80bc436" - integrity sha512-1ShFhuOI5Du7604nlCelBsRD61daXk2O0qwjumoz35bqrYThnSPPtpJqZOHw6Mg6o7mLjIInYLh/DBlh8UvzRg== +"@supabase/supabase-js@^2.4.0": + version "2.33.1" + resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.33.1.tgz#2407861afe63c2817d030514c87a745f78dfe68a" + integrity sha512-jA00rquPTppPOHpBB6KABW98lfg0gYXcuGqP3TB1iiduznRVsi3GGk2qBKXPDLMYSe0kRlQp5xCwWWthaJr8eA== dependencies: "@supabase/functions-js" "^2.1.0" "@supabase/gotrue-js" "^2.46.1" "@supabase/postgrest-js" "^1.8.0" - "@supabase/realtime-js" "^2.7.3" + "@supabase/realtime-js" "^2.7.4" "@supabase/storage-js" "^2.5.1" cross-fetch "^3.1.5" @@ -2190,6 +2190,11 @@ resolved "https://registry.yarnpkg.com/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz#a6ebde70d3b4af960fd802af8d0e3c7cfe281eb2" integrity sha512-BqI9B92u+cM3ccp8mpHf+HzJ8fBlRwdmyd6+fz3p99m3V6ifT5O3zmOMi612PGkpeFeG/G6loxUnzlDNhfjPSA== +"@types/lodash@^4.14.197": + version "4.14.197" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.197.tgz#e95c5ddcc814ec3e84c891910a01e0c8a378c54b" + integrity sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g== + "@types/mime@*": version "3.0.1" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" @@ -4189,6 +4194,11 @@ expect@^28.0.0: jest-message-util "^28.1.3" jest-util "^28.1.3" +exponential-backoff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" + integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== + express-handlebars@^6.0.3: version "6.0.7" resolved "https://registry.yarnpkg.com/express-handlebars/-/express-handlebars-6.0.7.tgz#f779254664eff0e250362ef1c2b30587059c212a" From 907b758c0f79123006fe98761137edd5c5f9abe5 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Wed, 30 Aug 2023 08:06:31 +0100 Subject: [PATCH 27/88] chore: merge default,repo and org --- src/utils/helpers.ts | 167 ------------------------------------------- src/utils/private.ts | 90 +++++++++++------------ 2 files changed, 43 insertions(+), 214 deletions(-) diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 534281d65..c188e6d50 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -1,13 +1,4 @@ -import { Incentives } from "./private"; import { Level } from "../adapters/supabase"; -import { CommandObj, WideLabel, WideOrgConfig, WideRepoConfig } from "./private"; -import _ from "lodash"; - -interface Configs { - parsedRepo?: WideRepoConfig; - parsedOrg?: WideOrgConfig; - parsedDefault: WideRepoConfig; -} export const getNumericLevel = (level: Level) => { switch (level) { @@ -29,161 +20,3 @@ export const getNumericLevel = (level: Level) => { return -1; // Invalid level } }; - -export const getNetworkId = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): number => { - if (parsedRepo && parsedRepo["evm-network-id"] !== undefined && !Number.isNaN(Number(parsedRepo["evm-network-id"]))) { - return Number(parsedRepo["evm-network-id"]); - } else if (parsedOrg && parsedOrg["evm-network-id"] !== undefined && !Number.isNaN(Number(parsedOrg["evm-network-id"]))) { - return Number(parsedOrg["evm-network-id"]); - } else { - return Number(parsedDefault["evm-network-id"]); - } -}; - -export const getBaseMultiplier = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): number => { - if (parsedRepo && parsedRepo["price-multiplier"] !== undefined && !Number.isNaN(Number(parsedRepo["price-multiplier"]))) { - return Number(parsedRepo["price-multiplier"]); - } else if (parsedOrg && parsedOrg["price-multiplier"] !== undefined && !Number.isNaN(Number(parsedOrg["price-multiplier"]))) { - return Number(parsedOrg["price-multiplier"]); - } else { - return Number(parsedDefault["price-multiplier"]); - } -}; - -export const getCreatorMultiplier = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): number => { - if (parsedRepo && parsedRepo["issue-creator-multiplier"] !== undefined && !Number.isNaN(Number(parsedRepo["issue-creator-multiplier"]))) { - return Number(parsedRepo["issue-creator-multiplier"]); - } else if (parsedOrg && parsedOrg["issue-creator-multiplier"] !== undefined && !Number.isNaN(Number(parsedOrg["issue-creator-multiplier"]))) { - return Number(parsedOrg["issue-creator-multiplier"]); - } else { - return Number(parsedDefault["issue-creator-multiplier"]); - } -}; - -export const getTimeLabels = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): WideLabel[] => { - if (parsedRepo && parsedRepo["time-labels"] !== undefined && Array.isArray(parsedRepo["time-labels"]) && parsedRepo["time-labels"].length > 0) { - return parsedRepo["time-labels"]; - } else if (parsedOrg && parsedOrg["time-labels"] !== undefined && Array.isArray(parsedOrg["time-labels"]) && parsedOrg["time-labels"].length > 0) { - return parsedOrg["time-labels"]; - } else { - return parsedDefault["time-labels"] as WideLabel[]; - } -}; - -export const getCommandSettings = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): CommandObj[] => { - if (parsedRepo && parsedRepo["command-settings"] && Array.isArray(parsedRepo["command-settings"]) && parsedRepo["command-settings"].length > 0) { - return parsedRepo["command-settings"]; - } else if (parsedOrg && parsedOrg["command-settings"] && Array.isArray(parsedOrg["command-settings"]) && parsedOrg["command-settings"].length > 0) { - return parsedOrg["command-settings"]; - } else { - return parsedDefault["command-settings"] as CommandObj[]; - } -}; - -export const getPriorityLabels = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): WideLabel[] => { - if (parsedRepo && parsedRepo["priority-labels"] !== undefined && Array.isArray(parsedRepo["priority-labels"]) && parsedRepo["priority-labels"].length > 0) { - return parsedRepo["priority-labels"]; - } else if ( - parsedOrg && - parsedOrg["priority-labels"] !== undefined && - Array.isArray(parsedOrg["priority-labels"]) && - parsedOrg["priority-labels"].length > 0 - ) { - return parsedOrg["priority-labels"]; - } else { - return parsedDefault["priority-labels"] as WideLabel[]; - } -}; - -export const getIncentives = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): Incentives => { - if (parsedRepo && parsedRepo["incentives"] && parsedOrg && parsedOrg["incentives"]) { - const mergedIncentives = _.merge({}, parsedOrg["incentives"], parsedRepo["incentives"]); - return mergedIncentives; - } else if (parsedRepo && parsedRepo["incentives"]) { - return parsedRepo["incentives"]; - } else if (parsedOrg && parsedOrg["incentives"]) { - return parsedOrg["incentives"]; - } else { - return parsedDefault["incentives"] as Incentives; - } -}; - -export const getPaymentPermitMaxPrice = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): number => { - if (parsedRepo && parsedRepo["payment-permit-max-price"] && typeof parsedRepo["payment-permit-max-price"] === "number") { - return Number(parsedRepo["payment-permit-max-price"]); - } else if (parsedOrg && parsedOrg["payment-permit-max-price"] && typeof parsedOrg["payment-permit-max-price"] === "number") { - return Number(parsedOrg["payment-permit-max-price"]); - } else { - return Number(parsedDefault["payment-permit-max-price"]); - } -}; - -export const getAssistivePricing = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): boolean => { - if (parsedRepo && parsedRepo["assistive-pricing"] && typeof parsedRepo["assistive-pricing"] === "boolean") { - return parsedRepo["assistive-pricing"]; - } else if (parsedOrg && parsedOrg["assistive-pricing"] && typeof parsedOrg["assistive-pricing"] === "boolean") { - return parsedOrg["assistive-pricing"]; - } else { - return parsedDefault["assistive-pricing"] as boolean; - } -}; - -export const getAnalyticsMode = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): boolean => { - if (parsedRepo && parsedRepo["disable-analytics"] !== undefined && typeof parsedRepo["disable-analytics"] === "boolean") { - return parsedRepo["disable-analytics"]; - } else if (parsedOrg && parsedOrg["disable-analytics"] !== undefined && typeof parsedOrg["disable-analytics"] === "boolean") { - return parsedOrg["disable-analytics"]; - } else { - return parsedDefault["disable-analytics"] as boolean; - } -}; - -export const getPromotionComment = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): string => { - if (parsedRepo && parsedRepo["promotion-comment"] !== undefined && typeof parsedRepo["promotion-comment"] === "string") { - return parsedRepo["promotion-comment"]; - } else if (parsedOrg && parsedOrg["promotion-comment"] !== undefined && typeof parsedOrg["promotion-comment"] === "string") { - return parsedOrg["promotion-comment"]; - } else { - return parsedDefault["promotion-comment"] as string; - } -}; - -export const getIncentiveMode = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): boolean => { - if (parsedRepo && parsedRepo["comment-incentives"] !== undefined && typeof parsedRepo["comment-incentives"] === "boolean") { - return parsedRepo["comment-incentives"]; - } else if (parsedOrg && parsedOrg["comment-incentives"] !== undefined && typeof parsedOrg["comment-incentives"] === "boolean") { - return parsedOrg["comment-incentives"]; - } else { - return parsedDefault["comment-incentives"] as boolean; - } -}; - -export const getBountyHunterMax = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): number => { - if (parsedRepo && parsedRepo["max-concurrent-assigns"] !== undefined && !Number.isNaN(Number(parsedRepo["max-concurrent-assigns"]))) { - return Number(parsedRepo["max-concurrent-assigns"]); - } else if (parsedOrg && parsedOrg["max-concurrent-assigns"] !== undefined && !Number.isNaN(Number(parsedOrg["max-concurrent-assigns"]))) { - return Number(parsedOrg["max-concurrent-assigns"]); - } else { - return Number(parsedDefault["max-concurrent-assigns"]); - } -}; - -export const getDefaultLabels = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): string[] => { - if (parsedRepo && parsedRepo["default-labels"] !== undefined) { - return parsedRepo["default-labels"]; - } else if (parsedOrg && parsedOrg["default-labels"] !== undefined) { - return parsedOrg["default-labels"]; - } else { - return parsedDefault["default-labels"] as string[]; - } -}; - -export const getRegisterWalletWithVerification = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): boolean => { - if (parsedRepo && parsedRepo["register-wallet-with-verification"] !== undefined && typeof parsedRepo["register-wallet-with-verification"] === "boolean") { - return Boolean(parsedRepo["register-wallet-with-verification"]); - } else if (parsedOrg && parsedOrg["register-wallet-with-verification"] !== undefined && typeof parsedOrg["register-wallet-with-verification"] === "boolean") { - return Boolean(parsedOrg["register-wallet-with-verification"]); - } else { - return Boolean(parsedDefault["register-wallet-with-verification"]); - } -}; diff --git a/src/utils/private.ts b/src/utils/private.ts index 36ff92f8c..116bc37a7 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -2,23 +2,7 @@ import _sodium from "libsodium-wrappers"; import YAML from "yaml"; import { Payload } from "../types"; import { Context } from "probot"; -import { - getAnalyticsMode, - getPaymentPermitMaxPrice, - getBaseMultiplier, - getCreatorMultiplier, - getBountyHunterMax, - getIncentiveMode, - getNetworkId, - getPriorityLabels, - getTimeLabels, - getDefaultLabels, - getPromotionComment, - getIncentives, - getAssistivePricing, - getCommandSettings, - getRegisterWalletWithVerification, -} from "./helpers"; +import _ from "lodash"; import DEFAULT_CONFIG_JSON from "../../ubiquibot-config-default.json"; @@ -68,21 +52,21 @@ export interface CommandObj { } export interface WideConfig { - "evm-network-id"?: number; - "price-multiplier"?: number; + "evm-network-id": number; + "price-multiplier": number; "issue-creator-multiplier": number; - "time-labels"?: WideLabel[]; - "priority-labels"?: WideLabel[]; - "payment-permit-max-price"?: number; - "command-settings"?: CommandObj[]; - "promotion-comment"?: string; - "disable-analytics"?: boolean; - "comment-incentives"?: boolean; - "assistive-pricing"?: boolean; - "max-concurrent-assigns"?: number; - incentives?: Incentives; - "default-labels"?: string[]; - "register-wallet-with-verification"?: boolean; + "time-labels": WideLabel[]; + "priority-labels": WideLabel[]; + "payment-permit-max-price": number; + "command-settings": CommandObj[]; + "promotion-comment": string; + "disable-analytics": boolean; + "comment-incentives": boolean; + "assistive-pricing": boolean; + "max-concurrent-assigns": number; + incentives: Incentives; + "default-labels": string[]; + "register-wallet-with-verification": boolean; } export type WideRepoConfig = WideConfig; @@ -91,6 +75,12 @@ export interface WideOrgConfig extends WideConfig { "private-key-encrypted"?: string; } +export interface MergedConfigs { + parsedRepo: WideRepoConfig | undefined; + parsedOrg: WideOrgConfig | undefined; + parsedDefault: WideRepoConfig; +} + export const parseYAML = (data?: string): WideConfig | undefined => { try { if (data) { @@ -155,6 +145,10 @@ export const getScalarKey = async (X25519_PRIVATE_KEY: string | undefined): Prom } }; +const mergeConfigs = (configs: MergedConfigs) => { + return _.merge({}, ...Object.values(configs)); +}; + export const getWideConfig = async (context: Context) => { const orgConfig = await getConfigSuperset(context, "org", CONFIG_PATH); const repoConfig = await getConfigSuperset(context, "repo", CONFIG_PATH); @@ -164,24 +158,26 @@ export const getWideConfig = async (context: Context) => { const parsedDefault: WideRepoConfig = DEFAULT_CONFIG_JSON; const privateKeyDecrypted = parsedOrg && parsedOrg[KEY_NAME] ? await getPrivateKey(parsedOrg[KEY_NAME]) : undefined; - const configs = { parsedRepo, parsedOrg, parsedDefault }; + const configs: MergedConfigs = { parsedRepo, parsedOrg, parsedDefault }; + const mergedConfigData: WideConfig = mergeConfigs(configs); + const configData = { - networkId: getNetworkId(configs), + networkId: mergedConfigData["evm-network-id"], privateKey: privateKeyDecrypted ?? "", - assistivePricing: getAssistivePricing(configs), - commandSettings: getCommandSettings(configs), - baseMultiplier: getBaseMultiplier(configs), - issueCreatorMultiplier: getCreatorMultiplier(configs), - timeLabels: getTimeLabels(configs), - priorityLabels: getPriorityLabels(configs), - paymentPermitMaxPrice: getPaymentPermitMaxPrice(configs), - disableAnalytics: getAnalyticsMode(configs), - bountyHunterMax: getBountyHunterMax(configs), - incentiveMode: getIncentiveMode(configs), - incentives: getIncentives(configs), - defaultLabels: getDefaultLabels(configs), - promotionComment: getPromotionComment(configs), - registerWalletWithVerification: getRegisterWalletWithVerification(configs), + assistivePricing: mergedConfigData["assistive-pricing"], + commandSettings: mergedConfigData["command-settings"], + baseMultiplier: mergedConfigData["price-multiplier"], + issueCreatorMultiplier: mergedConfigData["issue-creator-multiplier"], + timeLabels: mergedConfigData["time-labels"], + priorityLabels: mergedConfigData["priority-labels"], + paymentPermitMaxPrice: mergedConfigData["payment-permit-max-price"], + disableAnalytics: mergedConfigData["disable-analytics"], + bountyHunterMax: mergedConfigData["max-concurrent-assigns"], + incentiveMode: mergedConfigData["comment-incentives"], + incentives: mergedConfigData["incentives"], + defaultLabels: mergedConfigData["default-labels"], + promotionComment: mergedConfigData["promotion-comment"], + registerWalletWithVerification: mergedConfigData["register-wallet-with-verification"], }; return configData; From 7bbdadabab80bc8870cce94699661bc7d1da8126 Mon Sep 17 00:00:00 2001 From: DevPanther Date: Wed, 30 Aug 2023 08:16:38 +0100 Subject: [PATCH 28/88] chore: re-arrange order to use repo first --- src/utils/private.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/private.ts b/src/utils/private.ts index 116bc37a7..a78b48859 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -158,7 +158,7 @@ export const getWideConfig = async (context: Context) => { const parsedDefault: WideRepoConfig = DEFAULT_CONFIG_JSON; const privateKeyDecrypted = parsedOrg && parsedOrg[KEY_NAME] ? await getPrivateKey(parsedOrg[KEY_NAME]) : undefined; - const configs: MergedConfigs = { parsedRepo, parsedOrg, parsedDefault }; + const configs: MergedConfigs = { parsedDefault, parsedOrg, parsedRepo }; const mergedConfigData: WideConfig = mergeConfigs(configs); const configData = { From 39e2143512d9dce8434595506ec2330d264817be Mon Sep 17 00:00:00 2001 From: DevPanther <42383942+devpanther@users.noreply.github.com> Date: Wed, 30 Aug 2023 09:39:08 +0100 Subject: [PATCH 29/88] Update src/utils/private.ts Co-authored-by: whilefoo <139262667+whilefoo@users.noreply.github.com> --- src/utils/private.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/private.ts b/src/utils/private.ts index a78b48859..e040cc951 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -146,7 +146,7 @@ export const getScalarKey = async (X25519_PRIVATE_KEY: string | undefined): Prom }; const mergeConfigs = (configs: MergedConfigs) => { - return _.merge({}, ...Object.values(configs)); + return merge({}, configs.parsedDefault, configs.parsedOrg, configs.parsedRepo); }; export const getWideConfig = async (context: Context) => { From 646d4b8b0e53c0ead8347a2a54b37dc95dbe36e6 Mon Sep 17 00:00:00 2001 From: DevPanther <42383942+devpanther@users.noreply.github.com> Date: Wed, 30 Aug 2023 09:39:15 +0100 Subject: [PATCH 30/88] Update src/utils/private.ts Co-authored-by: whilefoo <139262667+whilefoo@users.noreply.github.com> --- src/utils/private.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/private.ts b/src/utils/private.ts index e040cc951..bc7ac27da 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -2,7 +2,7 @@ import _sodium from "libsodium-wrappers"; import YAML from "yaml"; import { Payload } from "../types"; import { Context } from "probot"; -import _ from "lodash"; +import merge from "lodash/merge"; import DEFAULT_CONFIG_JSON from "../../ubiquibot-config-default.json"; From 7f1dfc950e3fa4fcd4658feff2e3855c1b9cb631 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Wed, 30 Aug 2023 23:18:41 +0200 Subject: [PATCH 31/88] fix: run validate config if error loading config on push event refactor --- src/adapters/supabase/helpers/log.ts | 47 ++++++++------ src/bindings/config.ts | 5 +- src/bindings/event.ts | 14 +++-- src/handlers/push/index.ts | 25 ++------ src/helpers/commit.ts | 21 +++++++ src/helpers/index.ts | 1 + src/types/config.ts | 89 +++++++++++++++++++++------ src/types/index.ts | 1 + src/types/log.ts | 9 +++ src/utils/ajv.ts | 24 +++++++- src/utils/helpers.ts | 37 +++-------- src/utils/private.ts | 91 ++++------------------------ 12 files changed, 190 insertions(+), 174 deletions(-) create mode 100644 src/helpers/commit.ts create mode 100644 src/types/log.ts diff --git a/src/adapters/supabase/helpers/log.ts b/src/adapters/supabase/helpers/log.ts index e352339a8..51a16f5b2 100644 --- a/src/adapters/supabase/helpers/log.ts +++ b/src/adapters/supabase/helpers/log.ts @@ -1,26 +1,37 @@ import { getAdapters, getBotContext, Logger } from "../../../bindings"; -import { Payload } from "../../../types"; -import { getNumericLevel } from "../../../utils/helpers"; +import { Payload, LogLevel } from "../../../types"; import { getOrgAndRepoFromPath } from "../../../utils/private"; + interface Log { repo: string | null; org: string | null; commentId: number | undefined; issueNumber: number | undefined; logMessage: string; - level: Level; + level: LogLevel; timestamp: string; } -export enum Level { - ERROR = "error", - WARN = "warn", - INFO = "info", - HTTP = "http", - VERBOSE = "verbose", - DEBUG = "debug", - SILLY = "silly", -} +export const getNumericLevel = (level: LogLevel) => { + switch (level) { + case LogLevel.ERROR: + return 0; + case LogLevel.WARN: + return 1; + case LogLevel.INFO: + return 2; + case LogLevel.HTTP: + return 3; + case LogLevel.VERBOSE: + return 4; + case LogLevel.DEBUG: + return 5; + case LogLevel.SILLY: + return 6; + default: + return -1; // Invalid level + } +}; export class GitHubLogger implements Logger { private supabase; @@ -33,7 +44,7 @@ export class GitHubLogger implements Logger { private throttleCount = 0; private retryLimit = 0; // Retries disabled by default - constructor(app: string, logEnvironment: string, maxLevel: Level, retryLimit: number) { + constructor(app: string, logEnvironment: string, maxLevel: LogLevel, retryLimit: number) { this.app = app; this.logEnvironment = logEnvironment; this.maxLevel = getNumericLevel(maxLevel); @@ -118,7 +129,7 @@ export class GitHubLogger implements Logger { } } - private save(logMessage: string | object, level: Level, errorPayload?: string | object) { + private save(logMessage: string | object, level: LogLevel, errorPayload?: string | object) { if (getNumericLevel(level) > this.maxLevel) return; // only return errors lower than max level const context = getBotContext(); @@ -153,19 +164,19 @@ export class GitHubLogger implements Logger { } info(message: string | object, errorPayload?: string | object) { - this.save(message, Level.INFO, errorPayload); + this.save(message, LogLevel.INFO, errorPayload); } warn(message: string | object, errorPayload?: string | object) { - this.save(message, Level.WARN, errorPayload); + this.save(message, LogLevel.WARN, errorPayload); } debug(message: string | object, errorPayload?: string | object) { - this.save(message, Level.DEBUG, errorPayload); + this.save(message, LogLevel.DEBUG, errorPayload); } error(message: string | object, errorPayload?: string | object) { - this.save(message, Level.ERROR, errorPayload); + this.save(message, LogLevel.ERROR, errorPayload); } async get() { diff --git a/src/bindings/config.ts b/src/bindings/config.ts index 9fc6f4ed0..d87e4deaf 100644 --- a/src/bindings/config.ts +++ b/src/bindings/config.ts @@ -1,6 +1,6 @@ import ms from "ms"; -import { BotConfig, BotConfigSchema } from "../types"; +import { BotConfig, BotConfigSchema, LogLevel } from "../types"; import { DEFAULT_BOT_DELAY, DEFAULT_DISQUALIFY_TIME, @@ -13,7 +13,6 @@ import { getPayoutConfigByNetworkId } from "../helpers"; import { ajv } from "../utils"; import { Context } from "probot"; import { getScalarKey, getWideConfig } from "../utils/private"; -import { Level } from "../adapters/supabase"; export const loadConfig = async (context: Context): Promise => { const { @@ -41,7 +40,7 @@ export const loadConfig = async (context: Context): Promise => { const botConfig: BotConfig = { log: { logEnvironment: process.env.LOG_ENVIRONMENT || "production", - level: (process.env.LOG_LEVEL as Level) || Level.DEBUG, + level: (process.env.LOG_LEVEL as LogLevel) || LogLevel.DEBUG, retryLimit: Number(process.env.LOG_RETRY) || 0, }, price: { diff --git a/src/bindings/event.ts b/src/bindings/event.ts index 56019fefd..f36641565 100644 --- a/src/bindings/event.ts +++ b/src/bindings/event.ts @@ -2,11 +2,12 @@ import { Context } from "probot"; import { createAdapters } from "../adapters"; import { processors, wildcardProcessors } from "../handlers/processors"; import { shouldSkip } from "../helpers"; -import { BotConfig, GithubEvent, Payload, PayloadSchema } from "../types"; +import { BotConfig, GithubEvent, Payload, PayloadSchema, LogLevel } from "../types"; import { Adapters } from "../types/adapters"; import { ajv } from "../utils"; import { loadConfig } from "./config"; -import { GitHubLogger, Level } from "../adapters/supabase"; +import { GitHubLogger } from "../adapters/supabase"; +import { validateConfigChange } from "../handlers/push"; let botContext: Context = {} as Context; export const getBotContext = () => botContext; @@ -33,6 +34,8 @@ export const bindEvents = async (context: Context): Promise => { const { id, name } = context; botContext = context; const payload = context.payload as Payload; + const allowedEvents = Object.values(GithubEvent) as string[]; + const eventName = payload.action ? `${name}.${payload.action}` : name; // some events wont have actions as this grows let botConfigError; try { @@ -51,7 +54,7 @@ export const bindEvents = async (context: Context): Promise => { logger = new GitHubLogger( options.app, botConfig?.log?.logEnvironment ?? "development", - botConfig?.log?.level ?? Level.DEBUG, + botConfig?.log?.level ?? LogLevel.DEBUG, botConfig?.log?.retryLimit ?? 0 ); // contributors will see logs in console while on development env if (!logger) { @@ -60,6 +63,9 @@ export const bindEvents = async (context: Context): Promise => { if (botConfigError) { logger.error(botConfigError.toString()); + if (eventName === GithubEvent.PUSH_EVENT) { + await validateConfigChange(); + } return; } @@ -75,8 +81,6 @@ export const bindEvents = async (context: Context): Promise => { wallet: botConfig.wallet, })}` ); - const allowedEvents = Object.values(GithubEvent) as string[]; - const eventName = payload.action ? `${name}.${payload.action}` : name; // some events wont have actions as this grows logger.info(`Started binding events... id: ${id}, name: ${eventName}, allowedEvents: ${allowedEvents}`); diff --git a/src/handlers/push/index.ts b/src/handlers/push/index.ts index ed110afda..66dac755f 100644 --- a/src/handlers/push/index.ts +++ b/src/handlers/push/index.ts @@ -1,10 +1,9 @@ import { getBotContext, getLogger } from "../../bindings"; -import { getFileContent } from "../../helpers"; -import { CommitsPayload, PushPayload } from "../../types"; -import { ajv } from "../../utils"; +import { createCommitComment, getFileContent } from "../../helpers"; +import { CommitsPayload, PushPayload, WideOrgConfigSchema } from "../../types"; import { parseYAML } from "../../utils/private"; import { updateBaseRate } from "./update-base"; -import { WideOrgConfigSchema } from "../../utils/private"; +import { validate } from "../../utils/ajv"; const ZERO_SHA = "0000000000000000000000000000000000000000"; const BASE_RATE_FILE = ".github/ubiquibot-config.yml"; @@ -88,23 +87,9 @@ export const validateConfigChange = async () => { if (configFileContent) { const decodedConfig = Buffer.from(configFileContent, "base64").toString(); const config = parseYAML(decodedConfig); - const valid = ajv.validate(WideOrgConfigSchema, config); // additionalProperties: false is required to prevent unknown properties from being allowed + const { valid, error } = validate(WideOrgConfigSchema, config); if (!valid) { - // post commit comment - const additionalProperties = ajv.errors?.map((error) => { - if (error.keyword === "additionalProperties") { - return error.params.additionalProperty; - } - }); - await context.octokit.rest.repos.createCommitComment({ - owner: payload.repository.owner.login, - repo: payload.repository.name, - commit_sha: commitSha, - body: `@${payload.sender.login} Config validation failed! Error: ${ajv.errorsText()}. ${ - additionalProperties && additionalProperties.length > 0 ? `Unnecessary properties: ${additionalProperties.join(", ")}` : "" - }`, - path: BASE_RATE_FILE, - }); + await createCommitComment(`@${payload.sender.login} Config validation failed! ${error}`, commitSha, BASE_RATE_FILE); } } } diff --git a/src/helpers/commit.ts b/src/helpers/commit.ts new file mode 100644 index 000000000..678b4d774 --- /dev/null +++ b/src/helpers/commit.ts @@ -0,0 +1,21 @@ +import { getBotContext } from "../bindings"; +import { Payload } from "../types"; + +export async function createCommitComment(body: string, commitSha: string, path?: string, owner?: string, repo?: string) { + const context = getBotContext(); + const payload = context.payload as Payload; + if (!owner) { + owner = payload.repository.owner.login; + } + if (!repo) { + repo = payload.repository.name; + } + + await context.octokit.rest.repos.createCommitComment({ + owner: owner, + repo: repo, + commit_sha: commitSha, + body: body, + path: path, + }); +} diff --git a/src/helpers/index.ts b/src/helpers/index.ts index ad8ee0cb9..07cf66d74 100644 --- a/src/helpers/index.ts +++ b/src/helpers/index.ts @@ -9,3 +9,4 @@ export * from "./comment"; export * from "./payout"; export * from "./file"; export * from "./similarity"; +export * from "./commit"; diff --git a/src/types/config.ts b/src/types/config.ts index cda063811..093650085 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -1,28 +1,46 @@ import { Static, Type } from "@sinclair/typebox"; -import { Level } from "../adapters/supabase"; - -const LabelItemSchema = Type.Object({ - name: Type.String(), -}); +import { LogLevel } from "./log"; + +const LabelItemSchema = Type.Object( + { + name: Type.String(), + }, + { + additionalProperties: false, + } +); export type LabelItem = Static; -const CommentIncentivesSchema = Type.Object({ - elements: Type.Record(Type.String(), Type.Number()), - totals: Type.Object({ - word: Type.Number(), - }), -}); +const CommentIncentivesSchema = Type.Object( + { + elements: Type.Record(Type.String(), Type.Number()), + totals: Type.Object( + { + word: Type.Number(), + }, + { additionalProperties: false } + ), + }, + { additionalProperties: false } +); export type CommentIncentives = Static; -const IncentivesSchema = Type.Object({ - comment: CommentIncentivesSchema, -}); +const IncentivesSchema = Type.Object( + { + comment: CommentIncentivesSchema, + }, + { additionalProperties: false } +); + export type Incentives = Static; -const CommandItemSchema = Type.Object({ - name: Type.String(), - enabled: Type.Boolean(), -}); +const CommandItemSchema = Type.Object( + { + name: Type.String(), + enabled: Type.Boolean(), + }, + { additionalProperties: false } +); export type CommandItem = Static; export const PriceConfigSchema = Type.Object({ @@ -73,7 +91,7 @@ export const AssignSchema = Type.Object({ export const LogConfigSchema = Type.Object({ logEnvironment: Type.String(), - level: Type.Enum(Level), + level: Type.Enum(LogLevel), retryLimit: Type.Number(), }); @@ -109,3 +127,36 @@ export const BotConfigSchema = Type.Object({ }); export type BotConfig = Static; + +export const WideConfigSchema = Type.Object( + { + "evm-network-id": Type.Optional(Type.Number()), + "price-multiplier": Type.Optional(Type.Number()), + "issue-creator-multiplier": Type.Number(), + "time-labels": Type.Optional(Type.Array(LabelItemSchema)), + "priority-labels": Type.Optional(Type.Array(LabelItemSchema)), + "payment-permit-max-price": Type.Optional(Type.Number()), + "command-settings": Type.Optional(Type.Array(CommandItemSchema)), + "promotion-comment": Type.Optional(Type.String()), + "disable-analytics": Type.Optional(Type.Boolean()), + "comment-incentives": Type.Optional(Type.Boolean()), + "assistive-pricing": Type.Optional(Type.Boolean()), + "max-concurrent-assigns": Type.Optional(Type.Number()), + incentives: Type.Optional(IncentivesSchema), + "default-labels": Type.Optional(Type.Array(Type.String())), + "register-wallet-with-verification": Type.Optional(Type.Boolean()), + }, + { + additionalProperties: false, + } +); + +export type WideConfig = Static; + +export type WideRepoConfig = WideConfig; + +export const WideOrgConfigSchema = Type.Composite([Type.Object({ "private-key-encrypted": Type.Optional(Type.String()) }), WideConfigSchema], { + additionalProperties: false, +}); + +export type WideOrgConfig = Static; diff --git a/src/types/index.ts b/src/types/index.ts index d797feabf..83eac7e89 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -4,3 +4,4 @@ export * from "./label"; export * from "./handlers"; export * from "./config"; export * from "./markdown"; +export * from "./log"; diff --git a/src/types/log.ts b/src/types/log.ts new file mode 100644 index 000000000..8e3e1b913 --- /dev/null +++ b/src/types/log.ts @@ -0,0 +1,9 @@ +export enum LogLevel { + ERROR = "error", + WARN = "warn", + INFO = "info", + HTTP = "http", + VERBOSE = "verbose", + DEBUG = "debug", + SILLY = "silly", +} diff --git a/src/utils/ajv.ts b/src/utils/ajv.ts index 3a5d59d1b..11a8c87d1 100644 --- a/src/utils/ajv.ts +++ b/src/utils/ajv.ts @@ -1,4 +1,4 @@ -import Ajv from "ajv"; +import Ajv, { Schema } from "ajv"; import addFormats from "ajv-formats"; export const ajv = addFormats(new Ajv(), { @@ -27,3 +27,25 @@ export const ajv = addFormats(new Ajv(), { "binary", ], }); + +export function getAdditionalProperties() { + return ajv.errors?.map((error) => { + if (error.keyword === "additionalProperties") { + return error.params.additionalProperty; + } + }); +} + +export function validate(scheme: string | Schema, data: unknown): { valid: true; error: undefined } | { valid: false; error: string } { + const valid = ajv.validate(scheme, data); + if (!valid) { + const additionalProperties = getAdditionalProperties(); + return { + valid: false, + error: `${ajv.errorsText()}. ${ + additionalProperties && additionalProperties.length > 0 ? `Unnecessary properties: ${additionalProperties.join(", ")}` : "" + }`, + }; + } + return { valid: true, error: undefined }; +} diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index e3965208b..5432dbffc 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -1,6 +1,4 @@ -import { Incentives } from "./private"; -import { Level } from "../adapters/supabase"; -import { CommandObj, WideLabel, WideOrgConfig, WideRepoConfig } from "./private"; +import { CommandItem, LabelItem, WideOrgConfig, WideRepoConfig, Incentives } from "../types"; interface Configs { parsedRepo?: WideRepoConfig; @@ -8,27 +6,6 @@ interface Configs { parsedDefault: WideRepoConfig; } -export const getNumericLevel = (level: Level) => { - switch (level) { - case Level.ERROR: - return 0; - case Level.WARN: - return 1; - case Level.INFO: - return 2; - case Level.HTTP: - return 3; - case Level.VERBOSE: - return 4; - case Level.DEBUG: - return 5; - case Level.SILLY: - return 6; - default: - return -1; // Invalid level - } -}; - export const getNetworkId = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): number => { if (parsedRepo && parsedRepo["evm-network-id"] !== undefined && !Number.isNaN(Number(parsedRepo["evm-network-id"]))) { return Number(parsedRepo["evm-network-id"]); @@ -59,27 +36,27 @@ export const getCreatorMultiplier = ({ parsedRepo, parsedOrg, parsedDefault }: C } }; -export const getTimeLabels = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): WideLabel[] => { +export const getTimeLabels = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): LabelItem[] => { if (parsedRepo && parsedRepo["time-labels"] !== undefined && Array.isArray(parsedRepo["time-labels"]) && parsedRepo["time-labels"].length > 0) { return parsedRepo["time-labels"]; } else if (parsedOrg && parsedOrg["time-labels"] !== undefined && Array.isArray(parsedOrg["time-labels"]) && parsedOrg["time-labels"].length > 0) { return parsedOrg["time-labels"]; } else { - return parsedDefault["time-labels"] as WideLabel[]; + return parsedDefault["time-labels"] as LabelItem[]; } }; -export const getCommandSettings = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): CommandObj[] => { +export const getCommandSettings = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): CommandItem[] => { if (parsedRepo && parsedRepo["command-settings"] && Array.isArray(parsedRepo["command-settings"]) && parsedRepo["command-settings"].length > 0) { return parsedRepo["command-settings"]; } else if (parsedOrg && parsedOrg["command-settings"] && Array.isArray(parsedOrg["command-settings"]) && parsedOrg["command-settings"].length > 0) { return parsedOrg["command-settings"]; } else { - return parsedDefault["command-settings"] as CommandObj[]; + return parsedDefault["command-settings"] as CommandItem[]; } }; -export const getPriorityLabels = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): WideLabel[] => { +export const getPriorityLabels = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): LabelItem[] => { if (parsedRepo && parsedRepo["priority-labels"] !== undefined && Array.isArray(parsedRepo["priority-labels"]) && parsedRepo["priority-labels"].length > 0) { return parsedRepo["priority-labels"]; } else if ( @@ -90,7 +67,7 @@ export const getPriorityLabels = ({ parsedRepo, parsedOrg, parsedDefault }: Conf ) { return parsedOrg["priority-labels"]; } else { - return parsedDefault["priority-labels"] as WideLabel[]; + return parsedDefault["priority-labels"] as LabelItem[]; } }; diff --git a/src/utils/private.ts b/src/utils/private.ts index d6027c53f..094875b65 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -21,8 +21,8 @@ import { } from "./helpers"; import DEFAULT_CONFIG_JSON from "../../ubiquibot-config-default.json"; -import { Static, Type } from "@sinclair/typebox"; -import { ajv } from "./ajv"; +import { validate } from "./ajv"; +import { WideConfig, WideOrgConfig, WideRepoConfig, WideConfigSchema, WideOrgConfigSchema } from "../types"; const CONFIG_REPO = "ubiquibot-config"; const CONFIG_PATH = ".github/ubiquibot-config.yml"; @@ -49,78 +49,6 @@ export const getConfigSuperset = async (context: Context, type: "org" | "repo", } }; -const WideLabelSchema = Type.Object( - { - name: Type.String(), - }, - { additionalProperties: false } -); - -export type WideLabel = Static; - -const CommandObjSchema = Type.Object( - { - name: Type.String(), - enabled: Type.Boolean(), - }, - { additionalProperties: false } -); - -export type CommandObj = Static; - -const IncentivesSchema = Type.Object( - { - comment: Type.Object( - { - elements: Type.Record(Type.String(), Type.Number()), - totals: Type.Object( - { - word: Type.Number(), - }, - { additionalProperties: false } - ), - }, - { additionalProperties: false } - ), - }, - { additionalProperties: false } -); - -export type Incentives = Static; - -export const WideConfigSchema = Type.Object( - { - "evm-network-id": Type.Optional(Type.Number()), - "price-multiplier": Type.Optional(Type.Number()), - "issue-creator-multiplier": Type.Number(), - "time-labels": Type.Optional(Type.Array(WideLabelSchema)), - "priority-labels": Type.Optional(Type.Array(WideLabelSchema)), - "payment-permit-max-price": Type.Optional(Type.Number()), - "command-settings": Type.Optional(Type.Array(CommandObjSchema)), - "promotion-comment": Type.Optional(Type.String()), - "disable-analytics": Type.Optional(Type.Boolean()), - "comment-incentives": Type.Optional(Type.Boolean()), - "assistive-pricing": Type.Optional(Type.Boolean()), - "max-concurrent-assigns": Type.Optional(Type.Number()), - incentives: Type.Optional(IncentivesSchema), - "default-labels": Type.Optional(Type.Array(Type.String())), - "register-wallet-with-verification": Type.Optional(Type.Boolean()), - }, - { - additionalProperties: false, - } -); - -export type WideConfig = Static; - -export type WideRepoConfig = WideConfig; - -export const WideOrgConfigSchema = Type.Composite([Type.Object({ "private-key-encrypted": Type.Optional(Type.String()) }), WideConfigSchema], { - additionalProperties: false, -}); - -export type WideOrgConfig = Static; - export const parseYAML = (data?: string): WideConfig | undefined => { try { if (data) { @@ -190,12 +118,19 @@ export const getWideConfig = async (context: Context) => { const repoConfig = await getConfigSuperset(context, "repo", CONFIG_PATH); const parsedOrg: WideOrgConfig | undefined = parseYAML(orgConfig); - if (parsedOrg !== undefined && !ajv.validate(WideOrgConfigSchema, parsedOrg)) { - throw new Error(`Invalid org config: ${ajv.errorsText()}`); + + if (parsedOrg) { + const { valid, error } = validate(WideOrgConfigSchema, parsedOrg); + if (!valid) { + throw new Error(`Invalid org config: ${error}`); + } } const parsedRepo: WideRepoConfig | undefined = parseYAML(repoConfig); - if (parsedRepo !== undefined && !ajv.validate(WideConfigSchema, parsedRepo)) { - throw new Error(`Invalid repo config: ${ajv.errorsText()}`); + if (parsedRepo) { + const { valid, error } = validate(WideConfigSchema, parsedRepo); + if (!valid) { + throw new Error(`Invalid repo config: ${error}`); + } } const parsedDefault: WideRepoConfig = DEFAULT_CONFIG_JSON; const privateKeyDecrypted = parsedOrg && parsedOrg[KEY_NAME] ? await getPrivateKey(parsedOrg[KEY_NAME]) : undefined; From b3b2deaf66e9dddb353e42a310bf9a7d8c000167 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Thu, 31 Aug 2023 14:43:30 +0200 Subject: [PATCH 32/88] fix: filter then map --- src/utils/ajv.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/utils/ajv.ts b/src/utils/ajv.ts index 11a8c87d1..ce632101e 100644 --- a/src/utils/ajv.ts +++ b/src/utils/ajv.ts @@ -29,11 +29,7 @@ export const ajv = addFormats(new Ajv(), { }); export function getAdditionalProperties() { - return ajv.errors?.map((error) => { - if (error.keyword === "additionalProperties") { - return error.params.additionalProperty; - } - }); + return ajv.errors?.filter((error) => error.keyword === "additionalProperties").map((error) => error.params.additionalProperty); } export function validate(scheme: string | Schema, data: unknown): { valid: true; error: undefined } | { valid: false; error: string } { From 3eaedcc59d2813aaabb63533ae55477fbfc63ff0 Mon Sep 17 00:00:00 2001 From: 0xcodercrane <108444211+0xcodercrane@users.noreply.github.com> Date: Fri, 1 Sep 2023 12:52:49 +0800 Subject: [PATCH 33/88] feat: apply price label --- src/handlers/pricing/action.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handlers/pricing/action.ts b/src/handlers/pricing/action.ts index cd9dfa8a4..0b8982eaa 100644 --- a/src/handlers/pricing/action.ts +++ b/src/handlers/pricing/action.ts @@ -25,7 +25,7 @@ export const pricingLabelLogic = async (): Promise => { } const valid = await handleLabelsAccess(); - if (!valid) { + if (!valid && config.accessControl.label) { return; } From eb1d942f4a4d033b856ebc20756b73eb162e20e3 Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Sat, 2 Sep 2023 08:05:23 +0000 Subject: [PATCH 34/88] feat: display permission level in /query --- src/handlers/comment/handlers/query.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/handlers/comment/handlers/query.ts b/src/handlers/comment/handlers/query.ts index efee499d1..69f117bfc 100644 --- a/src/handlers/comment/handlers/query.ts +++ b/src/handlers/comment/handlers/query.ts @@ -1,5 +1,6 @@ import { getWalletInfo } from "../../../adapters/supabase"; import { getBotContext, getLogger } from "../../../bindings"; +import { getUserPermission } from "../../../helpers"; import { Payload } from "../../../types"; export const query = async (body: string) => { @@ -22,13 +23,14 @@ export const query = async (body: string) => { const regex = /^\/query\s+@([\w-]+)\s*$/; const matches = body.match(regex); const user = matches?.[1]; + const permissionLevel = await getUserPermission(sender, context); if (user) { const walletInfo = await getWalletInfo(user, id?.toString()); if (!walletInfo?.address) { return `Error retrieving multiplier and wallet address for @${user}`; } else { - return `@${user}'s wallet address is ${walletInfo?.address} and multiplier is ${walletInfo?.multiplier}`; + return `@${user}'s wallet address is ${walletInfo?.address}, multiplier is ${walletInfo?.multiplier} and permission level is ${permissionLevel}`; } } else { logger.error("Invalid body for query command"); From f2a684b67af760a53ca7e16fbe404af8e0ee6a3b Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Sat, 2 Sep 2023 08:31:54 +0000 Subject: [PATCH 35/88] feat: disable bot follow up for pending reviews --- src/handlers/wildcard/unassign.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/handlers/wildcard/unassign.ts b/src/handlers/wildcard/unassign.ts index 8e06ecebd..6d5feaaea 100644 --- a/src/handlers/wildcard/unassign.ts +++ b/src/handlers/wildcard/unassign.ts @@ -1,5 +1,5 @@ import { closePullRequestForAnIssue } from "../assign"; -import { getBotConfig, getLogger } from "../../bindings"; +import { getBotConfig, getBotContext, getLogger } from "../../bindings"; import { GLOBAL_STRINGS } from "../../configs/strings"; import { addCommentToIssue, @@ -9,7 +9,7 @@ import { listAllIssuesForRepo, removeAssignees, } from "../../helpers"; -import { Comment, Issue, IssueType } from "../../types"; +import { Comment, Issue, IssueType, Payload } from "../../types"; /** * @dev Check out the bounties which haven't been completed within the initial timeline @@ -31,6 +31,8 @@ export const checkBountiesToUnassign = async () => { }; const checkBountyToUnassign = async (issue: Issue): Promise => { + const context = getBotContext(); + const payload = context.payload as Payload; const logger = getLogger(); const { unassign: { followUpTime, disqualifyTime }, @@ -49,7 +51,18 @@ const checkBountyToUnassign = async (issue: Issue): Promise => { const curTimestamp = new Date().getTime(); const lastActivity = await lastActivityTime(issue, comments); const passedDuration = curTimestamp - lastActivity.getTime(); + const pullRequest = await getOpenedPullRequestsForAnIssue(issue.number, issue.assignee); + const { data: reviews } = await context.octokit.pulls.listReviews({ + owner: payload.repository.owner.login, + repo: payload.repository.name, + pull_number: pullRequest[0].id, + }); + + const pendingReviews = reviews.filter((review) => review.state === "PENDING"); + if (pendingReviews.length > 0) { + return false; + } if (passedDuration >= disqualifyTime || passedDuration >= followUpTime) { if (passedDuration >= disqualifyTime) { logger.info( From c86011c0fca458ed53c02ba687674aa534ba15a6 Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Sun, 3 Sep 2023 06:56:34 +0000 Subject: [PATCH 36/88] feat: display access level in /query --- src/handlers/comment/handlers/query.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/handlers/comment/handlers/query.ts b/src/handlers/comment/handlers/query.ts index 69f117bfc..d9a07aac3 100644 --- a/src/handlers/comment/handlers/query.ts +++ b/src/handlers/comment/handlers/query.ts @@ -1,6 +1,5 @@ -import { getWalletInfo } from "../../../adapters/supabase"; +import { getAccessLevel, getWalletInfo } from "../../../adapters/supabase"; import { getBotContext, getLogger } from "../../../bindings"; -import { getUserPermission } from "../../../helpers"; import { Payload } from "../../../types"; export const query = async (body: string) => { @@ -23,14 +22,24 @@ export const query = async (body: string) => { const regex = /^\/query\s+@([\w-]+)\s*$/; const matches = body.match(regex); const user = matches?.[1]; - const permissionLevel = await getUserPermission(sender, context); + const repo = payload.repository; if (user) { const walletInfo = await getWalletInfo(user, id?.toString()); if (!walletInfo?.address) { return `Error retrieving multiplier and wallet address for @${user}`; } else { - return `@${user}'s wallet address is ${walletInfo?.address}, multiplier is ${walletInfo?.multiplier} and permission level is ${permissionLevel}`; + return `@${user}'s wallet address is ${walletInfo?.address}, multiplier is ${walletInfo?.multiplier} and access levels are +| access type | access level | +| ----------- | ------------ |access type access level +multiplier true +priority true +time true +price true +| multiplier | ${getAccessLevel(sender, repo.full_name, "multiplier")} | +| priority | ${getAccessLevel(sender, repo.full_name, "priority")} | +| time | ${getAccessLevel(sender, repo.full_name, "time")} | +| price | ${getAccessLevel(sender, repo.full_name, "price")} |`; } } else { logger.error("Invalid body for query command"); From cf55a97842ba9f59c86e1a7691116ba1efacfc9f Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Sun, 3 Sep 2023 06:57:29 +0000 Subject: [PATCH 37/88] feat: display access level in /query --- src/handlers/comment/handlers/query.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/handlers/comment/handlers/query.ts b/src/handlers/comment/handlers/query.ts index d9a07aac3..6bbc342d6 100644 --- a/src/handlers/comment/handlers/query.ts +++ b/src/handlers/comment/handlers/query.ts @@ -31,11 +31,6 @@ export const query = async (body: string) => { } else { return `@${user}'s wallet address is ${walletInfo?.address}, multiplier is ${walletInfo?.multiplier} and access levels are | access type | access level | -| ----------- | ------------ |access type access level -multiplier true -priority true -time true -price true | multiplier | ${getAccessLevel(sender, repo.full_name, "multiplier")} | | priority | ${getAccessLevel(sender, repo.full_name, "priority")} | | time | ${getAccessLevel(sender, repo.full_name, "time")} | From 8ce9053747e6e80278b68c77f9fbfdaedcb21340 Mon Sep 17 00:00:00 2001 From: HARALD Date: Mon, 4 Sep 2023 18:01:11 +0900 Subject: [PATCH 38/88] feat: fix for nonse in incentive pr review --- src/handlers/payout/post.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index 92969028e..00326fe18 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -192,7 +192,7 @@ export const incentivizePullRequestReviews = async () => { const prReviews = await getAllPullRequestReviews(context, linkedPullRequest.number, "full"); logger.info(`Getting the PR reviews done. comments: ${JSON.stringify(prReviews)}`); - const prReviewsByUser: Record = {}; + const prReviewsByUser: Record = {}; for (const review of prReviews) { const user = review.user; if (!user) continue; @@ -202,9 +202,9 @@ export const incentivizePullRequestReviews = async () => { continue; } if (!prReviewsByUser[user.login]) { - prReviewsByUser[user.login] = []; + prReviewsByUser[user.login] = { id: user.node_id, comments: [] }; } - prReviewsByUser[user.login].push(review.body_html); + prReviewsByUser[user.login].comments.push(review.body_html); } const tokenSymbol = await getTokenSymbol(paymentToken, rpc); logger.info(`incentivizePullRequestReviews: Filtering by the user type done. commentsByUser: ${JSON.stringify(prReviewsByUser)}`); @@ -216,8 +216,8 @@ export const incentivizePullRequestReviews = async () => { const fallbackReward: Record = {}; let comment = `#### Reviewer Rewards\n`; for (const user of Object.keys(prReviewsByUser)) { - const comments = prReviewsByUser[user]; - const commentsByNode = await parseComments(comments, ItemsToExclude); + const commentByUser = prReviewsByUser[user]; + const commentsByNode = await parseComments(commentByUser.comments, ItemsToExclude); const rewardValue = calculateRewardValue(commentsByNode, incentives); if (rewardValue.equals(0)) { logger.info(`incentivizePullRequestReviews: Skipping to generate a permit url because the reward value is 0. user: ${user}`); @@ -231,7 +231,7 @@ export const incentivizePullRequestReviews = async () => { continue; } if (account) { - const { payoutUrl } = await generatePermit2Signature(account, amountInETH, issue.node_id); + const { payoutUrl } = await generatePermit2Signature(account, amountInETH, issue.node_id, commentByUser.id, "ISSUE_COMMENTER"); comment = `${comment}### [ **${user}: [ CLAIM ${amountInETH} ${tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n`; reward[user] = payoutUrl; } else { From 2709407cb09acc32fe1b58b426d26c39dc69dd6e Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Mon, 4 Sep 2023 12:59:18 +0000 Subject: [PATCH 39/88] feat: display access levels in /query --- src/adapters/supabase/helpers/client.ts | 21 +++++++++++++++++++++ src/handlers/comment/handlers/query.ts | 14 +++++++++----- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/adapters/supabase/helpers/client.ts b/src/adapters/supabase/helpers/client.ts index cbd0629f7..7e54f904f 100644 --- a/src/adapters/supabase/helpers/client.ts +++ b/src/adapters/supabase/helpers/client.ts @@ -5,6 +5,13 @@ import { Database } from "../types"; import { InsertPermit, Permit } from "../../../helpers"; import { BigNumber, BigNumberish } from "ethers"; +interface accessLevels { + multiplier: boolean; + price: boolean; + priority: boolean; + time: boolean; +} + /** * @dev Creates a typescript client which will be used to interact with supabase platform * @@ -340,6 +347,20 @@ export const getAccessLevel = async (username: string, repository: string, label return accessValues; }; +export const getAllAccessLevels = async (username: string, repository: string): Promise => { + const logger = getLogger(); + const { supabase } = getAdapters(); + + const { data } = await supabase.from("access").select("*").eq("user_name", username).eq("repository", repository).single(); + + if (!data) { + logger.info(`Access not found on the database`); + // no access + return false; + } + return { multiplier: data["multiplier_access"], time: data["time_access"], priority: data["priority_access"], price: data["price_access"] }; +}; + /** * Queries the wallet address registered previously * diff --git a/src/handlers/comment/handlers/query.ts b/src/handlers/comment/handlers/query.ts index 6bbc342d6..e75e255f4 100644 --- a/src/handlers/comment/handlers/query.ts +++ b/src/handlers/comment/handlers/query.ts @@ -1,4 +1,4 @@ -import { getAccessLevel, getWalletInfo } from "../../../adapters/supabase"; +import { getAccessLevel, getAllAccessLevels, getWalletInfo } from "../../../adapters/supabase"; import { getBotContext, getLogger } from "../../../bindings"; import { Payload } from "../../../types"; @@ -25,16 +25,20 @@ export const query = async (body: string) => { const repo = payload.repository; if (user) { + let data = await getAllAccessLevels(user, repo.full_name); + if (data === false) { + return `Error retrieving access for @${user}`; + } const walletInfo = await getWalletInfo(user, id?.toString()); if (!walletInfo?.address) { return `Error retrieving multiplier and wallet address for @${user}`; } else { return `@${user}'s wallet address is ${walletInfo?.address}, multiplier is ${walletInfo?.multiplier} and access levels are | access type | access level | -| multiplier | ${getAccessLevel(sender, repo.full_name, "multiplier")} | -| priority | ${getAccessLevel(sender, repo.full_name, "priority")} | -| time | ${getAccessLevel(sender, repo.full_name, "time")} | -| price | ${getAccessLevel(sender, repo.full_name, "price")} |`; +| multiplier | ${data["multiplier"]} | +| priority | ${data["priority"]} | +| time | ${data["time"]} | +| price | ${data["price"]} |`; } } else { logger.error("Invalid body for query command"); From 7fd7d3b83aaab0b19673d9c601937d9fdeb3f18c Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 5 Sep 2023 09:04:20 +0100 Subject: [PATCH 40/88] fix: warning header allowing zero input and changed warning --- src/bindings/config.ts | 4 ++-- src/configs/shared.ts | 1 - src/handlers/comment/handlers/assign.ts | 4 ++-- src/handlers/comment/handlers/table.ts | 13 ++++++------- src/types/config.ts | 2 +- src/utils/private.ts | 4 +--- ubiquibot-config-default.json | 18 +++++++++--------- yarn.lock | 18 +++++++++--------- 8 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/bindings/config.ts b/src/bindings/config.ts index 66cf7e64e..fcc980075 100644 --- a/src/bindings/config.ts +++ b/src/bindings/config.ts @@ -1,7 +1,7 @@ import ms from "ms"; import { BotConfig, BotConfigSchema } from "../types"; -import { DEFAULT_BOT_DELAY, DEFAULT_DISQUALIFY_TIME, DEFAULT_FOLLOWUP_TIME, DEFAULT_PERMIT_BASE_URL, STALE_BOUNTY_TIME } from "../configs"; +import { DEFAULT_BOT_DELAY, DEFAULT_DISQUALIFY_TIME, DEFAULT_FOLLOWUP_TIME, DEFAULT_PERMIT_BASE_URL } from "../configs"; import { getPayoutConfigByNetworkId } from "../helpers"; import { ajv } from "../utils"; import { Context } from "probot"; @@ -77,7 +77,7 @@ export const loadConfig = async (context: Context): Promise => { command: commandSettings, assign: { bountyHunterMax: bountyHunterMax, - staleBountyTime: staleBountyTime ? staleBountyTime : ms(STALE_BOUNTY_TIME), + staleBountyTime: staleBountyTime ? String(ms(staleBountyTime)) : "0", }, sodium: { privateKey: process.env.X25519_PRIVATE_KEY ?? "", diff --git a/src/configs/shared.ts b/src/configs/shared.ts index b90b587ff..2d817b7a0 100644 --- a/src/configs/shared.ts +++ b/src/configs/shared.ts @@ -22,7 +22,6 @@ export const ASSIGN_COMMAND_ENABLED = true; */ export const DEFAULT_FOLLOWUP_TIME = "4 days"; // 4 days export const DEFAULT_DISQUALIFY_TIME = "7 days"; // 7 days -export const STALE_BOUNTY_TIME = "30d"; // 30 days export const DEFAULT_NETWORK_ID = 1; // ethereum export const DEFAULT_RPC_ENDPOINT = "https://rpc-bot.ubq.fi/v1/mainnet"; diff --git a/src/handlers/comment/handlers/assign.ts b/src/handlers/comment/handlers/assign.ts index cbb7df465..d3cf1ef41 100644 --- a/src/handlers/comment/handlers/assign.ts +++ b/src/handlers/comment/handlers/assign.ts @@ -18,7 +18,7 @@ export const assign = async (body: string) => { const id = organization?.id || repository?.id; // repository?.id as fallback - const staleBounty = config.assign.staleBountyTime; + const staleBounty = Number(config.assign.staleBountyTime); logger.info(`Received '/start' command from user: ${payload.sender.login}, body: ${body}`); const issue = (_payload as Payload).issue; @@ -112,8 +112,8 @@ export const assign = async (body: string) => { await addAssignees(issue.number, [payload.sender.login]); } - const isBountyStale = new Date().getTime() - new Date(issue.created_at).getTime() > staleBounty; const days = Math.floor((new Date().getTime() - new Date(issue.created_at).getTime()) / (1000 * 60 * 60 * 24)); + const isBountyStale = staleBounty == 0 ? null : staleBounty > days ? false : true; // double check whether the assign message has been already posted or not logger.info(`Creating an issue comment: ${comment.commit}`); diff --git a/src/handlers/comment/handlers/table.ts b/src/handlers/comment/handlers/table.ts index bc2349cdf..a130eb2c3 100644 --- a/src/handlers/comment/handlers/table.ts +++ b/src/handlers/comment/handlers/table.ts @@ -12,20 +12,19 @@ export const tableComment = ({ multiplier?: string; reason?: string; bounty?: string; - isBountyStale?: boolean; + isBountyStale?: boolean | null; days?: number; }) => { return `
Ready to begin?You can start right away!This task was created over ${days} days ago. Please verify that it is still current.You can start right away!This task was created over ${days} days ago. Please verify that it is still current before starting work.
Deadline
- - ${ - !isBountyStale - ? `` - : `` + isBountyStale == null + ? null + : isBountyStale + ? `` + : `` } - diff --git a/src/types/config.ts b/src/types/config.ts index 373262377..ff642e221 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -69,7 +69,7 @@ export const ModeSchema = Type.Object({ export const AssignSchema = Type.Object({ bountyHunterMax: Type.Number(), - staleBountyTime: Type.Number(), + staleBountyTime: Type.String(), }); export const LogConfigSchema = Type.Object({ diff --git a/src/utils/private.ts b/src/utils/private.ts index d10ac378e..5adf2adc9 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -21,8 +21,6 @@ import { } from "./helpers"; import DEFAULT_CONFIG_JSON from "../../ubiquibot-config-default.json"; -import { STALE_BOUNTY_TIME } from "../configs"; -import ms from "ms"; const CONFIG_REPO = "ubiquibot-config"; const CONFIG_PATH = ".github/ubiquibot-config.yml"; @@ -187,7 +185,7 @@ export const getWideConfig = async (context: Context) => { defaultLabels: getDefaultLabels(configs), promotionComment: getPromotionComment(configs), registerWalletWithVerification: getRegisterWalletWithVerification(configs), - staleBountyTime: parsedDefault["stale-bounty-time"] == "0" ? ms(STALE_BOUNTY_TIME) : parsedDefault["stale-bounty-time"], + staleBountyTime: parsedDefault["stale-bounty-time"], }; return configData; diff --git a/ubiquibot-config-default.json b/ubiquibot-config-default.json index 5271a5d7f..4aa7ff9ba 100644 --- a/ubiquibot-config-default.json +++ b/ubiquibot-config-default.json @@ -8,7 +8,7 @@ "disable-analytics": false, "comment-incentives": false, "register-wallet-with-verification": false, - "stale-bounty-time": 42060, + "stale-bounty-time": "30d", "promotion-comment": "\n
If you enjoy the DevPool experience, please follow Ubiquity on GitHub and star this repo to show your support. It helps a lot!
", "default-labels": [], "time-labels": [ @@ -63,35 +63,35 @@ "command-settings": [ { "name": "start", - "enabled": true + "enabled": false }, { "name": "stop", - "enabled": true + "enabled": false }, { "name": "wallet", - "enabled": true + "enabled": false }, { "name": "payout", - "enabled": true + "enabled": false }, { "name": "multiplier", - "enabled": true + "enabled": false }, { "name": "query", - "enabled": true + "enabled": false }, { "name": "allow", - "enabled": true + "enabled": false }, { "name": "autopay", - "enabled": true + "enabled": false } ], "incentives": { diff --git a/yarn.lock b/yarn.lock index 2d930cf18..59de7f019 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1968,10 +1968,10 @@ dependencies: cross-fetch "^3.1.5" -"@supabase/realtime-js@^2.7.3": - version "2.7.3" - resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.7.3.tgz#cbcb84181add681ab99c87032bfe88101c6863b3" - integrity sha512-c7TzL81sx2kqyxsxcDduJcHL9KJdCOoKimGP6lQSqiZKX42ATlBZpWbyy9KFGFBjAP4nyopMf5JhPi2ZH9jyNw== +"@supabase/realtime-js@^2.7.4": + version "2.7.4" + resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.7.4.tgz#de41195bd3f2cdd6db82d9f93c4c5b8fae9f809b" + integrity sha512-FzSzs1k9ruh/uds5AJ95Nc3beiMCCIhougExJ3O98CX1LMLAKUKFy5FivKLvcNhXnNfUEL0XUfGMb4UH2J7alg== dependencies: "@types/phoenix" "^1.5.4" "@types/websocket" "^1.0.3" @@ -1984,15 +1984,15 @@ dependencies: cross-fetch "^3.1.5" -"@supabase/supabase-js@^2.32.0": - version "2.32.0" - resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.32.0.tgz#863c636d83232c6a2e9ba5932e0d7c1bf80bc436" - integrity sha512-1ShFhuOI5Du7604nlCelBsRD61daXk2O0qwjumoz35bqrYThnSPPtpJqZOHw6Mg6o7mLjIInYLh/DBlh8UvzRg== +"@supabase/supabase-js@^2.4.0": + version "2.33.1" + resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.33.1.tgz#2407861afe63c2817d030514c87a745f78dfe68a" + integrity sha512-jA00rquPTppPOHpBB6KABW98lfg0gYXcuGqP3TB1iiduznRVsi3GGk2qBKXPDLMYSe0kRlQp5xCwWWthaJr8eA== dependencies: "@supabase/functions-js" "^2.1.0" "@supabase/gotrue-js" "^2.46.1" "@supabase/postgrest-js" "^1.8.0" - "@supabase/realtime-js" "^2.7.3" + "@supabase/realtime-js" "^2.7.4" "@supabase/storage-js" "^2.5.1" cross-fetch "^3.1.5" From dc1d7ec75c5ab4cd374545d92be31ff918e11615 Mon Sep 17 00:00:00 2001 From: ByteBallet Date: Tue, 5 Sep 2023 04:02:06 -0500 Subject: [PATCH 41/88] fix: ignore param order for allow --- src/handlers/comment/handlers/allow.ts | 33 +++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/handlers/comment/handlers/allow.ts b/src/handlers/comment/handlers/allow.ts index a4fb44324..543c88047 100644 --- a/src/handlers/comment/handlers/allow.ts +++ b/src/handlers/comment/handlers/allow.ts @@ -20,12 +20,39 @@ export const setAccess = async (body: string) => { return; } - const regex = /^\/allow set-(\S+)\s@(\S+)\s(true|false)$/; - + const regex = + /^\/allow (?:set-(\S+)\s@(\w+)\s(true|false)|set-(\S+)\s(true|false)\s@(\w+)|(true|false)\sset-(\S+)\s@(\w+)|(true|false)\s@(\w+)\sset-(\S+)|@(\w+)\s(true|false)\sset-(\S+)|@(\w+)\sset-(\S+)\s(true|false))$/; const matches = body.match(regex); if (matches) { - const [, accessType, username, bool] = matches; + let accessType, username, bool; + if (matches[1]) { + accessType = matches[1]; + username = matches[2]; + bool = matches[3]; + } else if (matches[4]) { + username = matches[4]; + accessType = matches[5]; + bool = matches[6]; + } else if (matches[7]) { + bool = matches[7]; + accessType = matches[8]; + username = matches[9]; + } else if (matches[10]) { + accessType = matches[10]; + bool = matches[11]; + username = matches[12]; + } else if (matches[13]) { + username = matches[13]; + bool = matches[14]; + accessType = matches[15]; + } else if (matches[16]) { + bool = matches[16]; + username = matches[17]; + accessType = matches[18]; + } else { + bool = username = accessType = ""; + } // Check if access control demand is valid if (!validAccessString.includes(accessType)) { From 4d98c130689997385e24a97a9bfb1dd3377cb45b Mon Sep 17 00:00:00 2001 From: ByteBallet Date: Tue, 5 Sep 2023 04:18:03 -0500 Subject: [PATCH 42/88] fix: ignore param order for allow --- src/handlers/comment/handlers/allow.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/handlers/comment/handlers/allow.ts b/src/handlers/comment/handlers/allow.ts index 543c88047..bc7e86d4c 100644 --- a/src/handlers/comment/handlers/allow.ts +++ b/src/handlers/comment/handlers/allow.ts @@ -31,25 +31,25 @@ export const setAccess = async (body: string) => { username = matches[2]; bool = matches[3]; } else if (matches[4]) { - username = matches[4]; - accessType = matches[5]; - bool = matches[6]; + accessType = matches[4]; + bool = matches[5]; + username = matches[6]; } else if (matches[7]) { bool = matches[7]; accessType = matches[8]; username = matches[9]; } else if (matches[10]) { - accessType = matches[10]; - bool = matches[11]; - username = matches[12]; + bool = matches[10]; + username = matches[11]; + accessType = matches[12]; } else if (matches[13]) { username = matches[13]; bool = matches[14]; accessType = matches[15]; } else if (matches[16]) { - bool = matches[16]; - username = matches[17]; - accessType = matches[18]; + username = matches[16]; + accessType = matches[17]; + bool = matches[18]; } else { bool = username = accessType = ""; } From 74d1b4ae682ff2dcf3e6d5cfa087a19a0de048e8 Mon Sep 17 00:00:00 2001 From: ByteBallet Date: Tue, 5 Sep 2023 06:53:24 -0500 Subject: [PATCH 43/88] fix: check both pr and issue to verify first comment --- src/handlers/comment/handlers/first.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/handlers/comment/handlers/first.ts b/src/handlers/comment/handlers/first.ts index c14d50702..1e7400a35 100644 --- a/src/handlers/comment/handlers/first.ts +++ b/src/handlers/comment/handlers/first.ts @@ -10,14 +10,19 @@ export const verifyFirstCheck = async (): Promise => { if (!payload.issue) return; try { - const response = await context.octokit.rest.search.issuesAndPullRequests({ + const response_issue = await context.octokit.rest.search.issuesAndPullRequests({ q: `is:issue repo:${payload.repository.owner.login}/${payload.repository.name} commenter:${payload.sender.login}`, per_page: 2, }); - if (response.data.total_count === 1) { + const response_pr = await context.octokit.rest.search.issuesAndPullRequests({ + q: `is:pull-request repo:${payload.repository.owner.login}/${payload.repository.name} commenter:${payload.sender.login}`, + per_page: 2, + }); + if (response_issue.data.total_count + response_pr.data.total_count === 1) { //continue_first_search + const data = response_issue.data.total_count > 0 ? response_issue.data : response_pr.data; const resp = await context.octokit.rest.issues.listComments({ - issue_number: response.data.items[0].number, + issue_number: data.items[0].number, owner: payload.repository.owner.login, repo: payload.repository.name, per_page: 100, From 2855d0bc61da6c3acfa9ca0d395af80e5bc4e7fe Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:53:37 +0100 Subject: [PATCH 44/88] fix: config extraction following extraction pattern --- src/handlers/comment/handlers/assign.ts | 3 ++- src/utils/helpers.ts | 11 +++++++++++ src/utils/private.ts | 3 ++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/handlers/comment/handlers/assign.ts b/src/handlers/comment/handlers/assign.ts index d3cf1ef41..31441f160 100644 --- a/src/handlers/comment/handlers/assign.ts +++ b/src/handlers/comment/handlers/assign.ts @@ -113,7 +113,8 @@ export const assign = async (body: string) => { } const days = Math.floor((new Date().getTime() - new Date(issue.created_at).getTime()) / (1000 * 60 * 60 * 24)); - const isBountyStale = staleBounty == 0 ? null : staleBounty > days ? false : true; + const staleToDays = Math.floor(staleBounty / (1000 * 60 * 60 * 24)); + const isBountyStale = staleBounty == 0 ? null : staleToDays > days ? false : true; // double check whether the assign message has been already posted or not logger.info(`Creating an issue comment: ${comment.commit}`); diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index e3965208b..46531df7c 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -183,3 +183,14 @@ export const getRegisterWalletWithVerification = ({ parsedRepo, parsedOrg, parse return Boolean(parsedDefault["register-wallet-with-verification"]); } }; + +// we use ms library so the value is a a string like "30d" which we convert to a number inside the business logic +export const getStaleBountyTime = ({ parsedRepo, parsedOrg, parsedDefault }: Configs): string => { + if (parsedRepo && parsedRepo["stale-bounty-time"] !== undefined && typeof parsedRepo["stale-bounty-time"] === "string") { + return parsedRepo["stale-bounty-time"]; + } else if (parsedOrg && parsedOrg["stale-bounty-time"] !== undefined && typeof parsedOrg["stale-bounty-time"] === "string") { + return parsedOrg["stale-bounty-time"]; + } else { + return parsedDefault["stale-bounty-time"] as string; + } +}; diff --git a/src/utils/private.ts b/src/utils/private.ts index 5adf2adc9..acdcb0665 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -18,6 +18,7 @@ import { getAssistivePricing, getCommandSettings, getRegisterWalletWithVerification, + getStaleBountyTime, } from "./helpers"; import DEFAULT_CONFIG_JSON from "../../ubiquibot-config-default.json"; @@ -185,7 +186,7 @@ export const getWideConfig = async (context: Context) => { defaultLabels: getDefaultLabels(configs), promotionComment: getPromotionComment(configs), registerWalletWithVerification: getRegisterWalletWithVerification(configs), - staleBountyTime: parsedDefault["stale-bounty-time"], + staleBountyTime: getStaleBountyTime(configs), }; return configData; From 5eb77097456e044c6334278c71dafd7696c76b11 Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Wed, 6 Sep 2023 06:02:07 +0000 Subject: [PATCH 45/88] feat: disable bot follow up for pending reviews --- src/handlers/wildcard/unassign.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/handlers/wildcard/unassign.ts b/src/handlers/wildcard/unassign.ts index 6d5feaaea..c75896c51 100644 --- a/src/handlers/wildcard/unassign.ts +++ b/src/handlers/wildcard/unassign.ts @@ -6,6 +6,7 @@ import { getAllIssueComments, getCommitsOnPullRequest, getOpenedPullRequestsForAnIssue, + getPullRequestReviews, listAllIssuesForRepo, removeAssignees, } from "../../helpers"; @@ -53,11 +54,7 @@ const checkBountyToUnassign = async (issue: Issue): Promise => { const passedDuration = curTimestamp - lastActivity.getTime(); const pullRequest = await getOpenedPullRequestsForAnIssue(issue.number, issue.assignee); - const { data: reviews } = await context.octokit.pulls.listReviews({ - owner: payload.repository.owner.login, - repo: payload.repository.name, - pull_number: pullRequest[0].id, - }); + const reviews = await getPullRequestReviews(context, pullRequest[0].id, 30, 1); const pendingReviews = reviews.filter((review) => review.state === "PENDING"); if (pendingReviews.length > 0) { From 9479e6255ef92277a95bc8e452559306b9c69b82 Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Wed, 6 Sep 2023 06:06:42 +0000 Subject: [PATCH 46/88] feat: display access levels in /query --- src/adapters/supabase/helpers/client.ts | 6 +++--- src/handlers/comment/handlers/query.ts | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/adapters/supabase/helpers/client.ts b/src/adapters/supabase/helpers/client.ts index 7e54f904f..427fc1a04 100644 --- a/src/adapters/supabase/helpers/client.ts +++ b/src/adapters/supabase/helpers/client.ts @@ -5,7 +5,7 @@ import { Database } from "../types"; import { InsertPermit, Permit } from "../../../helpers"; import { BigNumber, BigNumberish } from "ethers"; -interface accessLevels { +interface AccessLevels { multiplier: boolean; price: boolean; priority: boolean; @@ -347,7 +347,7 @@ export const getAccessLevel = async (username: string, repository: string, label return accessValues; }; -export const getAllAccessLevels = async (username: string, repository: string): Promise => { +export const getAllAccessLevels = async (username: string, repository: string): Promise => { const logger = getLogger(); const { supabase } = getAdapters(); @@ -356,7 +356,7 @@ export const getAllAccessLevels = async (username: string, repository: string): if (!data) { logger.info(`Access not found on the database`); // no access - return false; + return null; } return { multiplier: data["multiplier_access"], time: data["time_access"], priority: data["priority_access"], price: data["price_access"] }; }; diff --git a/src/handlers/comment/handlers/query.ts b/src/handlers/comment/handlers/query.ts index e75e255f4..74d37c8ce 100644 --- a/src/handlers/comment/handlers/query.ts +++ b/src/handlers/comment/handlers/query.ts @@ -26,7 +26,7 @@ export const query = async (body: string) => { if (user) { let data = await getAllAccessLevels(user, repo.full_name); - if (data === false) { + if (!data) { return `Error retrieving access for @${user}`; } const walletInfo = await getWalletInfo(user, id?.toString()); @@ -35,10 +35,10 @@ export const query = async (body: string) => { } else { return `@${user}'s wallet address is ${walletInfo?.address}, multiplier is ${walletInfo?.multiplier} and access levels are | access type | access level | -| multiplier | ${data["multiplier"]} | -| priority | ${data["priority"]} | -| time | ${data["time"]} | -| price | ${data["price"]} |`; +| multiplier | ${data.multiplier} | +| priority | ${data.priority} | +| time | ${data.time} | +| price | ${data.price} |`; } } else { logger.error("Invalid body for query command"); From ab87dd4f034ec35256b58408269558253e68ce02 Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Wed, 6 Sep 2023 06:08:25 +0000 Subject: [PATCH 47/88] feat: display access levels in /query --- src/handlers/comment/handlers/query.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handlers/comment/handlers/query.ts b/src/handlers/comment/handlers/query.ts index 74d37c8ce..3f5a9f0cf 100644 --- a/src/handlers/comment/handlers/query.ts +++ b/src/handlers/comment/handlers/query.ts @@ -1,4 +1,4 @@ -import { getAccessLevel, getAllAccessLevels, getWalletInfo } from "../../../adapters/supabase"; +import { getAllAccessLevels, getWalletInfo } from "../../../adapters/supabase"; import { getBotContext, getLogger } from "../../../bindings"; import { Payload } from "../../../types"; From 467d7ebd1def83cd2823dfa3069a7d09d1d462e2 Mon Sep 17 00:00:00 2001 From: ByteBallet Date: Wed, 6 Sep 2023 02:35:47 -0500 Subject: [PATCH 48/88] fix: update method for params --- src/handlers/comment/handlers/allow.ts | 38 ++++++-------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/src/handlers/comment/handlers/allow.ts b/src/handlers/comment/handlers/allow.ts index bc7e86d4c..aa867985c 100644 --- a/src/handlers/comment/handlers/allow.ts +++ b/src/handlers/comment/handlers/allow.ts @@ -20,40 +20,20 @@ export const setAccess = async (body: string) => { return; } - const regex = - /^\/allow (?:set-(\S+)\s@(\w+)\s(true|false)|set-(\S+)\s(true|false)\s@(\w+)|(true|false)\sset-(\S+)\s@(\w+)|(true|false)\s@(\w+)\sset-(\S+)|@(\w+)\s(true|false)\sset-(\S+)|@(\w+)\sset-(\S+)\s(true|false))$/; + const regex = /\/allow\s+(\S+)\s+(\S+)\s+(\S+)/; const matches = body.match(regex); if (matches) { let accessType, username, bool; - if (matches[1]) { - accessType = matches[1]; - username = matches[2]; - bool = matches[3]; - } else if (matches[4]) { - accessType = matches[4]; - bool = matches[5]; - username = matches[6]; - } else if (matches[7]) { - bool = matches[7]; - accessType = matches[8]; - username = matches[9]; - } else if (matches[10]) { - bool = matches[10]; - username = matches[11]; - accessType = matches[12]; - } else if (matches[13]) { - username = matches[13]; - bool = matches[14]; - accessType = matches[15]; - } else if (matches[16]) { - username = matches[16]; - accessType = matches[17]; - bool = matches[18]; - } else { - bool = username = accessType = ""; + matches.slice(1).forEach((part) => { + if (part.startsWith("@")) username = part.slice(1); + else if (part.startsWith("set-")) accessType = part.slice(4); + else if (part === "true" || part === "false") bool = part; + }); + if (!accessType || !username || !bool) { + logger.error("Invalid body for allow command"); + return `Invalid syntax for allow \n usage: '/allow set-(access type) @user true|false' \n ex-1 /allow set-multiplier @user false`; } - // Check if access control demand is valid if (!validAccessString.includes(accessType)) { logger.info(`Access control setting for ${accessType} does not exist.`); From edbbe97504315fc58b055977311f3ac5f45e1f6d Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 7 Sep 2023 09:12:13 +0100 Subject: [PATCH 49/88] fix: conditional removed null and storing time with number --- src/bindings/config.ts | 2 +- src/handlers/comment/handlers/assign.ts | 16 ++++++++++++---- src/handlers/comment/handlers/table.ts | 6 ++---- src/types/config.ts | 2 +- ubiquibot-config-default.json | 2 +- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/bindings/config.ts b/src/bindings/config.ts index b8f95fff7..94cc00301 100644 --- a/src/bindings/config.ts +++ b/src/bindings/config.ts @@ -91,7 +91,7 @@ export const loadConfig = async (context: Context): Promise => { command: commandSettings, assign: { bountyHunterMax: bountyHunterMax, - staleBountyTime: staleBountyTime ? String(ms(staleBountyTime)) : "0", + staleBountyTime: ms(staleBountyTime), }, sodium: { privateKey: process.env.X25519_PRIVATE_KEY ?? "", diff --git a/src/handlers/comment/handlers/assign.ts b/src/handlers/comment/handlers/assign.ts index 742335969..8fbf9920d 100644 --- a/src/handlers/comment/handlers/assign.ts +++ b/src/handlers/comment/handlers/assign.ts @@ -18,7 +18,7 @@ export const assign = async (body: string) => { const id = organization?.id || repository?.id; // repository?.id as fallback - const staleBounty = Number(config.assign.staleBountyTime); + const staleBounty = config.assign.staleBountyTime; logger.info(`Received '/start' command from user: ${payload.sender.login}, body: ${body}`); const issue = (_payload as Payload).issue; @@ -112,9 +112,17 @@ export const assign = async (body: string) => { await addAssignees(issue.number, [payload.sender.login]); } - const days = Math.floor((new Date().getTime() - new Date(issue.created_at).getTime()) / (1000 * 60 * 60 * 24)); - const staleToDays = Math.floor(staleBounty / (1000 * 60 * 60 * 24)); - const isBountyStale = staleBounty == 0 ? null : staleToDays > days ? false : true; + let days; + Number; + let staleToDays; + Number; + let isBountyStale = false; + + if (staleBounty !== 0) { + days = Math.floor((new Date().getTime() - new Date(issue.created_at).getTime()) / (1000 * 60 * 60 * 24)); + staleToDays = Math.floor(staleBounty / (1000 * 60 * 60 * 24)); + isBountyStale = staleToDays > days ? false : true; + } // double check whether the assign message has been already posted or not logger.info(`Creating an issue comment: ${comment.commit}`); diff --git a/src/handlers/comment/handlers/table.ts b/src/handlers/comment/handlers/table.ts index a130eb2c3..00093ce4e 100644 --- a/src/handlers/comment/handlers/table.ts +++ b/src/handlers/comment/handlers/table.ts @@ -12,16 +12,14 @@ export const tableComment = ({ multiplier?: string; reason?: string; bounty?: string; - isBountyStale?: boolean | null; + isBountyStale?: boolean; days?: number; }) => { return `
Ready to begin?You can start right away!This task was created over ${days} days ago. Please verify that it is still current before starting work.Warning! This task was created over ${days} days ago. Please confirm that this issue specification is accurate before starting.
Deadline ${deadline}
${ - isBountyStale == null - ? null - : isBountyStale + isBountyStale ? `` : `` } diff --git a/src/types/config.ts b/src/types/config.ts index aa297232f..f31954f17 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -69,7 +69,7 @@ export const ModeSchema = Type.Object({ export const AssignSchema = Type.Object({ bountyHunterMax: Type.Number(), - staleBountyTime: Type.String(), + staleBountyTime: Type.Number(), }); export const LogConfigSchema = Type.Object({ diff --git a/ubiquibot-config-default.json b/ubiquibot-config-default.json index a05e26020..eb9496538 100644 --- a/ubiquibot-config-default.json +++ b/ubiquibot-config-default.json @@ -8,7 +8,7 @@ "disable-analytics": false, "comment-incentives": false, "register-wallet-with-verification": false, - "stale-bounty-time": "30d", + "stale-bounty-time": "0d", "promotion-comment": "\n
If you enjoy the DevPool experience, please follow Ubiquity on GitHub and star this repo to show your support. It helps a lot!
", "default-labels": [], "time-labels": [ From 408a3d9e632752d03a1e9ab05a50f88eaea4bdef Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Thu, 7 Sep 2023 09:00:15 +0000 Subject: [PATCH 50/88] feat: display access level in /qurey --- src/handlers/comment/handlers/query.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/handlers/comment/handlers/query.ts b/src/handlers/comment/handlers/query.ts index 3f5a9f0cf..baf9467a4 100644 --- a/src/handlers/comment/handlers/query.ts +++ b/src/handlers/comment/handlers/query.ts @@ -25,7 +25,7 @@ export const query = async (body: string) => { const repo = payload.repository; if (user) { - let data = await getAllAccessLevels(user, repo.full_name); + const data = await getAllAccessLevels(user, repo.full_name); if (!data) { return `Error retrieving access for @${user}`; } @@ -35,10 +35,10 @@ export const query = async (body: string) => { } else { return `@${user}'s wallet address is ${walletInfo?.address}, multiplier is ${walletInfo?.multiplier} and access levels are | access type | access level | -| multiplier | ${data.multiplier} | -| priority | ${data.priority} | -| time | ${data.time} | -| price | ${data.price} |`; +| multiplier | ${data.multiplier} | +| priority | ${data.priority} | +| time | ${data.time} | +| price | ${data.price} |`; } } else { logger.error("Invalid body for query command"); From f3e557d85127af98254834b20f2cf95eaa40295b Mon Sep 17 00:00:00 2001 From: whilefoo <139262667+whilefoo@users.noreply.github.com> Date: Thu, 7 Sep 2023 10:59:40 +0200 Subject: [PATCH 51/88] fix: types --- src/handlers/comment/handlers/assign.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/handlers/comment/handlers/assign.ts b/src/handlers/comment/handlers/assign.ts index 8fbf9920d..e0a79c5ec 100644 --- a/src/handlers/comment/handlers/assign.ts +++ b/src/handlers/comment/handlers/assign.ts @@ -112,10 +112,8 @@ export const assign = async (body: string) => { await addAssignees(issue.number, [payload.sender.login]); } - let days; - Number; - let staleToDays; - Number; + let days: Number; + let staleToDays: Number; let isBountyStale = false; if (staleBounty !== 0) { From 5e67a76a1bded48465f0cc7ccda38604b0aaebce Mon Sep 17 00:00:00 2001 From: whilefoo <139262667+whilefoo@users.noreply.github.com> Date: Thu, 7 Sep 2023 11:05:15 +0200 Subject: [PATCH 52/88] fix: types and explicit
--- src/handlers/comment/handlers/assign.ts | 4 ++-- src/handlers/comment/handlers/table.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/handlers/comment/handlers/assign.ts b/src/handlers/comment/handlers/assign.ts index e0a79c5ec..2c9b57586 100644 --- a/src/handlers/comment/handlers/assign.ts +++ b/src/handlers/comment/handlers/assign.ts @@ -112,8 +112,8 @@ export const assign = async (body: string) => { await addAssignees(issue.number, [payload.sender.login]); } - let days: Number; - let staleToDays: Number; + let days: number | undefined; + let staleToDays: number | undefined; let isBountyStale = false; if (staleBounty !== 0) { diff --git a/src/handlers/comment/handlers/table.ts b/src/handlers/comment/handlers/table.ts index 00093ce4e..8f22d664f 100644 --- a/src/handlers/comment/handlers/table.ts +++ b/src/handlers/comment/handlers/table.ts @@ -20,7 +20,7 @@ export const tableComment = ({
Warning! This task was created over ${days} days ago. Please confirm that this issue specification is accurate before starting.
${ isBountyStale - ? `` + ? `` : `` } From e628f63abe7d3e740c12bf1d21af324c8a90a62d Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Thu, 7 Sep 2023 09:29:36 +0000 Subject: [PATCH 53/88] feat: display access level in /qurey --- src/handlers/comment/handlers/query.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/handlers/comment/handlers/query.ts b/src/handlers/comment/handlers/query.ts index baf9467a4..8f78c537f 100644 --- a/src/handlers/comment/handlers/query.ts +++ b/src/handlers/comment/handlers/query.ts @@ -34,11 +34,14 @@ export const query = async (body: string) => { return `Error retrieving multiplier and wallet address for @${user}`; } else { return `@${user}'s wallet address is ${walletInfo?.address}, multiplier is ${walletInfo?.multiplier} and access levels are -| access type | access level | -| multiplier | ${data.multiplier} | -| priority | ${data.priority} | -| time | ${data.time} | -| price | ${data.price} |`; + +| access type | access level | +| ----------- | ------------------- | +| multiplier | ${data.multiplier} | +| priority | ${data.priority} | +| time | ${data.time} | +| price | ${data.price} | + `; } } else { logger.error("Invalid body for query command"); From 747beccde04a29e09411062a9e24623862b624e9 Mon Sep 17 00:00:00 2001 From: whilefoo <139262667+whilefoo@users.noreply.github.com> Date: Thu, 7 Sep 2023 11:55:27 +0200 Subject: [PATCH 54/88] chore: refactor --- src/handlers/comment/handlers/assign.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handlers/comment/handlers/assign.ts b/src/handlers/comment/handlers/assign.ts index 2c9b57586..16dc69f9b 100644 --- a/src/handlers/comment/handlers/assign.ts +++ b/src/handlers/comment/handlers/assign.ts @@ -119,7 +119,7 @@ export const assign = async (body: string) => { if (staleBounty !== 0) { days = Math.floor((new Date().getTime() - new Date(issue.created_at).getTime()) / (1000 * 60 * 60 * 24)); staleToDays = Math.floor(staleBounty / (1000 * 60 * 60 * 24)); - isBountyStale = staleToDays > days ? false : true; + isBountyStale = days >= staleToDays; } // double check whether the assign message has been already posted or not From 08b7cc0c8864aa9370a267c961f6c5275578d11b Mon Sep 17 00:00:00 2001 From: whilefoo <139262667+whilefoo@users.noreply.github.com> Date: Thu, 7 Sep 2023 13:46:14 +0200 Subject: [PATCH 55/88] chore: refactor --- src/adapters/supabase/helpers/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/supabase/helpers/client.ts b/src/adapters/supabase/helpers/client.ts index 427fc1a04..eaa7d3d3f 100644 --- a/src/adapters/supabase/helpers/client.ts +++ b/src/adapters/supabase/helpers/client.ts @@ -358,7 +358,7 @@ export const getAllAccessLevels = async (username: string, repository: string): // no access return null; } - return { multiplier: data["multiplier_access"], time: data["time_access"], priority: data["priority_access"], price: data["price_access"] }; + return { multiplier: data.multiplier_access, time: data.time_access, priority: data.priority_access, price: data.price_access }; }; /** From d959564b332e99f57e1f2aad21718b7cad8234b7 Mon Sep 17 00:00:00 2001 From: me505 <62057938+me505@users.noreply.github.com> Date: Thu, 7 Sep 2023 12:23:17 +0000 Subject: [PATCH 56/88] chore: reword ot comment on issues not closed as completed --- src/handlers/payout/action.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/handlers/payout/action.ts b/src/handlers/payout/action.ts index 76503d662..237a374b6 100644 --- a/src/handlers/payout/action.ts +++ b/src/handlers/payout/action.ts @@ -98,8 +98,8 @@ export const handleIssueClosed = async () => { return "Permit generation skipped because wallet private key is not set"; } if (issue.state_reason !== StateReason.COMPLETED) { - logger.info("Permit generation skipped because the issue was not closed as completed"); - return "Permit generation skipped because the issue was not closed as completed"; + logger.info("Permit generation skipped because this is marked as unplanned."); + return "Permit generation skipped because this is marked as unplanned."; } logger.info(`Checking if the issue is a parent issue.`); From c02596b8bf37e9ed5189e166eceb4d8bc831adc1 Mon Sep 17 00:00:00 2001 From: 0xCodercrane <108444211+0xcodercrane@users.noreply.github.com> Date: Fri, 8 Sep 2023 10:05:02 +0800 Subject: [PATCH 57/88] chore: update src/adapters/supabase/helpers/client.ts --- src/adapters/supabase/helpers/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/supabase/helpers/client.ts b/src/adapters/supabase/helpers/client.ts index a833d40cc..cd1063d76 100644 --- a/src/adapters/supabase/helpers/client.ts +++ b/src/adapters/supabase/helpers/client.ts @@ -188,7 +188,7 @@ export const upsertWalletAddress = async (username: string, address: string): Pr logger.error(`Creating a new wallet_table record failed, error: ${JSON.stringify(error)}`); throw new Error(`Creating a new wallet_table record failed, error: ${JSON.stringify(error)}`); } - logger.info(`Creating a new wallet_table record done, { data: ${JSON.stringify(data)} }`); + logger.info(`Creating a new wallet_table record done, { data: ${JSON.stringify(data)}, address: $address }`); } }; From 4196f309256e20b79752fbec99603e6acbc9e161 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 8 Sep 2023 09:27:23 +0100 Subject: [PATCH 58/88] fix: skip zero penalty skips penalty and comment if zero --- src/handlers/comment/handlers/index.ts | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/handlers/comment/handlers/index.ts b/src/handlers/comment/handlers/index.ts index 5470b3062..eb02da55e 100644 --- a/src/handlers/comment/handlers/index.ts +++ b/src/handlers/comment/handlers/index.ts @@ -176,18 +176,22 @@ export const issueReopenedCallback = async (): Promise => { } const assignee = events[0].assignee.login; - // write penalty to db - try { - await addPenalty(assignee, repository.full_name, tokenAddress, networkId.toString(), amount); - } catch (err) { - logger.error(`Error writing penalty to db: ${err}`); - return; - } + if (formattedAmount != "0.0") { + // write penalty to db + try { + await addPenalty(assignee, repository.full_name, tokenAddress, networkId.toString(), amount); + } catch (err) { + logger.error(`Error writing penalty to db: ${err}`); + return; + } - await addCommentToIssue( - `@${assignee} please be sure to review this conversation and implement any necessary fixes. Unless this is closed as completed, its payment of **${formattedAmount} ${tokenSymbol}** will be deducted from your next bounty.`, - issue.number - ); + await addCommentToIssue( + `@${assignee} please be sure to review this conversation and implement any necessary fixes. Unless this is closed as completed, its payment of **${formattedAmount} ${tokenSymbol}** will be deducted from your next bounty.`, + issue.number + ); + } else { + logger.info(`Skipped penalty because amount is 0`); + } } catch (err: unknown) { await addCommentToIssue(`Error: ${err}`, issue.number); } From 0cbf1885fd04246f208cd4adf3958143213cc657 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 8 Sep 2023 09:37:06 +0100 Subject: [PATCH 59/88] fix: error diff commenting errors using diff --- src/handlers/comment/action.ts | 3 ++- src/handlers/comment/handlers/index.ts | 7 ++++--- src/utils/helpers.ts | 6 +++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/handlers/comment/action.ts b/src/handlers/comment/action.ts index 84c54e6d5..08f7ebefe 100644 --- a/src/handlers/comment/action.ts +++ b/src/handlers/comment/action.ts @@ -1,5 +1,6 @@ import { getBotConfig, getBotContext, getLogger } from "../../bindings"; import { Payload } from "../../types"; +import { ErrorDiff } from "../../utils/helpers"; import { IssueCommentCommands } from "./commands"; import { commentParser, userCommands } from "./handlers"; import { verifyFirstCheck } from "./handlers/first"; @@ -54,7 +55,7 @@ export const handleComment = async (): Promise => { if (failureComment) { await callback(issue.number, failureComment, payload.action, payload.comment); } - await callback(issue.number, `Error: ${err}`, payload.action, payload.comment); + await callback(issue.number, ErrorDiff(err), payload.action, payload.comment); } } else { logger.info(`Skipping for a command: ${command}`); diff --git a/src/handlers/comment/handlers/index.ts b/src/handlers/comment/handlers/index.ts index eb02da55e..9c4f3900b 100644 --- a/src/handlers/comment/handlers/index.ts +++ b/src/handlers/comment/handlers/index.ts @@ -27,6 +27,7 @@ import { handleIssueClosed } from "../../payout"; import { query } from "./query"; import { autoPay } from "./payout"; import { getTargetPriceLabel } from "../../shared"; +import { ErrorDiff } from "../../../utils/helpers"; export * from "./assign"; export * from "./wallet"; @@ -71,7 +72,7 @@ export const issueClosedCallback = async (): Promise => { const comment = await handleIssueClosed(); if (comment) await addCommentToIssue(comment + comments.promotionComment, issue.number); } catch (err: unknown) { - return await addCommentToIssue(`Error: ${err}`, issue.number); + return await addCommentToIssue(ErrorDiff(err), issue.number); } }; @@ -112,7 +113,7 @@ export const issueCreatedCallback = async (): Promise => { await addLabelToIssue(targetPriceLabel); } } catch (err: unknown) { - await addCommentToIssue(`Error: ${err}`, issue.number); + await addCommentToIssue(ErrorDiff(err), issue.number); } }; @@ -193,7 +194,7 @@ export const issueReopenedCallback = async (): Promise => { logger.info(`Skipped penalty because amount is 0`); } } catch (err: unknown) { - await addCommentToIssue(`Error: ${err}`, issue.number); + await addCommentToIssue(ErrorDiff(err), issue.number); } }; diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 33261629b..61949e6ca 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -19,4 +19,8 @@ export const getNumericLevel = (level: Level) => { default: return -1; // Invalid level } -}; \ No newline at end of file +}; + +export const ErrorDiff = (message: unknown) => { + return ` ` + "```diff \n" + `- ${message}` + "```" + ` `; +}; From e3529bbd3291d2ba82eac3620868470a64d3bfa3 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 8 Sep 2023 11:22:58 +0100 Subject: [PATCH 60/88] fix: rendering fixed --- src/utils/helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 61949e6ca..aa5a377ff 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -22,5 +22,5 @@ export const getNumericLevel = (level: Level) => { }; export const ErrorDiff = (message: unknown) => { - return ` ` + "```diff \n" + `- ${message}` + "```" + ` `; + return "```diff\n- " + message + "\n```"; }; From b1e72325fd883cddcfd8380e03487aefe2781745 Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Fri, 8 Sep 2023 10:32:24 +0000 Subject: [PATCH 61/88] feat: disable bot follow up if there are pending reviews --- src/handlers/wildcard/unassign.ts | 12 +++++++----- src/helpers/issue.ts | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/handlers/wildcard/unassign.ts b/src/handlers/wildcard/unassign.ts index c75896c51..a24a732cd 100644 --- a/src/handlers/wildcard/unassign.ts +++ b/src/handlers/wildcard/unassign.ts @@ -6,7 +6,7 @@ import { getAllIssueComments, getCommitsOnPullRequest, getOpenedPullRequestsForAnIssue, - getPullRequestReviews, + getAllReviewRequests, listAllIssuesForRepo, removeAssignees, } from "../../helpers"; @@ -54,10 +54,12 @@ const checkBountyToUnassign = async (issue: Issue): Promise => { const passedDuration = curTimestamp - lastActivity.getTime(); const pullRequest = await getOpenedPullRequestsForAnIssue(issue.number, issue.assignee); - const reviews = await getPullRequestReviews(context, pullRequest[0].id, 30, 1); - - const pendingReviews = reviews.filter((review) => review.state === "PENDING"); - if (pendingReviews.length > 0) { + const requestedReviewers = await getAllReviewRequests(context, pullRequest[0].id); + if (!requestedReviewers) { + logger.debug("Error: could not get requested reviewers"); + return false; + } + if (requestedReviewers.users?.length > 0) { return false; } if (passedDuration >= disqualifyTime || passedDuration >= followUpTime) { diff --git a/src/helpers/issue.ts b/src/helpers/issue.ts index 00ccd0e93..ca64cb423 100644 --- a/src/helpers/issue.ts +++ b/src/helpers/issue.ts @@ -532,6 +532,23 @@ export const getAllPullRequestReviews = async (context: Context, pull_number: nu return prArr; }; +export const getAllReviewRequests = async (context: Context, pull_number: number) => { + const payload = context.payload as Payload; + const response = await context.octokit.request("GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers", { + owner: payload.repository.owner.login, + repo: payload.repository.full_name, + pull_number: pull_number, + headers: { + "X-GitHub-Api-Version": "2022-11-28", + }, + }); + if (response.status === 200) { + return response.data; + } else { + return null; + } +}; + export const getPullRequestReviews = async (context: Context, pull_number: number, per_page: number, page: number) => { const logger = getLogger(); const payload = context.payload as Payload; From 54b1a8bfee5d78ad028e18583b9e377664226754 Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Fri, 8 Sep 2023 12:32:46 +0000 Subject: [PATCH 62/88] feat: disable bot reveiw on pending reviews --- src/handlers/wildcard/unassign.ts | 12 ++++++++---- src/helpers/issue.ts | 17 ----------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/src/handlers/wildcard/unassign.ts b/src/handlers/wildcard/unassign.ts index a24a732cd..d1946ca60 100644 --- a/src/handlers/wildcard/unassign.ts +++ b/src/handlers/wildcard/unassign.ts @@ -6,7 +6,6 @@ import { getAllIssueComments, getCommitsOnPullRequest, getOpenedPullRequestsForAnIssue, - getAllReviewRequests, listAllIssuesForRepo, removeAssignees, } from "../../helpers"; @@ -54,12 +53,17 @@ const checkBountyToUnassign = async (issue: Issue): Promise => { const passedDuration = curTimestamp - lastActivity.getTime(); const pullRequest = await getOpenedPullRequestsForAnIssue(issue.number, issue.assignee); - const requestedReviewers = await getAllReviewRequests(context, pullRequest[0].id); - if (!requestedReviewers) { + const response = await context.octokit.pulls.listRequestedReviewers({ + owner: payload.repository.owner.login, + repo: payload.repository.full_name, + pull_number: pullRequest[0].id, + }); + const data = response.status == 200 ? response.data : null; + if (!data) { logger.debug("Error: could not get requested reviewers"); return false; } - if (requestedReviewers.users?.length > 0) { + if (data.users?.length > 0) { return false; } if (passedDuration >= disqualifyTime || passedDuration >= followUpTime) { diff --git a/src/helpers/issue.ts b/src/helpers/issue.ts index ca64cb423..00ccd0e93 100644 --- a/src/helpers/issue.ts +++ b/src/helpers/issue.ts @@ -532,23 +532,6 @@ export const getAllPullRequestReviews = async (context: Context, pull_number: nu return prArr; }; -export const getAllReviewRequests = async (context: Context, pull_number: number) => { - const payload = context.payload as Payload; - const response = await context.octokit.request("GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers", { - owner: payload.repository.owner.login, - repo: payload.repository.full_name, - pull_number: pull_number, - headers: { - "X-GitHub-Api-Version": "2022-11-28", - }, - }); - if (response.status === 200) { - return response.data; - } else { - return null; - } -}; - export const getPullRequestReviews = async (context: Context, pull_number: number, per_page: number, page: number) => { const logger = getLogger(); const payload = context.payload as Payload; From 79e5f584cf24cf83776601564b86c3b0567a8957 Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Fri, 8 Sep 2023 14:33:08 +0000 Subject: [PATCH 63/88] feat: disable bot follow up on pending reviews --- src/handlers/wildcard/unassign.ts | 76 +++++++++++++++---------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/handlers/wildcard/unassign.ts b/src/handlers/wildcard/unassign.ts index d1946ca60..e57461eb9 100644 --- a/src/handlers/wildcard/unassign.ts +++ b/src/handlers/wildcard/unassign.ts @@ -52,49 +52,49 @@ const checkBountyToUnassign = async (issue: Issue): Promise => { const lastActivity = await lastActivityTime(issue, comments); const passedDuration = curTimestamp - lastActivity.getTime(); const pullRequest = await getOpenedPullRequestsForAnIssue(issue.number, issue.assignee); - - const response = await context.octokit.pulls.listRequestedReviewers({ - owner: payload.repository.owner.login, - repo: payload.repository.full_name, - pull_number: pullRequest[0].id, - }); - const data = response.status == 200 ? response.data : null; - if (!data) { - logger.debug("Error: could not get requested reviewers"); - return false; - } - if (data.users?.length > 0) { - return false; - } - if (passedDuration >= disqualifyTime || passedDuration >= followUpTime) { - if (passedDuration >= disqualifyTime) { - logger.info( - `Unassigning... lastActivityTime: ${lastActivity.getTime()}, curTime: ${curTimestamp}, passedDuration: ${passedDuration}, followUpTime: ${followUpTime}, disqualifyTime: ${disqualifyTime}` - ); - await closePullRequestForAnIssue(); - // remove assignees from the issue - await removeAssignees(issue.number, assignees); - await addCommentToIssue(`@${assignees[0]} - ${unassignComment} \nLast activity time: ${lastActivity}`, issue.number); - - return true; - } else if (passedDuration >= followUpTime) { - logger.info( - `Asking for updates... lastActivityTime: ${lastActivity.getTime()}, curTime: ${curTimestamp}, passedDuration: ${passedDuration}, followUpTime: ${followUpTime}, disqualifyTime: ${disqualifyTime}` - ); - - if (lastAskTime > lastActivity.getTime()) { + try { + const response = await context.octokit.pulls.listRequestedReviewers({ + owner: payload.repository.owner.login, + repo: payload.repository.full_name, + pull_number: pullRequest[0].id, + }); + const data = response.data; + if (data.users?.length > 0) { + return false; + } + if (passedDuration >= disqualifyTime || passedDuration >= followUpTime) { + if (passedDuration >= disqualifyTime) { logger.info( - `Skipping posting an update message cause its been already asked, lastAskTime: ${lastAskTime}, lastActivityTime: ${lastActivity.getTime()}` + `Unassigning... lastActivityTime: ${lastActivity.getTime()}, curTime: ${curTimestamp}, passedDuration: ${passedDuration}, followUpTime: ${followUpTime}, disqualifyTime: ${disqualifyTime}` ); - } else - await addCommentToIssue( - `${askUpdate} @${assignees[0]}? If you would like to release the bounty back to the DevPool, please comment \`/stop\` \nLast activity time: ${lastActivity}`, - issue.number + await closePullRequestForAnIssue(); + // remove assignees from the issue + await removeAssignees(issue.number, assignees); + await addCommentToIssue(`@${assignees[0]} - ${unassignComment} \nLast activity time: ${lastActivity}`, issue.number); + + return true; + } else if (passedDuration >= followUpTime) { + logger.info( + `Asking for updates... lastActivityTime: ${lastActivity.getTime()}, curTime: ${curTimestamp}, passedDuration: ${passedDuration}, followUpTime: ${followUpTime}, disqualifyTime: ${disqualifyTime}` ); + + if (lastAskTime > lastActivity.getTime()) { + logger.info( + `Skipping posting an update message cause its been already asked, lastAskTime: ${lastAskTime}, lastActivityTime: ${lastActivity.getTime()}` + ); + } else { + await addCommentToIssue( + `${askUpdate} @${assignees[0]}? If you would like to release the bounty back to the DevPool, please comment \`/stop\` \nLast activity time: ${lastActivity}`, + issue.number + ); + } + } } + return false; + } catch (e) { + logger.debug(`Error: could not get requested reviewers Error: ${e}`); + return false; } - - return false; }; const lastActivityTime = async (issue: Issue, comments: Comment[]): Promise => { From 683a68196ac865da28b3f82f019d586a70d3bb96 Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Fri, 8 Sep 2023 14:52:00 +0000 Subject: [PATCH 64/88] feat: disable bot follow up on pending reviews --- src/handlers/wildcard/unassign.ts | 69 ++++++++++++++----------------- src/helpers/issue.ts | 14 +++++++ 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/handlers/wildcard/unassign.ts b/src/handlers/wildcard/unassign.ts index e57461eb9..bed1bd4b3 100644 --- a/src/handlers/wildcard/unassign.ts +++ b/src/handlers/wildcard/unassign.ts @@ -6,6 +6,7 @@ import { getAllIssueComments, getCommitsOnPullRequest, getOpenedPullRequestsForAnIssue, + getReviewRequests, listAllIssuesForRepo, removeAssignees, } from "../../helpers"; @@ -52,49 +53,43 @@ const checkBountyToUnassign = async (issue: Issue): Promise => { const lastActivity = await lastActivityTime(issue, comments); const passedDuration = curTimestamp - lastActivity.getTime(); const pullRequest = await getOpenedPullRequestsForAnIssue(issue.number, issue.assignee); - try { - const response = await context.octokit.pulls.listRequestedReviewers({ - owner: payload.repository.owner.login, - repo: payload.repository.full_name, - pull_number: pullRequest[0].id, - }); - const data = response.data; - if (data.users?.length > 0) { - return false; - } - if (passedDuration >= disqualifyTime || passedDuration >= followUpTime) { - if (passedDuration >= disqualifyTime) { - logger.info( - `Unassigning... lastActivityTime: ${lastActivity.getTime()}, curTime: ${curTimestamp}, passedDuration: ${passedDuration}, followUpTime: ${followUpTime}, disqualifyTime: ${disqualifyTime}` - ); - await closePullRequestForAnIssue(); - // remove assignees from the issue - await removeAssignees(issue.number, assignees); - await addCommentToIssue(`@${assignees[0]} - ${unassignComment} \nLast activity time: ${lastActivity}`, issue.number); - return true; - } else if (passedDuration >= followUpTime) { + const response = await getReviewRequests(context, pullRequest[0].id, payload.repository.owner.login, payload.repository.full_name); + if (!response) return false; + + if (response.users?.length > 0) { + return false; + } + if (passedDuration >= disqualifyTime || passedDuration >= followUpTime) { + if (passedDuration >= disqualifyTime) { + logger.info( + `Unassigning... lastActivityTime: ${lastActivity.getTime()}, curTime: ${curTimestamp}, passedDuration: ${passedDuration}, followUpTime: ${followUpTime}, disqualifyTime: ${disqualifyTime}` + ); + await closePullRequestForAnIssue(); + // remove assignees from the issue + await removeAssignees(issue.number, assignees); + await addCommentToIssue(`@${assignees[0]} - ${unassignComment} \nLast activity time: ${lastActivity}`, issue.number); + + return true; + } else if (passedDuration >= followUpTime) { + logger.info( + `Asking for updates... lastActivityTime: ${lastActivity.getTime()}, curTime: ${curTimestamp}, passedDuration: ${passedDuration}, followUpTime: ${followUpTime}, disqualifyTime: ${disqualifyTime}` + ); + + if (lastAskTime > lastActivity.getTime()) { logger.info( - `Asking for updates... lastActivityTime: ${lastActivity.getTime()}, curTime: ${curTimestamp}, passedDuration: ${passedDuration}, followUpTime: ${followUpTime}, disqualifyTime: ${disqualifyTime}` + `Skipping posting an update message cause its been already asked, lastAskTime: ${lastAskTime}, lastActivityTime: ${lastActivity.getTime()}` + ); + } else { + await addCommentToIssue( + `${askUpdate} @${assignees[0]}? If you would like to release the bounty back to the DevPool, please comment \`/stop\` \nLast activity time: ${lastActivity}`, + issue.number ); - - if (lastAskTime > lastActivity.getTime()) { - logger.info( - `Skipping posting an update message cause its been already asked, lastAskTime: ${lastAskTime}, lastActivityTime: ${lastActivity.getTime()}` - ); - } else { - await addCommentToIssue( - `${askUpdate} @${assignees[0]}? If you would like to release the bounty back to the DevPool, please comment \`/stop\` \nLast activity time: ${lastActivity}`, - issue.number - ); - } } } - return false; - } catch (e) { - logger.debug(`Error: could not get requested reviewers Error: ${e}`); - return false; } + + return false; }; const lastActivityTime = async (issue: Issue, comments: Comment[]): Promise => { diff --git a/src/helpers/issue.ts b/src/helpers/issue.ts index 00ccd0e93..aff228675 100644 --- a/src/helpers/issue.ts +++ b/src/helpers/issue.ts @@ -550,6 +550,20 @@ export const getPullRequestReviews = async (context: Context, pull_number: numbe } }; +export const getReviewRequests = async (context: Context, pull_number: number, owner: string, repo: string) => { + const logger = getLogger(); + try { + const response = await context.octokit.pulls.listRequestedReviewers({ + owner: owner, + repo: repo, + pull_number: pull_number, + }); + return response.data; + } catch (e: unknown) { + logger.debug(`Error: could not get requested reviewers, reason: ${e}`); + return null; + } +}; // Get issues by issue number export const getIssueByNumber = async (context: Context, issue_number: number) => { const logger = getLogger(); From 1329f12fcb691077e9d71ea1f80d559c71a20687 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sat, 9 Sep 2023 08:52:24 +0100 Subject: [PATCH 65/88] fix: table comment fix table so no whitespace --- src/handlers/comment/handlers/table.ts | 31 +++++++++++++------------- ubiquibot-config-default.json | 6 ++--- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/handlers/comment/handlers/table.ts b/src/handlers/comment/handlers/table.ts index 8f22d664f..8299b6284 100644 --- a/src/handlers/comment/handlers/table.ts +++ b/src/handlers/comment/handlers/table.ts @@ -16,24 +16,23 @@ export const tableComment = ({ days?: number; }) => { return ` - -
Warning! This task was created over ${days} days ago. Please confirm that this issue specification is accurate before starting.
Warning! This task was created over ${days} days ago. Please confirm that this issue specification is accurate before starting.
+ + + + ${ isBountyStale - ? `` + ? `| Warning! | This task was created over ${days} days ago. Please confirm that this issue specification is accurate before starting. |\n |--|--|` : `` } - - - - - - - - - ${multiplier ? `` : ``} - ${reason ? `` : ``} - ${bounty ? `` : ``} -
Warning! This task was created over ${days} days ago. Please confirm that this issue specification is accurate before starting.
Deadline${deadline}
Registered Wallet${wallet}
Payment Multiplier${multiplier}
Multiplier Reason${reason}
Total Bounty${bounty}
-`; + ${!isBountyStale ? `| Deadline | ${deadline} |\n |--|--|` : `| Deadline | ${deadline} |`} + | Registered Wallet | ${wallet} | + ${multiplier ? `| Payment Multiplier | ${multiplier} |` : ``} + ${reason ? `| Multiplier Reason | ${reason} |` : ``} + ${bounty ? `| Total Bounty | ${bounty} |` : ``} + + + + +`; }; diff --git a/ubiquibot-config-default.json b/ubiquibot-config-default.json index eb9496538..9f3cfeae4 100644 --- a/ubiquibot-config-default.json +++ b/ubiquibot-config-default.json @@ -8,7 +8,7 @@ "disable-analytics": false, "comment-incentives": false, "register-wallet-with-verification": false, - "stale-bounty-time": "0d", + "stale-bounty-time": "15d", "promotion-comment": "\n
If you enjoy the DevPool experience, please follow Ubiquity on GitHub and star this repo to show your support. It helps a lot!
", "default-labels": [], "time-labels": [ @@ -48,11 +48,11 @@ "command-settings": [ { "name": "start", - "enabled": false + "enabled": true }, { "name": "stop", - "enabled": false + "enabled": true }, { "name": "wallet", From bc2c4fdab974a7b5b3cbaa35de52eaf3d565ad3d Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sat, 9 Sep 2023 08:53:15 +0100 Subject: [PATCH 66/88] fix: default set to false --- ubiquibot-config-default.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ubiquibot-config-default.json b/ubiquibot-config-default.json index 9f3cfeae4..eb9496538 100644 --- a/ubiquibot-config-default.json +++ b/ubiquibot-config-default.json @@ -8,7 +8,7 @@ "disable-analytics": false, "comment-incentives": false, "register-wallet-with-verification": false, - "stale-bounty-time": "15d", + "stale-bounty-time": "0d", "promotion-comment": "\n
If you enjoy the DevPool experience, please follow Ubiquity on GitHub and star this repo to show your support. It helps a lot!
", "default-labels": [], "time-labels": [ @@ -48,11 +48,11 @@ "command-settings": [ { "name": "start", - "enabled": true + "enabled": false }, { "name": "stop", - "enabled": true + "enabled": false }, { "name": "wallet", From 678551fa3c124b1a84a79749f47fa56399873459 Mon Sep 17 00:00:00 2001 From: EtherealGlow <139999816+EtherealGlow@users.noreply.github.com> Date: Sat, 9 Sep 2023 14:10:26 +0530 Subject: [PATCH 67/88] Update src/helpers/issue.ts Co-authored-by: whilefoo <139262667+whilefoo@users.noreply.github.com> --- src/helpers/issue.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/issue.ts b/src/helpers/issue.ts index aff228675..bb9c80c55 100644 --- a/src/helpers/issue.ts +++ b/src/helpers/issue.ts @@ -560,7 +560,7 @@ export const getReviewRequests = async (context: Context, pull_number: number, o }); return response.data; } catch (e: unknown) { - logger.debug(`Error: could not get requested reviewers, reason: ${e}`); + logger.error(`Error: could not get requested reviewers, reason: ${e}`); return null; } }; From 542c429e558eb88748f7739d0cbc562aaeea2eb9 Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Sat, 9 Sep 2023 08:45:49 +0000 Subject: [PATCH 68/88] feat: disable bot follow up on pending reviews --- src/handlers/wildcard/unassign.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/handlers/wildcard/unassign.ts b/src/handlers/wildcard/unassign.ts index bed1bd4b3..fa2788c2f 100644 --- a/src/handlers/wildcard/unassign.ts +++ b/src/handlers/wildcard/unassign.ts @@ -54,10 +54,8 @@ const checkBountyToUnassign = async (issue: Issue): Promise => { const passedDuration = curTimestamp - lastActivity.getTime(); const pullRequest = await getOpenedPullRequestsForAnIssue(issue.number, issue.assignee); - const response = await getReviewRequests(context, pullRequest[0].id, payload.repository.owner.login, payload.repository.full_name); - if (!response) return false; - - if (response.users?.length > 0) { + const reviewRequests = await getReviewRequests(context, pullRequest[0].id, payload.repository.owner.login, payload.repository.full_name); + if (!reviewRequests || reviewRequests.users?.length > 0) { return false; } if (passedDuration >= disqualifyTime || passedDuration >= followUpTime) { From d31ec44758c23e322194f171f715ca7c48bf3286 Mon Sep 17 00:00:00 2001 From: EtherealGlow Date: Sat, 9 Sep 2023 10:57:40 +0000 Subject: [PATCH 69/88] feat: disable bot follow up for pending reviews --- src/handlers/wildcard/unassign.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/handlers/wildcard/unassign.ts b/src/handlers/wildcard/unassign.ts index fa2788c2f..f71369b47 100644 --- a/src/handlers/wildcard/unassign.ts +++ b/src/handlers/wildcard/unassign.ts @@ -52,12 +52,15 @@ const checkBountyToUnassign = async (issue: Issue): Promise => { const curTimestamp = new Date().getTime(); const lastActivity = await lastActivityTime(issue, comments); const passedDuration = curTimestamp - lastActivity.getTime(); - const pullRequest = await getOpenedPullRequestsForAnIssue(issue.number, issue.assignee); + const pullRequest = await getOpenedPullRequestsForAnIssue(issue.number, issue.assignee.login); - const reviewRequests = await getReviewRequests(context, pullRequest[0].id, payload.repository.owner.login, payload.repository.full_name); - if (!reviewRequests || reviewRequests.users?.length > 0) { - return false; + if (pullRequest.length > 0) { + const reviewRequests = await getReviewRequests(context, pullRequest[0].number, payload.repository.owner.login, payload.repository.name); + if (!reviewRequests || reviewRequests.users?.length > 0) { + return false; + } } + if (passedDuration >= disqualifyTime || passedDuration >= followUpTime) { if (passedDuration >= disqualifyTime) { logger.info( From 9f398e6322cceecc07758eb67a5be3a34b2907cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=83=AC=E3=82=AF=E3=82=B5=E3=83=B3=E3=83=80?= =?UTF-8?q?=E3=83=BC=2Eeth?= <4975670+pavlovcik@users.noreply.github.com> Date: Sun, 10 Sep 2023 21:16:23 +0900 Subject: [PATCH 70/88] Update ubiquibot-config.yml --- .github/ubiquibot-config.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/ubiquibot-config.yml b/.github/ubiquibot-config.yml index 609d52ba1..336f1f1a4 100644 --- a/.github/ubiquibot-config.yml +++ b/.github/ubiquibot-config.yml @@ -1,4 +1 @@ -price-multiplier: 1.5 -default-labels: - - "Time: <1 Hour" - - "Priority: 1 (Normal)" +price-multiplier: 1.5 \ No newline at end of file From 5aa2908039deee6db44e8906518824c9713d0dc7 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun, 10 Sep 2023 18:31:28 +0100 Subject: [PATCH 71/88] fix: table and check parsing as float and removed whitespace from table --- src/handlers/comment/handlers/index.ts | 2 +- src/handlers/comment/handlers/table.ts | 38 +++++++++++++------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/handlers/comment/handlers/index.ts b/src/handlers/comment/handlers/index.ts index 9c4f3900b..3a58979a1 100644 --- a/src/handlers/comment/handlers/index.ts +++ b/src/handlers/comment/handlers/index.ts @@ -177,7 +177,7 @@ export const issueReopenedCallback = async (): Promise => { } const assignee = events[0].assignee.login; - if (formattedAmount != "0.0") { + if (parseFloat(formattedAmount) > 0) { // write penalty to db try { await addPenalty(assignee, repository.full_name, tokenAddress, networkId.toString(), amount); diff --git a/src/handlers/comment/handlers/table.ts b/src/handlers/comment/handlers/table.ts index 8299b6284..97f154e0b 100644 --- a/src/handlers/comment/handlers/table.ts +++ b/src/handlers/comment/handlers/table.ts @@ -16,23 +16,23 @@ export const tableComment = ({ days?: number; }) => { return ` - - - - - ${ - isBountyStale - ? `| Warning! | This task was created over ${days} days ago. Please confirm that this issue specification is accurate before starting. |\n |--|--|` - : `` - } - ${!isBountyStale ? `| Deadline | ${deadline} |\n |--|--|` : `| Deadline | ${deadline} |`} - | Registered Wallet | ${wallet} | - ${multiplier ? `| Payment Multiplier | ${multiplier} |` : ``} - ${reason ? `| Multiplier Reason | ${reason} |` : ``} - ${bounty ? `| Total Bounty | ${bounty} |` : ``} - - - - -`; + + +${ + isBountyStale + ? `` + : `` +} + + + + + + + + +${multiplier ? `` : ``} +${reason ? `` : ``} +${bounty ? `` : ``} +
Warning! This task was created over ${days} days ago. Please confirm that this issue specification is accurate before starting.
Deadline${deadline}
Registered Wallet${wallet}
Payment Multiplier${multiplier}
Multiplier Reason${reason}
Total Bounty${bounty}
`; }; From a60a0173b411fedabb69f6d2888fbef1f4a848f3 Mon Sep 17 00:00:00 2001 From: Wholesomebruh <109906215+Wholesomebruh@users.noreply.github.com> Date: Sun, 10 Sep 2023 23:13:39 +0530 Subject: [PATCH 72/88] Fix : skipped->disabled , since -> because --- src/handlers/comment/action.ts | 4 +-- src/handlers/comment/handlers/assign.ts | 2 +- src/handlers/comment/handlers/index.ts | 2 +- src/handlers/payout/action.ts | 38 ++++++++++++------------- src/handlers/payout/post.ts | 4 +-- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/handlers/comment/action.ts b/src/handlers/comment/action.ts index 84c54e6d5..5341aed76 100644 --- a/src/handlers/comment/action.ts +++ b/src/handlers/comment/action.ts @@ -40,8 +40,8 @@ export const handleComment = async (): Promise => { const feature = config.command.find((e) => e.name === id.split("/")[1]); if (!feature?.enabled && id !== IssueCommentCommands.HELP) { - logger.info(`Skipping '${id}' because it is disabled on this repo`); - await callback(issue.number, `Skipping \`${id}\` because it is disabled on this repo`, payload.action, payload.comment); + logger.info(`Skipping '${id}' because it is disabled on this repo.`); + await callback(issue.number, `Skipping \`${id}\` because it is disabled on this repo.`, payload.action, payload.comment); continue; } diff --git a/src/handlers/comment/handlers/assign.ts b/src/handlers/comment/handlers/assign.ts index 16dc69f9b..e50831a64 100644 --- a/src/handlers/comment/handlers/assign.ts +++ b/src/handlers/comment/handlers/assign.ts @@ -152,7 +152,7 @@ const getMultiplierInfoToDisplay = async (senderLogin: string, org_id: string, i } else { _multiplierToDisplay = multiplier; _reasonToDisplay = reason; - _bountyToDisplay = `Permit generation skipped since price label is not set`; + _bountyToDisplay = `Permit generation disabled because price label is not set.`; const issueDetailed = bountyInfo(issue); if (issueDetailed.priceLabel) { _bountyToDisplay = (+issueDetailed.priceLabel.substring(7, issueDetailed.priceLabel.length - 4) * value).toString() + " USD"; diff --git a/src/handlers/comment/handlers/index.ts b/src/handlers/comment/handlers/index.ts index 5470b3062..fea8fb943 100644 --- a/src/handlers/comment/handlers/index.ts +++ b/src/handlers/comment/handlers/index.ts @@ -90,7 +90,7 @@ export const issueCreatedCallback = async (): Promise => { const { assistivePricing } = config.mode; if (!assistivePricing) { - logger.info("Skipping adding label to issue because assistive pricing is disabled"); + logger.info("Skipping adding label to issue because assistive pricing is disabled."); return; } diff --git a/src/handlers/payout/action.ts b/src/handlers/payout/action.ts index 237a374b6..bd84daf13 100644 --- a/src/handlers/payout/action.ts +++ b/src/handlers/payout/action.ts @@ -39,7 +39,7 @@ export const handleIssueClosed = async () => { if (accessControl.organization) { const userHasPermission = await checkUserPermissionForRepoAndOrg(payload.sender.login, context); - if (!userHasPermission) return "Permit generation skipped because this issue has been closed by an external contributor."; + if (!userHasPermission) return "Permit generation disabled because this issue has been closed by an external contributor."; } const comments = await getAllIssueComments(issue.number); @@ -94,19 +94,19 @@ export const handleIssueClosed = async () => { return; } if (privateKey == "") { - logger.info("Permit generation skipped because wallet private key is not set"); - return "Permit generation skipped because wallet private key is not set"; + logger.info("Permit generation disabled because wallet private key is not set."); + return "Permit generation disabled because wallet private key is not set."; } if (issue.state_reason !== StateReason.COMPLETED) { - logger.info("Permit generation skipped because this is marked as unplanned."); - return "Permit generation skipped because this is marked as unplanned."; + logger.info("Permit generation disabled because this is marked as unplanned."); + return "Permit generation disabled because this is marked as unplanned."; } logger.info(`Checking if the issue is a parent issue.`); if (issue.body && isParentIssue(issue.body)) { - logger.error("Permit generation skipped since the issue is identified as parent issue."); + logger.error("Permit generation disabled because this is a collection of issues."); await clearAllPriceLabelsOnIssue(); - return "Permit generation skipped since the issue is identified as parent issue."; + return "Permit generation disabled because this is a collection of issues."; } logger.info(`Handling issues.closed event, issue: ${issue.number}`); @@ -118,7 +118,7 @@ export const handleIssueClosed = async () => { if (res) { if (res[1] === "false") { logger.info(`Skipping to generate permit2 url, reason: autoPayMode for this issue: false`); - return `Permit generation skipped since automatic payment for this issue is disabled.`; + return `Permit generation disabled because automatic payment for this issue is disabled.`; } break; } @@ -127,25 +127,25 @@ export const handleIssueClosed = async () => { if (paymentPermitMaxPrice == 0 || !paymentPermitMaxPrice) { logger.info(`Skipping to generate permit2 url, reason: { paymentPermitMaxPrice: ${paymentPermitMaxPrice}}`); - return `Permit generation skipped since paymentPermitMaxPrice is 0`; + return `Permit generation disabled because paymentPermitMaxPrice is 0.`; } const issueDetailed = bountyInfo(issue); if (!issueDetailed.isBounty) { - logger.info(`Skipping... its not a bounty`); - return `Permit generation skipped since this issue didn't qualify as bounty`; + logger.info(`Skipping... its not a bounty.`); + return `Permit generation disabled because this issue didn't qualify as bounty.`; } const assignees = issue?.assignees ?? []; const assignee = assignees.length > 0 ? assignees[0] : undefined; if (!assignee) { - logger.info("Skipping to proceed the payment because `assignee` is undefined"); - return `Permit generation skipped since assignee is undefined`; + logger.info("Skipping to proceed the payment because `assignee` is undefined."); + return `Permit generation disabled because assignee is undefined.`; } if (!issueDetailed.priceLabel) { logger.info("Skipping to proceed the payment because price not set"); - return `Permit generation skipped since price label is not set`; + return `Permit generation disabled because price label is not set.`; } const recipient = await getWalletAddress(assignee.login); @@ -164,8 +164,8 @@ export const handleIssueClosed = async () => { let priceInEth = new Decimal(issueDetailed.priceLabel.substring(7, issueDetailed.priceLabel.length - 4)).mul(multiplier); if (priceInEth.gt(paymentPermitMaxPrice)) { - logger.info("Skipping to proceed the payment because bounty payout is higher than paymentPermitMaxPrice"); - return `Permit generation skipped since issue's bounty is higher than ${paymentPermitMaxPrice}`; + logger.info("Skipping to proceed the payment because bounty payout is higher than paymentPermitMaxPrice."); + return `Permit generation disabled because issue's bounty is higher than ${paymentPermitMaxPrice}.`; } // if bounty hunter has any penalty then deduct it from the bounty @@ -176,7 +176,7 @@ export const handleIssueClosed = async () => { const bountyAmountAfterPenalty = bountyAmount.sub(penaltyAmount); if (bountyAmountAfterPenalty.lte(0)) { await removePenalty(assignee.login, payload.repository.full_name, paymentToken, networkId.toString(), bountyAmount); - const msg = `Permit generation skipped because bounty amount after penalty is 0`; + const msg = `Permit generation disabled because bounty amount after penalty is 0.`; logger.info(msg); return msg; } @@ -191,8 +191,8 @@ export const handleIssueClosed = async () => { `#### Task Assignee Reward\n### [ **[ CLAIM ${priceInEth} ${tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n` + "```" + shortenRecipient + "```"; const permitComments = comments.filter((content) => content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot); if (permitComments.length > 0) { - logger.info(`Skip to generate a permit url because it has been already posted`); - return `Permit generation skipped because it was already posted to this issue.`; + logger.info(`Skip to generate a permit url because it has been already posted.`); + return `Permit generation disabled because it was already posted to this issue.`; } await deleteLabel(issueDetailed.priceLabel); await addLabelToIssue("Permitted"); diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index 371c3d68a..eb321dcc6 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -31,7 +31,7 @@ export const incentivizeComments = async () => { } if (issue.state_reason !== StateReason.COMPLETED) { - logger.info("incentivizeComments: comment incentives skipped because the issue was not closed as completed"); + logger.info("incentivizeComments: comment incentives disabled because the issue was not closed as completed."); return; } @@ -143,7 +143,7 @@ export const incentivizeCreatorComment = async () => { } if (issue.state_reason !== StateReason.COMPLETED) { - logger.info("incentivizeCreatorComment: comment incentives skipped because the issue was not closed as completed"); + logger.info("incentivizeCreatorComment: comment incentives disabled because the issue was not closed as completed."); return; } From 4e8158433abc71bb9e4e1c9f24a0fc0b12962214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=83=AC=E3=82=AF=E3=82=B5=E3=83=B3=E3=83=80?= =?UTF-8?q?=E3=83=BC=2Eeth?= <4975670+pavlovcik@users.noreply.github.com> Date: Mon, 11 Sep 2023 17:48:52 +0900 Subject: [PATCH 73/88] Update pull_request_template.md --- .github/pull_request_template.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 9d7bbd50f..5804d2b1e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,7 +1,10 @@ -Resolves # - - + +Resolves # +QA: From 7a42059ff55f9ff21d654c314416896cf91c03f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=83=AC=E3=82=AF=E3=82=B5=E3=83=B3=E3=83=80?= =?UTF-8?q?=E3=83=BC=2Eeth?= <4975670+pavlovcik@users.noreply.github.com> Date: Mon, 11 Sep 2023 17:50:38 +0900 Subject: [PATCH 74/88] Update pull_request_template.md --- .github/pull_request_template.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 5804d2b1e..b1b688448 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,10 +1,11 @@ Resolves # -QA: + +Quality Assurance: From c6b6709b5af1447dddcb5a9ab231f00fcd16d33e Mon Sep 17 00:00:00 2001 From: HARALD Date: Mon, 11 Sep 2023 22:48:51 -0400 Subject: [PATCH 75/88] feat: include comments on pr --- src/handlers/assign/auto.ts | 8 ++++---- src/handlers/payout/post.ts | 15 +++++++++++++++ src/helpers/parser.ts | 21 +++++++++++++-------- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/handlers/assign/auto.ts b/src/handlers/assign/auto.ts index 7c648b5e7..380b59983 100644 --- a/src/handlers/assign/auto.ts +++ b/src/handlers/assign/auto.ts @@ -18,14 +18,14 @@ export const checkPullRequests = async () => { // Loop through the pull requests and assign them to their respective issues if needed for (const pull of pulls) { - const pullRequestLinked = await gitLinkedIssueParser({ + const linkedIssue = await gitLinkedIssueParser({ owner: payload.repository.owner.login, repo: payload.repository.name, - issue_number: pull.number, + pull_number: pull.number, }); // if pullRequestLinked is empty, continue - if (pullRequestLinked == "" || !pull.user) { + if (linkedIssue == "" || !pull.user || !linkedIssue) { continue; } @@ -37,7 +37,7 @@ export const checkPullRequests = async () => { continue; } - const linkedIssueNumber = pullRequestLinked.substring(pullRequestLinked.lastIndexOf("/") + 1); + const linkedIssueNumber = linkedIssue.substring(linkedIssue.lastIndexOf("/") + 1); // Check if the pull request opener is assigned to the issue const opener = pull.user.login; diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index de2f1d3aa..e43f9d4c5 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -191,6 +191,7 @@ export const incentivizePullRequestReviews = async () => { } const prReviews = await getAllPullRequestReviews(context, linkedPullRequest.number, "full"); + const prComments = await getAllIssueComments(linkedPullRequest.number, "full"); logger.info(`Getting the PR reviews done. comments: ${JSON.stringify(prReviews)}`); const prReviewsByUser: Record = {}; for (const review of prReviews) { @@ -206,6 +207,20 @@ export const incentivizePullRequestReviews = async () => { } prReviewsByUser[user.login].comments.push(review.body_html); } + + for (const comment of prComments) { + const user = comment.user; + if (!user) continue; + if (user.type == UserType.Bot || user.login == assignee) continue; + if (!comment.body_html) { + logger.info(`incentivizePullRequestReviews: Skipping to parse the comment because body_html is undefined. comment: ${JSON.stringify(comment)}`); + continue; + } + if (!prReviewsByUser[user.login]) { + prReviewsByUser[user.login] = { id: user.node_id, comments: [] }; + } + prReviewsByUser[user.login].comments.push(comment.body_html); + } const tokenSymbol = await getTokenSymbol(paymentToken, rpc); logger.info(`incentivizePullRequestReviews: Filtering by the user type done. commentsByUser: ${JSON.stringify(prReviewsByUser)}`); diff --git a/src/helpers/parser.ts b/src/helpers/parser.ts index 82563657c..93d249404 100644 --- a/src/helpers/parser.ts +++ b/src/helpers/parser.ts @@ -1,7 +1,7 @@ import axios from "axios"; import { HTMLElement, parse } from "node-html-parser"; import { getPullByNumber } from "./issue"; -import { getBotContext } from "../bindings"; +import { getBotContext, getLogger } from "../bindings"; import { Payload } from "../types"; interface GitParser { @@ -29,7 +29,8 @@ export const gitIssueParser = async ({ owner, repo, issue_number }: GitParser): } }; -export const gitLinkedIssueParser = async ({ owner, repo, pull_number }: GitParser): Promise => { +export const gitLinkedIssueParser = async ({ owner, repo, pull_number }: GitParser) => { + const logger = getLogger(); try { const { data } = await axios.get(`https://github.com/${owner}/${repo}/pull/${pull_number}`); const dom = parse(data); @@ -37,17 +38,19 @@ export const gitLinkedIssueParser = async ({ owner, repo, pull_number }: GitPars const linkedIssues = devForm.querySelectorAll(".my-1"); if (linkedIssues.length === 0) { - return ""; + return null; } const issueUrl = linkedIssues[0].querySelector("a")?.attrs?.href || ""; return issueUrl; } catch (error) { - return ""; + logger.error(`${JSON.stringify(error)}`); + return null; } }; export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser) => { + const logger = getLogger(); try { const { data } = await axios.get(`https://github.com/${owner}/${repo}/issues/${issue_number}`); const context = getBotContext(); @@ -55,8 +58,8 @@ export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser const dom = parse(data); const devForm = dom.querySelector("[data-target='create-branch.developmentForm']") as HTMLElement; const linkedPRs = devForm.querySelectorAll(".my-1"); - if (linkedPRs.length === 0) return ""; - let linkedPullRequest; + if (linkedPRs.length === 0) return null; + let linkedPullRequest = null; for (const linkedPr of linkedPRs) { const prHref = linkedPr.querySelector("a")?.attrs?.href || ""; const parts = prHref.split("/"); @@ -65,7 +68,8 @@ export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser const repository = parts[parts.length - 3]; if (`${organization}/${repository}` !== payload.repository.full_name) continue; - const prNumber = prHref.substring(prHref.lastIndexOf("/") + 1); + const prNumber = parts[parts.length - 1]; + if (Number.isNaN(Number(prNumber))) return null; const pr = await getPullByNumber(context, Number(prNumber)); if (!pr || !pr.merged) continue; @@ -76,6 +80,7 @@ export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser } return linkedPullRequest; } catch (error) { - return ""; + logger.error(`${JSON.stringify(error)}`); + return null; } }; From 391453259f5d7c2ffbe359705c51df28ecf1d01c Mon Sep 17 00:00:00 2001 From: whilefoo Date: Tue, 12 Sep 2023 09:51:09 +0200 Subject: [PATCH 76/88] fix: add helpers back --- src/utils/helpers.ts | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/utils/helpers.ts diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts new file mode 100644 index 000000000..c7bad1b2c --- /dev/null +++ b/src/utils/helpers.ts @@ -0,0 +1,3 @@ +export const ErrorDiff = (message: unknown) => { + return "```diff\n- " + message + "\n```"; +}; From 6ca50a44edd1b32a65c3b4d75899a0a289fdcd37 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Tue, 12 Sep 2023 10:36:35 +0200 Subject: [PATCH 77/88] feat: issue creator multiplier should be optional --- src/types/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/config.ts b/src/types/config.ts index ab1699c93..c162ece1a 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -141,7 +141,7 @@ export const WideConfigSchema = Type.Object( { "evm-network-id": Type.Optional(Type.Number()), "price-multiplier": Type.Optional(Type.Number()), - "issue-creator-multiplier": Type.Number(), + "issue-creator-multiplier": Type.Optional(Type.Number()), "time-labels": Type.Optional(Type.Array(LabelItemSchema)), "priority-labels": Type.Optional(Type.Array(LabelItemSchema)), "payment-permit-max-price": Type.Optional(Type.Number()), From 0414bba322f11589d895556e9c7526e6db79809d Mon Sep 17 00:00:00 2001 From: FUTURE Date: Thu, 14 Sep 2023 10:08:08 +0200 Subject: [PATCH 78/88] feat: extract time duration with ms (#756) * feat: extract time duration with ms * feat: use regex --- src/helpers/shared.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/helpers/shared.ts b/src/helpers/shared.ts index f851c5220..86e1599eb 100644 --- a/src/helpers/shared.ts +++ b/src/helpers/shared.ts @@ -1,3 +1,4 @@ +import ms from "ms"; import { getBotContext } from "../bindings"; import { LabelItem, Payload, UserType } from "../types"; @@ -35,13 +36,11 @@ export const calculateWeight = (label: LabelItem | undefined): number => { export const calculateDuration = (label: LabelItem): number => { if (!label) return 0; - const matches = label.name.match(/\d+/); if (label.name.toLowerCase().includes("priority")) return 0; - const number = matches && matches.length > 0 ? parseInt(matches[0]) || 0 : 0; - if (label.name.toLowerCase().includes("minute")) return number * 60; - if (label.name.toLowerCase().includes("hour")) return number * 3600; - if (label.name.toLowerCase().includes("day")) return number * 86400; - if (label.name.toLowerCase().includes("week")) return number * 604800; - if (label.name.toLowerCase().includes("month")) return number * 2592000; - return 0; + + const pattern = /<(\d+\s\w+)/; + const result = label.name.match(pattern); + if (!result) return 0; + + return ms(result[1]) / 1000; }; From 0dfa52024f860b6323f8d001d257461c24312ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=83=AC=E3=82=AF=E3=82=B5=E3=83=B3=E3=83=80?= =?UTF-8?q?=E3=83=BC=2Eeth?= <4975670+pavlovcik@users.noreply.github.com> Date: Fri, 15 Sep 2023 03:58:18 +0900 Subject: [PATCH 79/88] Update config.yml --- .github/ISSUE_TEMPLATE/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 86f3b5e6b..2403ad576 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: true contact_links: - - name: Telegram Group Chat - url: https://t.me/UbiquityDAO/29891 - about: "Join us on Telegram!" + - name: UbiquiBot Development Group Chat + url: https://t.me/UbiquityDAO/31132 + about: "Live chat with us on Telegram!" From cf2c9be2b3ce88cc7d55979ec57700665265532d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A2=E3=83=AC=E3=82=AF=E3=82=B5=E3=83=B3=E3=83=80?= =?UTF-8?q?=E3=83=BC=2Eeth?= <4975670+pavlovcik@users.noreply.github.com> Date: Fri, 15 Sep 2023 04:01:43 +0900 Subject: [PATCH 80/88] Update bounty-template.yml --- .github/ISSUE_TEMPLATE/bounty-template.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bounty-template.yml b/.github/ISSUE_TEMPLATE/bounty-template.yml index eb78b826f..7e81ebf0c 100644 --- a/.github/ISSUE_TEMPLATE/bounty-template.yml +++ b/.github/ISSUE_TEMPLATE/bounty-template.yml @@ -1,18 +1,20 @@ name: "Bounty Proposal" description: Have a suggestion for how to improve UbiquiBot? Let us know! -title: "Bounty Proposal:" +title: "Bounty Proposal: " body: - type: markdown attributes: value: | ## Feature Request Form - Thank you for taking the time to file a feature request! Please let us know what you're trying to do, and how UbiquiBot can help. + Thank you for taking the time to file a feature request. + If you register your wallet address, you will be eligible for compensation if this is accepted! + Please let us know how we can improve the bot. - type: textarea attributes: label: Describe the background or context - description: Please let us know what inspired you to write this proposal. Backlinking to specific comments is usually sufficient context. + description: Please let us know what inspired you to write this proposal. Backlinking to specific comments on GitHub, and leaving a remark about how the bot should have interacted with it is usually sufficient context. validations: required: false @@ -22,3 +24,10 @@ body: description: A clear description of what you want to happen. Add any considered drawbacks. validations: required: true + + - type: textarea + attributes: + label: Remarks + description: Any closing remarks? + validations: + required: false From 53fc6ab3193d89c2ef391b2faf2b3e3ee6126103 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 18 Sep 2023 04:34:02 +0100 Subject: [PATCH 81/88] fix: use bot penalty (#749) * fix: use bot penalty uses bot penalty created at * fix: defaults set to false * fix: use reopen time vs using penalty comment * fix: future living implemented futures fix --- src/handlers/wildcard/unassign.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/handlers/wildcard/unassign.ts b/src/handlers/wildcard/unassign.ts index f71369b47..880c29974 100644 --- a/src/handlers/wildcard/unassign.ts +++ b/src/handlers/wildcard/unassign.ts @@ -10,7 +10,8 @@ import { listAllIssuesForRepo, removeAssignees, } from "../../helpers"; -import { Comment, Issue, IssueType, Payload } from "../../types"; +import { Comment, Issue, IssueType, Payload, UserType } from "../../types"; +import { deadLinePrefix } from "../shared"; /** * @dev Check out the bounties which haven't been completed within the initial timeline @@ -99,6 +100,11 @@ const lastActivityTime = async (issue: Issue, comments: Comment[]): Promise i.login); const activities: Date[] = [new Date(issue.created_at)]; + const lastAssignCommentOfHunter = comments + .filter((comment) => comment.user.type === UserType.Bot && comment.body.includes(assignees[0]) && comment.body.includes(deadLinePrefix)) + .sort((a: Comment, b: Comment) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()); + if (lastAssignCommentOfHunter.length > 0) activities.push(new Date(lastAssignCommentOfHunter[0].created_at)); + // get last comment on the issue const lastCommentsOfHunterForIssue = comments .filter((comment) => assignees.includes(comment.user.login)) From 82564f02642da988d9fa1f6c785358669f467985 Mon Sep 17 00:00:00 2001 From: Wholesomebruh <109906215+Wholesomebruh@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:30:57 +0530 Subject: [PATCH 82/88] fix: renamed default config file (#763) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix: renamed default config file * Fix: resolved changes * chore: update ubiquibot-config-default.ts Co-authored-by: アレクサンダー.eth <4975670+pavlovcik@users.noreply.github.com> * Update ubiquibot-config-default.ts as const / as read only isn't working * Fix: added default config to src --------- Co-authored-by: 0xCodercrane <108444211+0xcodercrane@users.noreply.github.com> Co-authored-by: アレクサンダー.eth <4975670+pavlovcik@users.noreply.github.com> --- README.md | 2 +- src/configs/index.ts | 1 + .../configs/ubiquibot-config-default.ts | 9 ++++++--- src/utils/private.ts | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) rename ubiquibot-config-default.json => src/configs/ubiquibot-config-default.ts (93%) diff --git a/README.md b/README.md index 4b38ed11d..e8d09c845 100644 --- a/README.md +++ b/README.md @@ -224,7 +224,7 @@ Bounty bot is built using the [probot](https://probot.github.io/) framework so i ├── utils A set of utility functions -## Default Config Notes (`ubiquibot-config-default.json`) +## Default Config Notes (`ubiquibot-config-default.ts`) We can't use a `jsonc` file due to limitations with Netlify. Here is a snippet of some values with notes next to them. diff --git a/src/configs/index.ts b/src/configs/index.ts index 6addb9b75..d6231b38f 100644 --- a/src/configs/index.ts +++ b/src/configs/index.ts @@ -1,3 +1,4 @@ export * from "./shared"; export * from "./strings"; export * from "./abis"; +export * from "./ubiquibot-config-default"; \ No newline at end of file diff --git a/ubiquibot-config-default.json b/src/configs/ubiquibot-config-default.ts similarity index 93% rename from ubiquibot-config-default.json rename to src/configs/ubiquibot-config-default.ts index eb9496538..d1d9b7ffd 100644 --- a/ubiquibot-config-default.json +++ b/src/configs/ubiquibot-config-default.ts @@ -1,4 +1,6 @@ -{ +import { MergedConfig } from "../types"; + +export const DefaultConfig : MergedConfig = { "evm-network-id": 100, "price-multiplier": 1, "issue-creator-multiplier": 2, @@ -8,7 +10,6 @@ "disable-analytics": false, "comment-incentives": false, "register-wallet-with-verification": false, - "stale-bounty-time": "0d", "promotion-comment": "\n
If you enjoy the DevPool experience, please follow Ubiquity on GitHub and star this repo to show your support. It helps a lot!
", "default-labels": [], "time-labels": [ @@ -90,5 +91,7 @@ "enable-access-control": { "label": false, "organization": true - } + }, + "stale-bounty-time":"0d" } + diff --git a/src/utils/private.ts b/src/utils/private.ts index 23f014e16..d0cb329c5 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -4,7 +4,7 @@ import { MergedConfig, Payload } from "../types"; import { Context } from "probot"; import merge from "lodash/merge"; -import DEFAULT_CONFIG_JSON from "../../ubiquibot-config-default.json"; +import { DefaultConfig } from "../configs"; import { validate } from "./ajv"; import { WideConfig, WideOrgConfig, WideRepoConfig, WideConfigSchema, WideOrgConfigSchema } from "../types"; @@ -126,7 +126,7 @@ export const getWideConfig = async (context: Context) => { throw new Error(`Invalid repo config: ${error}`); } } - const parsedDefault: MergedConfig = DEFAULT_CONFIG_JSON; + const parsedDefault: MergedConfig = DefaultConfig; const privateKeyDecrypted = parsedOrg && parsedOrg[KEY_NAME] ? await getPrivateKey(parsedOrg[KEY_NAME]) : undefined; const configs: MergedConfigs = { parsedDefault, parsedOrg, parsedRepo }; From 81669894775f17a09859aa188b7b188ad5d7999e Mon Sep 17 00:00:00 2001 From: Sadaf Ahmed <119438857+Sadaf-A@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:34:23 +0530 Subject: [PATCH 83/88] feat: parse Permit Url (#738) * feat(action): parsing the permitUrl to an URL object * refactor(action) : using permitBaseUrl from config * feat: use regex * fix(action): - removing unused import statement --------- Co-authored-by: 0xcodercrane <108444211+0xcodercrane@users.noreply.github.com> --- src/handlers/payout/action.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/handlers/payout/action.ts b/src/handlers/payout/action.ts index bd84daf13..49677a3cb 100644 --- a/src/handlers/payout/action.ts +++ b/src/handlers/payout/action.ts @@ -189,7 +189,12 @@ export const handleIssueClosed = async () => { logger.info(`Posting a payout url to the issue, url: ${payoutUrl}`); const comment = `#### Task Assignee Reward\n### [ **[ CLAIM ${priceInEth} ${tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n` + "```" + shortenRecipient + "```"; - const permitComments = comments.filter((content) => content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot); + const permitComments = comments.filter((content) => { + claimUrlRegex; + const permitUrlMatches = content.body.match(claimUrlRegex); + if (!permitUrlMatches || permitUrlMatches.length < 2) return false; + else return true; + }); if (permitComments.length > 0) { logger.info(`Skip to generate a permit url because it has been already posted.`); return `Permit generation disabled because it was already posted to this issue.`; From e734904e1a3b0c8fa0f4d9b29eca93eb25f9b6ac Mon Sep 17 00:00:00 2001 From: Seprintour <51956013+seprintour@users.noreply.github.com> Date: Tue, 19 Sep 2023 18:47:28 +0100 Subject: [PATCH 84/88] fix: close pr issues and stop running handlers twice (#728) * fix: close pr issues and stop running handlers twice * chore: remove unused * chore: remove unused * chore: check org and repo name * chore: refactor gitLinkedPrParser * chore: make pr parser generic * Update src/helpers/parser.ts Co-authored-by: whilefoo <139262667+whilefoo@users.noreply.github.com> * Update src/helpers/parser.ts Co-authored-by: whilefoo <139262667+whilefoo@users.noreply.github.com> * Update src/helpers/parser.ts Co-authored-by: whilefoo <139262667+whilefoo@users.noreply.github.com> * Update src/helpers/parser.ts Co-authored-by: whilefoo <139262667+whilefoo@users.noreply.github.com> * chore: whilefoo review refactor --------- Co-authored-by: whilefoo <139262667+whilefoo@users.noreply.github.com> --- src/handlers/assign/action.ts | 15 ++++-- src/handlers/payout/post.ts | 15 ++++-- src/handlers/wildcard/unassign.ts | 2 - src/helpers/parser.ts | 89 +++++++++++++++++-------------- yarn.lock | 19 ++++--- 5 files changed, 82 insertions(+), 58 deletions(-) diff --git a/src/handlers/assign/action.ts b/src/handlers/assign/action.ts index b42312a88..e0093de07 100644 --- a/src/handlers/assign/action.ts +++ b/src/handlers/assign/action.ts @@ -1,5 +1,6 @@ import { getBotConfig, getBotContext, getLogger } from "../../bindings"; -import { addCommentToIssue, closePullRequest, getOpenedPullRequestsForAnIssue, calculateWeight, calculateDuration } from "../../helpers"; +import { addCommentToIssue, closePullRequest, calculateWeight, calculateDuration } from "../../helpers"; +import { gitLinkedPrParser } from "../../helpers/parser"; import { Payload, LabelItem } from "../../types"; import { deadLinePrefix } from "../shared"; @@ -72,13 +73,19 @@ export const closePullRequestForAnIssue = async (): Promise => { const payload = context.payload as Payload; if (!payload.issue?.number) return; - const prs = await getOpenedPullRequestsForAnIssue(payload.issue.number, ""); + const prs = await gitLinkedPrParser({ + owner: payload.repository.owner.login, + repo: payload.repository.name, + issue_number: payload.issue.number, + }); + if (!prs.length) return; + logger.info(`Opened prs for this issue: ${JSON.stringify(prs)}`); let comment = `These linked pull requests are closed: `; for (let i = 0; i < prs.length; i++) { - await closePullRequest(prs[i].number); - comment += ` #${prs[i].number} `; + await closePullRequest(prs[i].prNumber); + comment += ` #${prs[i].prNumber} `; } await addCommentToIssue(comment, payload.issue.number); }; diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index e43f9d4c5..e2a903f55 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -9,7 +9,7 @@ import { getTokenSymbol, parseComments, } from "../../helpers"; -import { gitLinkedPrParser } from "../../helpers/parser"; +import { getLatestPullRequest, gitLinkedPrParser } from "../../helpers/parser"; import { Incentives, MarkdownItem, Payload, StateReason, UserType } from "../../types"; import { commentParser } from "../comment"; import Decimal from "decimal.js"; @@ -167,9 +167,14 @@ export const incentivizePullRequestReviews = async () => { return; } - const linkedPullRequest = await gitLinkedPrParser({ owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: issue.number }); + const linkedPullRequest = await gitLinkedPrParser({ + owner: payload.repository.owner.login, + repo: payload.repository.name, + issue_number: issue.number, + }); + const latestLinkedPullRequest = await getLatestPullRequest(linkedPullRequest); - if (!linkedPullRequest) { + if (!latestLinkedPullRequest) { logger.debug(`incentivizePullRequestReviews: No linked pull requests found`); return; } @@ -190,8 +195,8 @@ export const incentivizePullRequestReviews = async () => { return; } - const prReviews = await getAllPullRequestReviews(context, linkedPullRequest.number, "full"); - const prComments = await getAllIssueComments(linkedPullRequest.number, "full"); + const prReviews = await getAllPullRequestReviews(context, latestLinkedPullRequest.number, "full"); + const prComments = await getAllIssueComments(latestLinkedPullRequest.number, "full"); logger.info(`Getting the PR reviews done. comments: ${JSON.stringify(prReviews)}`); const prReviewsByUser: Record = {}; for (const review of prReviews) { diff --git a/src/handlers/wildcard/unassign.ts b/src/handlers/wildcard/unassign.ts index 880c29974..ec057ce73 100644 --- a/src/handlers/wildcard/unassign.ts +++ b/src/handlers/wildcard/unassign.ts @@ -1,4 +1,3 @@ -import { closePullRequestForAnIssue } from "../assign"; import { getBotConfig, getBotContext, getLogger } from "../../bindings"; import { GLOBAL_STRINGS } from "../../configs/strings"; import { @@ -67,7 +66,6 @@ const checkBountyToUnassign = async (issue: Issue): Promise => { logger.info( `Unassigning... lastActivityTime: ${lastActivity.getTime()}, curTime: ${curTimestamp}, passedDuration: ${passedDuration}, followUpTime: ${followUpTime}, disqualifyTime: ${disqualifyTime}` ); - await closePullRequestForAnIssue(); // remove assignees from the issue await removeAssignees(issue.number, assignees); await addCommentToIssue(`@${assignees[0]} - ${unassignComment} \nLast activity time: ${lastActivity}`, issue.number); diff --git a/src/helpers/parser.ts b/src/helpers/parser.ts index 93d249404..42821a5b5 100644 --- a/src/helpers/parser.ts +++ b/src/helpers/parser.ts @@ -2,7 +2,6 @@ import axios from "axios"; import { HTMLElement, parse } from "node-html-parser"; import { getPullByNumber } from "./issue"; import { getBotContext, getLogger } from "../bindings"; -import { Payload } from "../types"; interface GitParser { owner: string; @@ -11,23 +10,12 @@ interface GitParser { pull_number?: number; } -export const gitIssueParser = async ({ owner, repo, issue_number }: GitParser): Promise => { - try { - const { data } = await axios.get(`https://github.com/${owner}/${repo}/issues/${issue_number}`); - const dom = parse(data); - const devForm = dom.querySelector("[data-target='create-branch.developmentForm']") as HTMLElement; - const linkedPRs = devForm.querySelectorAll(".my-1"); - if (linkedPRs.length > 0) { - //has LinkedPRs - return true; - } else { - //no LinkedPRs - return false; - } - } catch (error) { - return true; - } -}; +export interface LinkedPR { + prOrganization: string; + prRepository: string; + prNumber: number; + prHref: string; +} export const gitLinkedIssueParser = async ({ owner, repo, pull_number }: GitParser) => { const logger = getLogger(); @@ -49,38 +37,57 @@ export const gitLinkedIssueParser = async ({ owner, repo, pull_number }: GitPars } }; -export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser) => { +export const gitLinkedPrParser = async ({ owner, repo, issue_number }: GitParser): Promise => { const logger = getLogger(); try { + const prData = []; const { data } = await axios.get(`https://github.com/${owner}/${repo}/issues/${issue_number}`); - const context = getBotContext(); - const payload = context.payload as Payload; const dom = parse(data); const devForm = dom.querySelector("[data-target='create-branch.developmentForm']") as HTMLElement; const linkedPRs = devForm.querySelectorAll(".my-1"); - if (linkedPRs.length === 0) return null; - let linkedPullRequest = null; + if (linkedPRs.length === 0) return []; + for (const linkedPr of linkedPRs) { - const prHref = linkedPr.querySelector("a")?.attrs?.href || ""; - const parts = prHref.split("/"); - // extract the organization name and repo name from the link:(e.g. "https://github.com/wannacfuture/ubiquibot/pull/5";) - const organization = parts[parts.length - 4]; - const repository = parts[parts.length - 3]; - - if (`${organization}/${repository}` !== payload.repository.full_name) continue; - const prNumber = parts[parts.length - 1]; - if (Number.isNaN(Number(prNumber))) return null; - const pr = await getPullByNumber(context, Number(prNumber)); - if (!pr || !pr.merged) continue; - - if (!linkedPullRequest) linkedPullRequest = pr; - else if (linkedPullRequest.merged_at && pr.merged_at && new Date(linkedPullRequest.merged_at) < new Date(pr.merged_at)) { - linkedPullRequest = pr; - } + const prUrl = linkedPr.querySelector("a")?.attrs?.href; + + if (!prUrl) continue; + + const parts = prUrl.split("/"); + + // check if array size is at least 4 + if (parts.length < 4) continue; + + // extract the organization name and repo name from the link:(e.g. " + const prOrganization = parts[parts.length - 4]; + const prRepository = parts[parts.length - 3]; + const prNumber = Number(parts[parts.length - 1]); + const prHref = `https://github.com${prUrl}`; + + if (`${prOrganization}/${prRepository}` !== `${owner}/${repo}`) continue; + + prData.push({ prOrganization, prRepository, prNumber, prHref }); } - return linkedPullRequest; + + return prData; } catch (error) { logger.error(`${JSON.stringify(error)}`); - return null; + return []; } }; + +export const getLatestPullRequest = async (prs: LinkedPR[]) => { + const context = getBotContext(); + let linkedPullRequest = null; + for (const _pr of prs) { + if (Number.isNaN(_pr.prNumber)) return null; + const pr = await getPullByNumber(context, _pr.prNumber); + if (!pr || !pr.merged) continue; + + if (!linkedPullRequest) linkedPullRequest = pr; + else if (linkedPullRequest.merged_at && pr.merged_at && new Date(linkedPullRequest.merged_at) < new Date(pr.merged_at)) { + linkedPullRequest = pr; + } + } + + return linkedPullRequest; +}; diff --git a/yarn.lock b/yarn.lock index 89f4cdf2c..68cf237fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2235,6 +2235,13 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== +"@types/parse5@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-7.0.0.tgz#8b412a0a4461c84d6280a372bfa8c57a418a06bd" + integrity sha512-f2SeAxumolBmhuR62vNGTsSAvdz/Oj0k682xNrcKJ4dmRnTPODB74j6CPoNPzBPTHsu7Y7W7u93Mgp8Ovo8vWw== + dependencies: + parse5 "*" + "@types/phoenix@^1.5.4": version "1.6.0" resolved "https://registry.yarnpkg.com/@types/phoenix/-/phoenix-1.6.0.tgz#eb7536259ee695646e75c4c7b0c9a857ea174781" @@ -6896,18 +6903,18 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse5@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== - -parse5@^7.1.2: +parse5@*, parse5@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== dependencies: entities "^4.4.0" +parse5@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" From dba8308779aa1ea74e5a98c227a5e92ae3307d9b Mon Sep 17 00:00:00 2001 From: me505 <62057938+me505@users.noreply.github.com> Date: Tue, 19 Sep 2023 23:23:23 +0530 Subject: [PATCH 85/88] feat: add repo specific wallet support (#747) * feat: add repo specific wallet support * feat: repo specific wallet support * feat: repo specific wallet support * feat: add repo specific wallet support --------- Co-authored-by: whilefoo <139262667+whilefoo@users.noreply.github.com> --- src/handlers/push/index.ts | 4 ++-- src/types/config.ts | 7 +------ src/utils/private.ts | 18 +++++++++++++----- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/handlers/push/index.ts b/src/handlers/push/index.ts index 66dac755f..340143439 100644 --- a/src/handlers/push/index.ts +++ b/src/handlers/push/index.ts @@ -1,6 +1,6 @@ import { getBotContext, getLogger } from "../../bindings"; import { createCommitComment, getFileContent } from "../../helpers"; -import { CommitsPayload, PushPayload, WideOrgConfigSchema } from "../../types"; +import { CommitsPayload, PushPayload, WideConfigSchema } from "../../types"; import { parseYAML } from "../../utils/private"; import { updateBaseRate } from "./update-base"; import { validate } from "../../utils/ajv"; @@ -87,7 +87,7 @@ export const validateConfigChange = async () => { if (configFileContent) { const decodedConfig = Buffer.from(configFileContent, "base64").toString(); const config = parseYAML(decodedConfig); - const { valid, error } = validate(WideOrgConfigSchema, config); + const { valid, error } = validate(WideConfigSchema, config); if (!valid) { await createCommitComment(`@${payload.sender.login} Config validation failed! ${error}`, commitSha, BASE_RATE_FILE); } diff --git a/src/types/config.ts b/src/types/config.ts index c162ece1a..b4dedf3d0 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -156,6 +156,7 @@ export const WideConfigSchema = Type.Object( "register-wallet-with-verification": Type.Optional(Type.Boolean()), "enable-access-control": Type.Optional(AccessControlSchema), "stale-bounty-time": Type.Optional(Type.String()), + "private-key-encrypted": Type.Optional(Type.String()), }, { additionalProperties: false, @@ -166,12 +167,6 @@ export type WideConfig = Static; export type WideRepoConfig = WideConfig; -export const WideOrgConfigSchema = Type.Composite([Type.Object({ "private-key-encrypted": Type.Optional(Type.String()) }), WideConfigSchema], { - additionalProperties: false, -}); - -export type WideOrgConfig = Static; - export const MergedConfigSchema = Type.Object({ "evm-network-id": Type.Number(), "price-multiplier": Type.Number(), diff --git a/src/utils/private.ts b/src/utils/private.ts index d0cb329c5..683a9014c 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -6,7 +6,7 @@ import merge from "lodash/merge"; import { DefaultConfig } from "../configs"; import { validate } from "./ajv"; -import { WideConfig, WideOrgConfig, WideRepoConfig, WideConfigSchema, WideOrgConfigSchema } from "../types"; +import { WideConfig, WideRepoConfig, WideConfigSchema } from "../types"; const CONFIG_REPO = "ubiquibot-config"; const CONFIG_PATH = ".github/ubiquibot-config.yml"; @@ -35,7 +35,7 @@ export const getConfigSuperset = async (context: Context, type: "org" | "repo", export interface MergedConfigs { parsedRepo: WideRepoConfig | undefined; - parsedOrg: WideOrgConfig | undefined; + parsedOrg: WideRepoConfig | undefined; parsedDefault: MergedConfig; } @@ -111,10 +111,10 @@ export const getWideConfig = async (context: Context) => { const orgConfig = await getConfigSuperset(context, "org", CONFIG_PATH); const repoConfig = await getConfigSuperset(context, "repo", CONFIG_PATH); - const parsedOrg: WideOrgConfig | undefined = parseYAML(orgConfig); + const parsedOrg: WideRepoConfig | undefined = parseYAML(orgConfig); if (parsedOrg) { - const { valid, error } = validate(WideOrgConfigSchema, parsedOrg); + const { valid, error } = validate(WideConfigSchema, parsedOrg); if (!valid) { throw new Error(`Invalid org config: ${error}`); } @@ -127,7 +127,15 @@ export const getWideConfig = async (context: Context) => { } } const parsedDefault: MergedConfig = DefaultConfig; - const privateKeyDecrypted = parsedOrg && parsedOrg[KEY_NAME] ? await getPrivateKey(parsedOrg[KEY_NAME]) : undefined; + + let privateKeyDecrypted; + if (parsedRepo && parsedRepo[KEY_NAME]) { + privateKeyDecrypted = await getPrivateKey(parsedRepo[KEY_NAME]); + } else if (parsedOrg && parsedOrg[KEY_NAME]) { + privateKeyDecrypted = await getPrivateKey(parsedOrg[KEY_NAME]); + } else { + privateKeyDecrypted = undefined; + } const configs: MergedConfigs = { parsedDefault, parsedOrg, parsedRepo }; const mergedConfigData: MergedConfig = mergeConfigs(configs); From 3966177ca39f387bdc30b5e559737be14a3f1b5b Mon Sep 17 00:00:00 2001 From: DevPanther <42383942+devpanther@users.noreply.github.com> Date: Thu, 21 Sep 2023 02:37:04 +0100 Subject: [PATCH 86/88] feat: bounty rewards consolidation (#714) * chore: move incentives to main handler * chore: setting up creator reward * chore: setting up commenter reward * chore: remove type string * fix: syntax errors * fix: make sure assignee cannot get comment rewards * fix: undefined for payout command * fix: add types to fix lodash error * fix: lint error on const * chore: refactor reward generation * fix: remove unused * chore: edit payout function * chore: edit payout function * chore: fix error from latest merge * chore: remove assetion and make camelcase * chore: remove all assertions * chore: fix reviews * chore: merge commenter and reviewer * chore: make interface for rewards user * chore: fix regexp error * fix: new merge issues --- src/handlers/comment/handlers/index.ts | 41 ++- src/handlers/comment/handlers/payout.ts | 20 +- src/handlers/payout/action.ts | 404 +++++++++++++++++++++--- src/handlers/payout/post.ts | 353 ++++++++------------- src/handlers/processors.ts | 3 +- src/helpers/permit.ts | 5 +- 6 files changed, 545 insertions(+), 281 deletions(-) diff --git a/src/handlers/comment/handlers/index.ts b/src/handlers/comment/handlers/index.ts index b8dfe8534..244e6a080 100644 --- a/src/handlers/comment/handlers/index.ts +++ b/src/handlers/comment/handlers/index.ts @@ -23,10 +23,18 @@ import { calculateWeight, } from "../../../helpers"; import { getBotConfig, getBotContext, getLogger } from "../../../bindings"; -import { handleIssueClosed } from "../../payout"; +import { + handleIssueClosed, + incentivesCalculation, + calculateIssueConversationReward, + calculateIssueCreatorReward, + calculateIssueAssigneeReward, + calculatePullRequestReviewsReward, +} from "../../payout"; import { query } from "./query"; import { autoPay } from "./payout"; import { getTargetPriceLabel } from "../../shared"; +import Decimal from "decimal.js"; import { ErrorDiff } from "../../../utils/helpers"; export * from "./assign"; @@ -37,6 +45,21 @@ export * from "./help"; export * from "./multiplier"; export * from "./query"; +export interface RewardsResponse { + error: string | null; + title?: string; + userId?: string; + username?: string; + reward?: { + account: string; + priceInEth: Decimal; + penaltyAmount: BigNumber; + user: string; + userId: string; + }[]; + fallbackReward?: Record; +} + /** * Parses the comment body and figure out the command name a user wants * @@ -65,12 +88,22 @@ export const commentParser = (body: string): IssueCommentCommands[] => { export const issueClosedCallback = async (): Promise => { const { payload: _payload } = getBotContext(); - const { comments } = getBotConfig(); const issue = (_payload as Payload).issue; if (!issue) return; try { - const comment = await handleIssueClosed(); - if (comment) await addCommentToIssue(comment + comments.promotionComment, issue.number); + // assign function incentivesCalculation to a variable + const calculateIncentives = await incentivesCalculation(); + + const creatorReward = await calculateIssueCreatorReward(calculateIncentives); + const assigneeReward = await calculateIssueAssigneeReward(calculateIncentives); + const conversationRewards = await calculateIssueConversationReward(calculateIncentives); + const pullRequestReviewersReward = await calculatePullRequestReviewsReward(calculateIncentives); + + const { error } = await handleIssueClosed(creatorReward, assigneeReward, conversationRewards, pullRequestReviewersReward, calculateIncentives); + + if (error) { + throw new Error(error); + } } catch (err: unknown) { return await addCommentToIssue(ErrorDiff(err), issue.number); } diff --git a/src/handlers/comment/handlers/payout.ts b/src/handlers/comment/handlers/payout.ts index 98ce9f9ae..d5aabc7d6 100644 --- a/src/handlers/comment/handlers/payout.ts +++ b/src/handlers/comment/handlers/payout.ts @@ -1,7 +1,14 @@ import { getBotContext, getLogger } from "../../../bindings"; import { Payload } from "../../../types"; import { IssueCommentCommands } from "../commands"; -import { handleIssueClosed } from "../../payout"; +import { + calculateIssueAssigneeReward, + calculateIssueConversationReward, + calculateIssueCreatorReward, + calculatePullRequestReviewsReward, + handleIssueClosed, + incentivesCalculation, +} from "../../payout"; import { getAllIssueComments, getUserPermission } from "../../../helpers"; import { GLOBAL_STRINGS } from "../../../configs"; @@ -38,8 +45,15 @@ export const payout = async (body: string) => { return; } - const response = await handleIssueClosed(); - return response; + // assign function incentivesCalculation to a variable + const calculateIncentives = await incentivesCalculation(); + + const creatorReward = await calculateIssueCreatorReward(calculateIncentives); + const assigneeReward = await calculateIssueAssigneeReward(calculateIncentives); + const conversationRewards = await calculateIssueConversationReward(calculateIncentives); + const pullRequestReviewersReward = await calculatePullRequestReviewsReward(calculateIncentives); + + return await handleIssueClosed(creatorReward, assigneeReward, conversationRewards, pullRequestReviewersReward, calculateIncentives); }; export const autoPay = async (body: string) => { diff --git a/src/handlers/payout/action.ts b/src/handlers/payout/action.ts index 49677a3cb..0afe9c424 100644 --- a/src/handlers/payout/action.ts +++ b/src/handlers/payout/action.ts @@ -12,19 +12,61 @@ import { savePermitToDB, wasIssueReopened, getAllIssueAssignEvents, + addCommentToIssue, } from "../../helpers"; -import { UserType, Payload, StateReason } from "../../types"; +import { UserType, Payload, StateReason, Comment, User, Incentives, Issue } from "../../types"; import { shortenEthAddress } from "../../utils"; import { bountyInfo } from "../wildcard"; import Decimal from "decimal.js"; import { GLOBAL_STRINGS } from "../../configs"; import { isParentIssue } from "../pricing"; +import { RewardsResponse } from "../comment"; +import { isEmpty } from "lodash"; -export const handleIssueClosed = async () => { +export interface IncentivesCalculationResult { + paymentToken: string; + rpc: string; + networkId: number; + privateKey: string; + paymentPermitMaxPrice: number; + baseMultiplier: number; + incentives: Incentives; + issueCreatorMultiplier: number; + recipient: string; + multiplier: number; + issue: Issue; + payload: Payload; + comments: Comment[]; + issueDetailed: { + isBounty: boolean; + timelabel: string; + priorityLabel: string; + priceLabel: string; + }; + assignee: User; + tokenSymbol: string; + claimUrlRegex: RegExp; +} + +export interface RewardByUser { + account: string; + priceInEth: Decimal; + userId: string | undefined; + issueId: string; + type: string | undefined; + user: string | undefined; +} + +/** + * Collect the information required for the permit generation and error handling + */ + +export const incentivesCalculation = async (): Promise => { const context = getBotContext(); const { payout: { paymentToken, rpc, permitBaseUrl, networkId, privateKey }, - mode: { paymentPermitMaxPrice }, + mode: { incentiveMode, paymentPermitMaxPrice }, + price: { incentives, issueCreatorMultiplier, baseMultiplier }, accessControl, } = getBotConfig(); const logger = getLogger(); @@ -34,12 +76,16 @@ export const handleIssueClosed = async () => { const id = organization?.id || repository?.id; // repository?.id as fallback - if (!issue) return; + if (!issue) { + throw new Error("Permit generation skipped because issue is undefined"); + } if (accessControl.organization) { const userHasPermission = await checkUserPermissionForRepoAndOrg(payload.sender.login, context); - if (!userHasPermission) return "Permit generation disabled because this issue has been closed by an external contributor."; + if (!userHasPermission) { + throw new Error("Permit generation disabled because this issue has been closed by an external contributor."); + } } const comments = await getAllIssueComments(issue.number); @@ -53,13 +99,13 @@ export const handleIssueClosed = async () => { const permitUrl = permitComment.body.match(claimUrlRegex); if (!permitUrl || permitUrl.length < 2) { logger.error(`Permit URL not found`); - return; + throw new Error("Permit generation skipped because permit URL not found"); } const url = new URL(permitUrl[1]); const claimBase64 = url.searchParams.get("claim"); if (!claimBase64) { logger.error(`Permit claim search parameter not found`); - return; + throw new Error("Permit generation skipped because permit claim search parameter not found"); } let networkId = url.searchParams.get("network"); if (!networkId) { @@ -70,7 +116,7 @@ export const handleIssueClosed = async () => { claim = JSON.parse(Buffer.from(claimBase64, "base64").toString("utf-8")); } catch (err: unknown) { logger.error(`${err}`); - return; + throw new Error("Permit generation skipped because permit claim is invalid"); } const amount = BigNumber.from(claim.permit.permitted.amount); const tokenAddress = claim.permit.permitted.token; @@ -79,7 +125,7 @@ export const handleIssueClosed = async () => { const events = await getAllIssueAssignEvents(issue.number); if (events.length === 0) { logger.error(`No assignment found`); - return; + throw new Error("Permit generation skipped because no assignment found"); } const assignee = events[0].assignee.login; @@ -87,26 +133,33 @@ export const handleIssueClosed = async () => { await removePenalty(assignee, payload.repository.full_name, tokenAddress, networkId, amount); } catch (err) { logger.error(`Failed to remove penalty: ${err}`); - return; + throw new Error("Permit generation skipped because failed to remove penalty"); } logger.info(`Penalty removed`); - return; + throw new Error("Permit generation skipped, penalty removed"); } + + if (!incentiveMode) { + logger.info(`No incentive mode. skipping to process`); + throw new Error("No incentive mode. skipping to process"); + } + if (privateKey == "") { logger.info("Permit generation disabled because wallet private key is not set."); - return "Permit generation disabled because wallet private key is not set."; + throw new Error("Permit generation disabled because wallet private key is not set."); } + if (issue.state_reason !== StateReason.COMPLETED) { logger.info("Permit generation disabled because this is marked as unplanned."); - return "Permit generation disabled because this is marked as unplanned."; + throw new Error("Permit generation disabled because this is marked as unplanned."); } logger.info(`Checking if the issue is a parent issue.`); if (issue.body && isParentIssue(issue.body)) { logger.error("Permit generation disabled because this is a collection of issues."); await clearAllPriceLabelsOnIssue(); - return "Permit generation disabled because this is a collection of issues."; + throw new Error("Permit generation disabled because this is a collection of issues."); } logger.info(`Handling issues.closed event, issue: ${issue.number}`); @@ -118,7 +171,7 @@ export const handleIssueClosed = async () => { if (res) { if (res[1] === "false") { logger.info(`Skipping to generate permit2 url, reason: autoPayMode for this issue: false`); - return `Permit generation disabled because automatic payment for this issue is disabled.`; + throw new Error(`Permit generation disabled because automatic payment for this issue is disabled.`); } break; } @@ -127,31 +180,36 @@ export const handleIssueClosed = async () => { if (paymentPermitMaxPrice == 0 || !paymentPermitMaxPrice) { logger.info(`Skipping to generate permit2 url, reason: { paymentPermitMaxPrice: ${paymentPermitMaxPrice}}`); - return `Permit generation disabled because paymentPermitMaxPrice is 0.`; + throw new Error(`Permit generation disabled because paymentPermitMaxPrice is 0.`); } const issueDetailed = bountyInfo(issue); if (!issueDetailed.isBounty) { - logger.info(`Skipping... its not a bounty.`); - return `Permit generation disabled because this issue didn't qualify as bounty.`; + logger.info(`Skipping... its not a bounty`); + throw new Error(`Permit generation disabled because this issue didn't qualify as bounty.`); + } + + if (!issueDetailed.priceLabel || !issueDetailed.priorityLabel || !issueDetailed.timelabel) { + logger.info(`Skipping... its not a bounty`); + throw new Error(`Permit generation disabled because this issue didn't qualify as bounty.`); } const assignees = issue?.assignees ?? []; const assignee = assignees.length > 0 ? assignees[0] : undefined; if (!assignee) { - logger.info("Skipping to proceed the payment because `assignee` is undefined."); - return `Permit generation disabled because assignee is undefined.`; + logger.info("Skipping to proceed the payment because `assignee` is undefined"); + throw new Error(`Permit generation disabled because assignee is undefined.`); } if (!issueDetailed.priceLabel) { logger.info("Skipping to proceed the payment because price not set"); - return `Permit generation disabled because price label is not set.`; + throw new Error(`Permit generation disabled because price label is not set.`); } const recipient = await getWalletAddress(assignee.login); if (!recipient || recipient?.trim() === "") { logger.info(`Recipient address is missing`); - return; + throw new Error(`Permit generation skipped because recipient address is missing`); } const { value: multiplier } = await getWalletMultiplier(assignee.login, id?.toString()); @@ -159,51 +217,295 @@ export const handleIssueClosed = async () => { if (multiplier === 0) { const errMsg = "Refusing to generate the payment permit because " + `@${assignee.login}` + "'s payment `multiplier` is `0`"; logger.info(errMsg); - return errMsg; + throw new Error(errMsg); } - let priceInEth = new Decimal(issueDetailed.priceLabel.substring(7, issueDetailed.priceLabel.length - 4)).mul(multiplier); - if (priceInEth.gt(paymentPermitMaxPrice)) { + const tokenSymbol = await getTokenSymbol(paymentToken, rpc); + + return { + paymentToken, + rpc, + networkId, + privateKey, + recipient, + multiplier, + paymentPermitMaxPrice, + baseMultiplier, + incentives, + issueCreatorMultiplier, + issue, + payload, + comments, + issueDetailed: { + isBounty: issueDetailed.isBounty, + timelabel: issueDetailed.timelabel, + priorityLabel: issueDetailed.priorityLabel, + priceLabel: issueDetailed.priceLabel, + }, + assignee, + tokenSymbol, + claimUrlRegex, + }; +}; + +/** + * Calculate the reward for the assignee + */ + +export const calculateIssueAssigneeReward = async (incentivesCalculation: IncentivesCalculationResult): Promise => { + const logger = getLogger(); + const assigneeLogin = incentivesCalculation.assignee.login; + + let priceInEth = new Decimal(incentivesCalculation.issueDetailed.priceLabel.substring(7, incentivesCalculation.issueDetailed.priceLabel.length - 4)).mul( + incentivesCalculation.multiplier + ); + if (priceInEth.gt(incentivesCalculation.paymentPermitMaxPrice)) { logger.info("Skipping to proceed the payment because bounty payout is higher than paymentPermitMaxPrice."); - return `Permit generation disabled because issue's bounty is higher than ${paymentPermitMaxPrice}.`; + return { error: `Permit generation disabled because issue's bounty is higher than ${incentivesCalculation.paymentPermitMaxPrice}` }; } // if bounty hunter has any penalty then deduct it from the bounty - const penaltyAmount = await getPenalty(assignee.login, payload.repository.full_name, paymentToken, networkId.toString()); + const penaltyAmount = await getPenalty( + assigneeLogin, + incentivesCalculation.payload.repository.full_name, + incentivesCalculation.paymentToken, + incentivesCalculation.networkId.toString() + ); if (penaltyAmount.gt(0)) { logger.info(`Deducting penalty from bounty`); const bountyAmount = ethers.utils.parseUnits(priceInEth.toString(), 18); const bountyAmountAfterPenalty = bountyAmount.sub(penaltyAmount); if (bountyAmountAfterPenalty.lte(0)) { - await removePenalty(assignee.login, payload.repository.full_name, paymentToken, networkId.toString(), bountyAmount); + await removePenalty( + assigneeLogin, + incentivesCalculation.payload.repository.full_name, + incentivesCalculation.paymentToken, + incentivesCalculation.networkId.toString(), + bountyAmount + ); const msg = `Permit generation disabled because bounty amount after penalty is 0.`; logger.info(msg); - return msg; + return { error: msg }; } priceInEth = new Decimal(ethers.utils.formatUnits(bountyAmountAfterPenalty, 18)); } - const { txData, payoutUrl } = await generatePermit2Signature(recipient, priceInEth, issue.node_id, assignee.node_id, "ISSUE_ASSIGNEE"); - const tokenSymbol = await getTokenSymbol(paymentToken, rpc); - const shortenRecipient = shortenEthAddress(recipient, `[ CLAIM ${priceInEth} ${tokenSymbol.toUpperCase()} ]`.length); - logger.info(`Posting a payout url to the issue, url: ${payoutUrl}`); - const comment = - `#### Task Assignee Reward\n### [ **[ CLAIM ${priceInEth} ${tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n` + "```" + shortenRecipient + "```"; - const permitComments = comments.filter((content) => { - claimUrlRegex; - const permitUrlMatches = content.body.match(claimUrlRegex); - if (!permitUrlMatches || permitUrlMatches.length < 2) return false; - else return true; - }); - if (permitComments.length > 0) { - logger.info(`Skip to generate a permit url because it has been already posted.`); - return `Permit generation disabled because it was already posted to this issue.`; - } - await deleteLabel(issueDetailed.priceLabel); - await addLabelToIssue("Permitted"); - await savePermitToDB(assignee.id, txData); - if (penaltyAmount.gt(0)) { - await removePenalty(assignee.login, payload.repository.full_name, paymentToken, networkId.toString(), penaltyAmount); + const account = await getWalletAddress(assigneeLogin); + + return { + error: "", + userId: incentivesCalculation.assignee.node_id, + username: assigneeLogin, + reward: [ + { + priceInEth, + penaltyAmount, + account: account || "0x", + user: "", + userId: "", + }, + ], + }; +}; + +export const handleIssueClosed = async ( + creatorReward: RewardsResponse, + assigneeReward: RewardsResponse, + conversationRewards: RewardsResponse, + pullRequestReviewersReward: RewardsResponse, + incentivesCalculation: IncentivesCalculationResult +): Promise<{ error: string }> => { + const logger = getLogger(); + const { comments } = getBotConfig(); + const issueNumber = incentivesCalculation.issue.number; + + let commentersComment = "", + title = "Task Assignee", + assigneeComment = "", + creatorComment = "", + mergedComment = "", + pullRequestReviewerComment = ""; + // The mapping between gh handle and comment with a permit url + const commentersReward: Record = {}; + const prReviewersReward: Record = {}; + + // Rewards by user + const rewardByUser: RewardByUser[] = []; + + // ASSIGNEE REWARD PRICE PROCESSOR + let priceInEth = new Decimal(incentivesCalculation.issueDetailed.priceLabel.substring(7, incentivesCalculation.issueDetailed.priceLabel.length - 4)).mul( + incentivesCalculation.multiplier + ); + if (priceInEth.gt(incentivesCalculation.paymentPermitMaxPrice)) { + logger.info("Skipping to proceed the payment because bounty payout is higher than paymentPermitMaxPrice"); + return { error: `Permit generation skipped since issue's bounty is higher than ${incentivesCalculation.paymentPermitMaxPrice}` }; + } + + // COMMENTERS REWARD HANDLER + if (conversationRewards.reward && conversationRewards.reward.length > 0) { + commentersComment = `#### ${conversationRewards.title} Rewards \n`; + + conversationRewards.reward.map(async (permit) => { + // Exclude issue creator from commenter rewards + if (permit.userId !== creatorReward.userId) { + rewardByUser.push({ + account: permit.account, + priceInEth: permit.priceInEth, + userId: permit.userId, + issueId: incentivesCalculation.issue.node_id, + type: conversationRewards.title, + user: permit.user, + }); + } + }); } - return comment; + + // PULL REQUEST REVIEWERS REWARD HANDLER + if (pullRequestReviewersReward.reward && pullRequestReviewersReward.reward.length > 0) { + pullRequestReviewerComment = `#### ${pullRequestReviewersReward.title} Rewards \n`; + + pullRequestReviewersReward.reward.map(async (permit) => { + // Exclude issue creator from commenter rewards + if (permit.userId !== creatorReward.userId) { + rewardByUser.push({ + account: permit.account, + priceInEth: permit.priceInEth, + userId: permit.userId, + issueId: incentivesCalculation.issue.node_id, + type: pullRequestReviewersReward.title, + user: permit.user, + }); + } + }); + } + + // CREATOR REWARD HANDLER + // Generate permit for user if its not the same id as assignee + if (creatorReward && creatorReward.reward && creatorReward.reward[0].account !== "0x" && creatorReward.userId !== incentivesCalculation.assignee.node_id) { + const { payoutUrl } = await generatePermit2Signature( + creatorReward.reward[0].account, + creatorReward.reward[0].priceInEth, + incentivesCalculation.issue.node_id, + creatorReward.userId + ); + + creatorComment = `#### ${creatorReward.title} Reward \n### [ **${creatorReward.username}: [ CLAIM ${ + creatorReward.reward[0].priceInEth + } ${incentivesCalculation.tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n`; + if (payoutUrl) { + logger.info(`Permit url generated for creator. reward: ${payoutUrl}`); + } + // Add amount to assignee if assignee is the creator + } else if ( + creatorReward && + creatorReward.reward && + creatorReward.reward[0].account !== "0x" && + creatorReward.userId === incentivesCalculation.assignee.node_id + ) { + priceInEth = priceInEth.add(creatorReward.reward[0].priceInEth); + title += " and Creator"; + } else if (creatorReward && creatorReward.reward && creatorReward.reward[0].account === "0x") { + logger.info(`Skipping to generate a permit url for missing account. fallback: ${creatorReward.fallbackReward}`); + } + + // ASSIGNEE REWARD HANDLER + if (assigneeReward && assigneeReward.reward && assigneeReward.reward[0].account !== "0x") { + const { txData, payoutUrl } = await generatePermit2Signature( + assigneeReward.reward[0].account, + assigneeReward.reward[0].priceInEth, + incentivesCalculation.issue.node_id, + incentivesCalculation.assignee.node_id + ); + const tokenSymbol = await getTokenSymbol(incentivesCalculation.paymentToken, incentivesCalculation.rpc); + const shortenRecipient = shortenEthAddress(assigneeReward.reward[0].account, `[ CLAIM ${priceInEth} ${tokenSymbol.toUpperCase()} ]`.length); + logger.info(`Posting a payout url to the issue, url: ${payoutUrl}`); + assigneeComment = + `#### ${title} Reward \n### [ **[ CLAIM ${priceInEth} ${tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n` + "```" + shortenRecipient + "```"; + const permitComments = incentivesCalculation.comments.filter((content) => { + const permitUrlMatches = content.body.match(incentivesCalculation.claimUrlRegex); + if (!permitUrlMatches || permitUrlMatches.length < 2) return false; + else return true; + }); + + if (permitComments.length > 0) { + logger.info(`Skip to generate a permit url because it has been already posted.`); + return { error: `Permit generation disabled because it was already posted to this issue.` }; + } + + if (assigneeReward.reward[0].penaltyAmount.gt(0)) { + await removePenalty( + incentivesCalculation.assignee.login, + incentivesCalculation.payload.repository.full_name, + incentivesCalculation.paymentToken, + incentivesCalculation.networkId.toString(), + assigneeReward.reward[0].penaltyAmount + ); + } + + await savePermitToDB(incentivesCalculation.assignee.id, txData); + } + + // MERGE ALL REWARDS + const rewards = rewardByUser.reduce((acc, curr) => { + const existing = acc.find((item) => item.userId === curr.userId); + if (existing) { + existing.priceInEth = existing.priceInEth.add(curr.priceInEth); + // merge type by adding comma and + existing.type = `${existing.type} and ${curr.type}`; + } else { + acc.push(curr); + } + return acc; + }, [] as RewardByUser[]); + + // CREATE PERMIT URL FOR EACH USER + for (const reward of rewards) { + const { payoutUrl } = await generatePermit2Signature(reward.account, reward.priceInEth, reward.issueId, reward.userId); + + if (!reward.user) { + logger.info(`Skipping to generate a permit url for missing user. fallback: ${reward.user}`); + continue; + } + + switch (reward.type) { + case "Conversation and Reviewer": + case "Reviewer and Conversation": + if (mergedComment === "") mergedComment = `#### ${reward.type} Rewards `; + mergedComment = `${mergedComment}\n### [ **${reward.user}: [ CLAIM ${ + reward.priceInEth + } ${incentivesCalculation.tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n`; + break; + case "Conversation": + commentersComment = `${commentersComment}\n### [ **${reward.user}: [ CLAIM ${ + reward.priceInEth + } ${incentivesCalculation.tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n`; + commentersReward[reward.user] = payoutUrl; + break; + case "Reviewer": + pullRequestReviewerComment = `${pullRequestReviewerComment}\n### [ **${reward.user}: [ CLAIM ${ + reward.priceInEth + } ${incentivesCalculation.tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n`; + prReviewersReward[reward.user] = payoutUrl; + break; + default: + break; + } + + logger.info(`Permit url generated for contributors. reward: ${JSON.stringify(commentersReward)}`); + logger.info(`Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(conversationRewards.fallbackReward)}`); + + logger.info(`Permit url generated for pull request reviewers. reward: ${JSON.stringify(prReviewersReward)}`); + logger.info(`Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(pullRequestReviewersReward.fallbackReward)}`); + } + + if (commentersComment && !isEmpty(commentersReward)) await addCommentToIssue(commentersComment, issueNumber); + if (creatorComment) await addCommentToIssue(creatorComment, issueNumber); + if (pullRequestReviewerComment && !isEmpty(prReviewersReward)) await addCommentToIssue(pullRequestReviewerComment, issueNumber); + if (mergedComment) await addCommentToIssue(mergedComment, issueNumber); + if (assigneeComment) await addCommentToIssue(assigneeComment + comments.promotionComment, issueNumber); + + await deleteLabel(incentivesCalculation.issueDetailed.priceLabel); + await addLabelToIssue("Permitted"); + + return { error: "" }; }; diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index e2a903f55..18d9aa1df 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -1,82 +1,58 @@ import { getWalletAddress } from "../../adapters/supabase"; -import { getBotConfig, getBotContext, getLogger } from "../../bindings"; -import { - addCommentToIssue, - generatePermit2Signature, - getAllIssueComments, - getAllPullRequestReviews, - getIssueDescription, - getTokenSymbol, - parseComments, -} from "../../helpers"; +import { getBotContext, getLogger } from "../../bindings"; +import { getAllIssueComments, getAllPullRequestReviews, getIssueDescription, parseComments } from "../../helpers"; import { getLatestPullRequest, gitLinkedPrParser } from "../../helpers/parser"; -import { Incentives, MarkdownItem, Payload, StateReason, UserType } from "../../types"; -import { commentParser } from "../comment"; +import { Incentives, MarkdownItem, Payload, UserType } from "../../types"; +import { RewardsResponse, commentParser } from "../comment"; import Decimal from "decimal.js"; import { bountyInfo } from "../wildcard"; +import { IncentivesCalculationResult } from "./action"; +import { BigNumber } from "ethers"; + +export interface CreatorCommentResult { + title: string; + account?: string | undefined; + amountInETH?: Decimal | undefined; + userId?: string | undefined; + tokenSymbol?: string | undefined; + node_id?: string | undefined; + user?: string | undefined; +} const ItemsToExclude: string[] = [MarkdownItem.BlockQuote]; /** * Incentivize the contributors based on their contribution. * The default formula has been defined in https://github.com/ubiquity/ubiquibot/issues/272 */ -export const incentivizeComments = async () => { +export const calculateIssueConversationReward = async (calculateIncentives: IncentivesCalculationResult): Promise => { + const title = `Conversation`; const logger = getLogger(); - const { - mode: { incentiveMode, paymentPermitMaxPrice }, - price: { baseMultiplier, incentives }, - payout: { paymentToken, rpc }, - } = getBotConfig(); - if (!incentiveMode) { - logger.info(`No incentive mode. skipping to process`); - return; - } + const context = getBotContext(); const payload = context.payload as Payload; const issue = payload.issue; - if (!issue) { - logger.info(`Incomplete payload. issue: ${issue}`); - return; - } - - if (issue.state_reason !== StateReason.COMPLETED) { - logger.info("incentivizeComments: comment incentives disabled because the issue was not closed as completed."); - return; - } - - if (!paymentPermitMaxPrice) { - logger.info(`incentivizeComments: skipping to generate permit2 url, reason: { paymentPermitMaxPrice: ${paymentPermitMaxPrice}}`); - return; - } - - const issueDetailed = bountyInfo(issue); - if (!issueDetailed.isBounty) { - logger.info(`incentivizeComments: its not a bounty`); - return; - } - const comments = await getAllIssueComments(issue.number); - const permitComments = comments.filter( - (content) => content.body.includes("Conversation Rewards") && content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot + const permitComments = calculateIncentives.comments.filter( + (content) => content.body.includes(title) && content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot ); if (permitComments.length > 0) { logger.info(`incentivizeComments: skip to generate a permit url because it has been already posted`); - return; + return { error: `incentivizeComments: skip to generate a permit url because it has been already posted` }; } const assignees = issue?.assignees ?? []; const assignee = assignees.length > 0 ? assignees[0] : undefined; if (!assignee) { logger.info("incentivizeComments: skipping payment permit generation because `assignee` is `undefined`."); - return; + return { error: "incentivizeComments: skipping payment permit generation because `assignee` is `undefined`." }; } - const issueComments = await getAllIssueComments(issue.number, "full"); + const issueComments = await getAllIssueComments(calculateIncentives.issue.number, "full"); logger.info(`Getting the issue comments done. comments: ${JSON.stringify(issueComments)}`); const issueCommentsByUser: Record = {}; for (const issueComment of issueComments) { const user = issueComment.user; - if (user.type == UserType.Bot || user.login == assignee) continue; + if (user.type == UserType.Bot || user.login == assignee.login) continue; const commands = commentParser(issueComment.body); if (commands.length > 0) { logger.info(`Skipping to parse the comment because it contains commands. comment: ${JSON.stringify(issueComment)}`); @@ -93,106 +69,138 @@ export const incentivizeComments = async () => { } issueCommentsByUser[user.login].comments.push(issueComment.body_html); } - const tokenSymbol = await getTokenSymbol(paymentToken, rpc); logger.info(`Filtering by the user type done. commentsByUser: ${JSON.stringify(issueCommentsByUser)}`); - // The mapping between gh handle and comment with a permit url - const reward: Record = {}; - // The mapping between gh handle and amount in ETH const fallbackReward: Record = {}; - let comment = `#### Conversation Rewards\n`; + + // array of awaiting permits to generate + const reward: { account: string; priceInEth: Decimal; userId: string; user: string; penaltyAmount: BigNumber }[] = []; + for (const user of Object.keys(issueCommentsByUser)) { const commentsByUser = issueCommentsByUser[user]; const commentsByNode = await parseComments(commentsByUser.comments, ItemsToExclude); - const rewardValue = calculateRewardValue(commentsByNode, incentives); + const rewardValue = calculateRewardValue(commentsByNode, calculateIncentives.incentives); if (rewardValue.equals(0)) { logger.info(`Skipping to generate a permit url because the reward value is 0. user: ${user}`); continue; } logger.debug(`Comment parsed for the user: ${user}. comments: ${JSON.stringify(commentsByNode)}, sum: ${rewardValue}`); const account = await getWalletAddress(user); - const amountInETH = rewardValue.mul(baseMultiplier); - if (amountInETH.gt(paymentPermitMaxPrice)) { + const priceInEth = rewardValue.mul(calculateIncentives.baseMultiplier); + if (priceInEth.gt(calculateIncentives.paymentPermitMaxPrice)) { logger.info(`Skipping comment reward for user ${user} because reward is higher than payment permit max price`); continue; } if (account) { - const { payoutUrl } = await generatePermit2Signature(account, amountInETH, issue.node_id, commentsByUser.id, "ISSUE_COMMENTER"); - comment = `${comment}### [ **${user}: [ CLAIM ${amountInETH} ${tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n`; - reward[user] = payoutUrl; + reward.push({ account, priceInEth, userId: commentsByUser.id, user, penaltyAmount: BigNumber.from(0) }); } else { - fallbackReward[user] = amountInETH; + fallbackReward[user] = priceInEth; } } - logger.info(`Permit url generated for contributors. reward: ${JSON.stringify(reward)}`); - logger.info(`Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(fallbackReward)}`); - - await addCommentToIssue(comment, issue.number); + return { error: "", title, reward, fallbackReward }; }; -export const incentivizePullRequestReviews = async () => { +export const calculateIssueCreatorReward = async (incentivesCalculation: IncentivesCalculationResult): Promise => { + const title = `Task Creator`; const logger = getLogger(); - const { - mode: { incentiveMode, paymentPermitMaxPrice }, - price: { baseMultiplier, incentives }, - payout: { paymentToken, rpc }, - } = getBotConfig(); - if (!incentiveMode) { - logger.info(`No incentive mode. skipping to process`); - return; - } - const context = getBotContext(); - const payload = context.payload as Payload; - const issue = payload.issue; - if (!issue) { - logger.info(`Incomplete payload. issue: ${issue}`); - return; + + const issueDetailed = bountyInfo(incentivesCalculation.issue); + if (!issueDetailed.isBounty) { + logger.info(`incentivizeCreatorComment: its not a bounty`); + return { error: `incentivizeCreatorComment: its not a bounty` }; } - if (issue.state_reason !== StateReason.COMPLETED) { - logger.info("incentivizePullRequestReviews: comment incentives skipped because the issue was not closed as completed"); - return; + const comments = await getAllIssueComments(incentivesCalculation.issue.number); + const permitComments = comments.filter( + (content) => content.body.includes(title) && content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot + ); + if (permitComments.length > 0) { + logger.info(`incentivizeCreatorComment: skip to generate a permit url because it has been already posted`); + return { error: `incentivizeCreatorComment: skip to generate a permit url because it has been already posted` }; } - if (paymentPermitMaxPrice == 0 || !paymentPermitMaxPrice) { - logger.info(`incentivizePullRequestReviews: skipping to generate permit2 url, reason: { paymentPermitMaxPrice: ${paymentPermitMaxPrice}}`); - return; + const assignees = incentivesCalculation.issue.assignees ?? []; + const assignee = assignees.length > 0 ? assignees[0] : undefined; + if (!assignee) { + logger.info("incentivizeCreatorComment: skipping payment permit generation because `assignee` is `undefined`."); + return { error: "incentivizeCreatorComment: skipping payment permit generation because `assignee` is `undefined`." }; } - const issueDetailed = bountyInfo(issue); - if (!issueDetailed.isBounty) { - logger.info(`incentivizePullRequestReviews: its not a bounty`); - return; + const description = await getIssueDescription(incentivesCalculation.issue.number, "html"); + if (!description) { + logger.info(`Skipping to generate a permit url because issue description is empty. description: ${description}`); + return { error: `Skipping to generate a permit url because issue description is empty. description: ${description}` }; } + logger.info(`Getting the issue description done. description: ${description}`); + const creator = incentivesCalculation.issue.user; + if (creator.type === UserType.Bot || creator.login === incentivesCalculation.issue.assignee) { + logger.info("Issue creator assigneed himself or Bot created this issue."); + return { error: "Issue creator assigneed himself or Bot created this issue." }; + } + + const result = await generatePermitForComments( + creator.login, + [description], + incentivesCalculation.issueCreatorMultiplier, + incentivesCalculation.incentives, + incentivesCalculation.paymentPermitMaxPrice + ); + + if (!result || !result.account || !result.amountInETH) { + throw new Error("Failed to generate permit for issue creator because of missing account or amountInETH"); + } + + return { + error: "", + title, + userId: creator.node_id, + username: creator.login, + reward: [ + { + priceInEth: result?.amountInETH ?? new Decimal(0), + account: result?.account, + userId: "", + user: "", + penaltyAmount: BigNumber.from(0), + }, + ], + }; +}; + +export const calculatePullRequestReviewsReward = async (incentivesCalculation: IncentivesCalculationResult): Promise => { + const logger = getLogger(); + const context = getBotContext(); + const title = "Reviewer"; const linkedPullRequest = await gitLinkedPrParser({ - owner: payload.repository.owner.login, - repo: payload.repository.name, - issue_number: issue.number, + owner: incentivesCalculation.payload.repository.owner.login, + repo: incentivesCalculation.payload.repository.name, + issue_number: incentivesCalculation.issue.number, }); + const latestLinkedPullRequest = await getLatestPullRequest(linkedPullRequest); if (!latestLinkedPullRequest) { - logger.debug(`incentivizePullRequestReviews: No linked pull requests found`); - return; + logger.debug(`calculatePullRequestReviewsReward: No linked pull requests found`); + return { error: `calculatePullRequestReviewsReward: No linked pull requests found` }; } - const comments = await getAllIssueComments(issue.number); + const comments = await getAllIssueComments(incentivesCalculation.issue.number); const permitComments = comments.filter( - (content) => content.body.includes("Reviewer Rewards") && content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot + (content) => content.body.includes(title) && content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot ); if (permitComments.length > 0) { - logger.info(`incentivizePullRequestReviews: skip to generate a permit url because it has been already posted`); - return; + logger.info(`calculatePullRequestReviewsReward: skip to generate a permit url because it has been already posted`); + return { error: `calculatePullRequestReviewsReward: skip to generate a permit url because it has been already posted` }; } - const assignees = issue?.assignees ?? []; + const assignees = incentivesCalculation.issue?.assignees ?? []; const assignee = assignees.length > 0 ? assignees[0] : undefined; if (!assignee) { - logger.info("incentivizePullRequestReviews: skipping payment permit generation because `assignee` is `undefined`."); - return; + logger.info("calculatePullRequestReviewsReward: skipping payment permit generation because `assignee` is `undefined`."); + return { error: "calculatePullRequestReviewsReward: skipping payment permit generation because `assignee` is `undefined`." }; } const prReviews = await getAllPullRequestReviews(context, latestLinkedPullRequest.number, "full"); @@ -204,7 +212,7 @@ export const incentivizePullRequestReviews = async () => { if (!user) continue; if (user.type == UserType.Bot || user.login == assignee) continue; if (!review.body_html) { - logger.info(`incentivizePullRequestReviews: Skipping to parse the comment because body_html is undefined. comment: ${JSON.stringify(review)}`); + logger.info(`calculatePullRequestReviewsReward: Skipping to parse the comment because body_html is undefined. comment: ${JSON.stringify(review)}`); continue; } if (!prReviewsByUser[user.login]) { @@ -218,7 +226,7 @@ export const incentivizePullRequestReviews = async () => { if (!user) continue; if (user.type == UserType.Bot || user.login == assignee) continue; if (!comment.body_html) { - logger.info(`incentivizePullRequestReviews: Skipping to parse the comment because body_html is undefined. comment: ${JSON.stringify(comment)}`); + logger.info(`calculatePullRequestReviewsReward: Skipping to parse the comment because body_html is undefined. comment: ${JSON.stringify(comment)}`); continue; } if (!prReviewsByUser[user.login]) { @@ -226,160 +234,69 @@ export const incentivizePullRequestReviews = async () => { } prReviewsByUser[user.login].comments.push(comment.body_html); } - const tokenSymbol = await getTokenSymbol(paymentToken, rpc); - logger.info(`incentivizePullRequestReviews: Filtering by the user type done. commentsByUser: ${JSON.stringify(prReviewsByUser)}`); - // The mapping between gh handle and comment with a permit url - const reward: Record = {}; + logger.info(`calculatePullRequestReviewsReward: Filtering by the user type done. commentsByUser: ${JSON.stringify(prReviewsByUser)}`); + + // array of awaiting permits to generate + const reward: { account: string; priceInEth: Decimal; userId: string; user: string; penaltyAmount: BigNumber }[] = []; // The mapping between gh handle and amount in ETH const fallbackReward: Record = {}; - let comment = `#### Reviewer Rewards\n`; + for (const user of Object.keys(prReviewsByUser)) { const commentByUser = prReviewsByUser[user]; const commentsByNode = await parseComments(commentByUser.comments, ItemsToExclude); - const rewardValue = calculateRewardValue(commentsByNode, incentives); + const rewardValue = calculateRewardValue(commentsByNode, incentivesCalculation.incentives); if (rewardValue.equals(0)) { - logger.info(`incentivizePullRequestReviews: Skipping to generate a permit url because the reward value is 0. user: ${user}`); + logger.info(`calculatePullRequestReviewsReward: Skipping to generate a permit url because the reward value is 0. user: ${user}`); continue; } - logger.info(`incentivizePullRequestReviews: Comment parsed for the user: ${user}. comments: ${JSON.stringify(commentsByNode)}, sum: ${rewardValue}`); + logger.info(`calculatePullRequestReviewsReward: Comment parsed for the user: ${user}. comments: ${JSON.stringify(commentsByNode)}, sum: ${rewardValue}`); const account = await getWalletAddress(user); - const amountInETH = rewardValue.mul(baseMultiplier); - if (amountInETH.gt(paymentPermitMaxPrice)) { - logger.info(`incentivizePullRequestReviews: Skipping comment reward for user ${user} because reward is higher than payment permit max price`); + const priceInEth = rewardValue.mul(incentivesCalculation.baseMultiplier); + if (priceInEth.gt(incentivesCalculation.paymentPermitMaxPrice)) { + logger.info(`calculatePullRequestReviewsReward: Skipping comment reward for user ${user} because reward is higher than payment permit max price`); continue; } + if (account) { - const { payoutUrl } = await generatePermit2Signature(account, amountInETH, issue.node_id, commentByUser.id, "ISSUE_COMMENTER"); - comment = `${comment}### [ **${user}: [ CLAIM ${amountInETH} ${tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n`; - reward[user] = payoutUrl; + reward.push({ account, priceInEth, userId: commentByUser.id, user, penaltyAmount: BigNumber.from(0) }); } else { - fallbackReward[user] = amountInETH; + fallbackReward[user] = priceInEth; } } - logger.info(`incentivizePullRequestReviews: Permit url generated for pull request reviewers. reward: ${JSON.stringify(reward)}`); - logger.info(`incentivizePullRequestReviews: Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(fallbackReward)}`); + logger.info(`calculatePullRequestReviewsReward: Permit url generated for pull request reviewers. reward: ${JSON.stringify(reward)}`); + logger.info(`calculatePullRequestReviewsReward: Skipping to generate a permit url for missing accounts. fallback: ${JSON.stringify(fallbackReward)}`); - await addCommentToIssue(comment, issue.number); -}; - -export const incentivizeCreatorComment = async () => { - const logger = getLogger(); - const { - mode: { incentiveMode, paymentPermitMaxPrice }, - price: { incentives, issueCreatorMultiplier }, - payout: { paymentToken, rpc }, - } = getBotConfig(); - if (!incentiveMode) { - logger.info(`No incentive mode. skipping to process`); - return; - } - const context = getBotContext(); - const payload = context.payload as Payload; - const issue = payload.issue; - if (!issue) { - logger.info(`Incomplete payload. issue: ${issue}`); - return; - } - - if (issue.state_reason !== StateReason.COMPLETED) { - logger.info("incentivizeCreatorComment: comment incentives disabled because the issue was not closed as completed."); - return; - } - - if (paymentPermitMaxPrice == 0 || !paymentPermitMaxPrice) { - logger.info(`incentivizeCreatorComment: skipping to generate permit2 url, reason: { paymentPermitMaxPrice: ${paymentPermitMaxPrice}}`); - return; - } - - const issueDetailed = bountyInfo(issue); - if (!issueDetailed.isBounty) { - logger.info(`incentivizeCreatorComment: its not a bounty`); - return; - } - - const comments = await getAllIssueComments(issue.number); - const permitComments = comments.filter( - (content) => content.body.includes("Task Creator Reward") && content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot - ); - if (permitComments.length > 0) { - logger.info(`incentivizeCreatorComment: skip to generate a permit url because it has been already posted`); - return; - } - - const assignees = issue.assignees ?? []; - const assignee = assignees.length > 0 ? assignees[0] : undefined; - if (!assignee) { - logger.info("incentivizeCreatorComment: skipping payment permit generation because `assignee` is `undefined`."); - return; - } - - const description = await getIssueDescription(issue.number, "html"); - if (!description) { - logger.info(`Skipping to generate a permit url because issue description is empty. description: ${description}`); - return; - } - logger.info(`Getting the issue description done. description: ${description}`); - const creator = issue.user; - if (creator.type === UserType.Bot || creator.login === issue.assignee) { - logger.info("Issue creator assigneed himself or Bot created this issue."); - return; - } - - const tokenSymbol = await getTokenSymbol(paymentToken, rpc); - const result = await generatePermitForComments( - creator.login, - creator.node_id, - [description], - issueCreatorMultiplier, - incentives, - tokenSymbol, - issue.node_id, - paymentPermitMaxPrice - ); - - if (result.payoutUrl) { - logger.info(`Permit url generated for creator. reward: ${result.payoutUrl}`); - await addCommentToIssue(result.comment, issue.number); - } - if (result.amountInETH) { - logger.info(`Skipping to generate a permit url for missing account. fallback: ${result.amountInETH}`); - } + return { error: "", title, reward, fallbackReward }; }; const generatePermitForComments = async ( user: string, - userId: string, comments: string[], multiplier: number, incentives: Incentives, - tokenSymbol: string, - node_id: string, paymentPermitMaxPrice: number -): Promise<{ comment: string; payoutUrl?: string; amountInETH?: Decimal }> => { +): Promise => { const logger = getLogger(); const commentsByNode = await parseComments(comments, ItemsToExclude); const rewardValue = calculateRewardValue(commentsByNode, incentives); if (rewardValue.equals(0)) { logger.info(`No reward for the user: ${user}. comments: ${JSON.stringify(commentsByNode)}, sum: ${rewardValue}`); - return { comment: "" }; + return; } logger.debug(`Comment parsed for the user: ${user}. comments: ${JSON.stringify(commentsByNode)}, sum: ${rewardValue}`); const account = await getWalletAddress(user); const amountInETH = rewardValue.mul(multiplier); if (amountInETH.gt(paymentPermitMaxPrice)) { logger.info(`Skipping issue creator reward for user ${user} because reward is higher than payment permit max price`); - return { comment: "" }; + return; } - let comment = `#### Task Creator Reward\n`; if (account) { - const { payoutUrl } = await generatePermit2Signature(account, amountInETH, node_id, userId, "ISSUE_CREATOR"); - comment = `${comment}### [ **${user}: [ CLAIM ${amountInETH} ${tokenSymbol.toUpperCase()} ]** ](${payoutUrl})\n`; - return { comment, payoutUrl }; + return { account, amountInETH }; } else { - return { comment, amountInETH }; + return { account: "0x", amountInETH: new Decimal(0) }; } }; /** diff --git a/src/handlers/processors.ts b/src/handlers/processors.ts index 68e366063..94a0ff93a 100644 --- a/src/handlers/processors.ts +++ b/src/handlers/processors.ts @@ -6,7 +6,6 @@ import { nullHandler } from "./shared"; import { handleComment, issueClosedCallback, issueCreatedCallback, issueReopenedCallback } from "./comment"; import { checkPullRequests } from "./assign/auto"; import { createDevPoolPR } from "./pull-request"; -import { incentivizeComments, incentivizeCreatorComment, incentivizePullRequestReviews } from "./payout"; import { runOnPush, validateConfigChange } from "./push"; import { findDuplicateOne } from "./issue"; @@ -54,7 +53,7 @@ export const processors: Record = { [GithubEvent.ISSUES_CLOSED]: { pre: [nullHandler], action: [issueClosedCallback], - post: [incentivizeCreatorComment, incentivizeComments, incentivizePullRequestReviews], + post: [nullHandler], }, [GithubEvent.PULL_REQUEST_OPENED]: { pre: [nullHandler], diff --git a/src/helpers/permit.ts b/src/helpers/permit.ts index 3e6f21832..064b8918c 100644 --- a/src/helpers/permit.ts +++ b/src/helpers/permit.ts @@ -56,8 +56,7 @@ export const generatePermit2Signature = async ( spender: string, amountInEth: Decimal, identifier: string, - userId = "", - type = "" + userId = "" ): Promise<{ txData: TxData; payoutUrl: string }> => { const { payout: { networkId, privateKey, permitBaseUrl, rpc, paymentToken }, @@ -75,7 +74,7 @@ export const generatePermit2Signature = async ( }, // who can transfer the tokens spender: spender, - nonce: BigNumber.from(keccak256(toUtf8Bytes(identifier + userId + type))), + nonce: BigNumber.from(keccak256(toUtf8Bytes(identifier + userId))), // signature deadline deadline: MaxUint256, }; From c40efc5a8aa29fba30d9571a6546725cd8ccfbe6 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 21 Sep 2023 03:34:33 +0100 Subject: [PATCH 87/88] feat: ask Command (#663) * feat(deps): added openai added openAI * feat: added ask command Simple prompt engineering, one response per user per question. * fix: update prompt better initial prompt * fix: update system prompt update prompt * feat: simple memory original context indexable across repos, issues and pull requests * fix: comments comments etc * fix: streamlined context waiting for more input * chore: pulling context pulls from sources using the hashtag in issue body * chore: tokenization total token usage now displayed * chore: diff comparison feed gpt the spec and diff for it to analyze * fix: ci and spec check will only spec check once now fixed tsc issues * fix: merge mistake sort import * fix: key from config allow it to be set in org and repo config * fix: set ask to false reset default * fix(deps): langchain unused dep * fix: apikey undefined no longer undefined * fix: using token limit set to 8k in config 4k by default * chore: improve ask command improved pr-review and context for both ask and pr-review commands * fix: gpt helpers moved base ask and context call into helpers * chore: use error diff replace text error with diff * fix: remove unused requested changes * fix: remove unused missed the shared default * fix: schema new types * fix: nullable and error start with a bang and clear api key error * fix: duplicated --------- Co-authored-by: 0xcodercrane <108444211+0xcodercrane@users.noreply.github.com> --- .env.example | 1 + package.json | 1 + src/bindings/config.ts | 6 + src/configs/index.ts | 2 +- src/configs/ubiquibot-config-default.ts | 92 +- src/handlers/comment/commands.ts | 1 + src/handlers/comment/handlers/ask.ts | 123 ++ src/handlers/comment/handlers/index.ts | 8 + src/helpers/gpt.ts | 180 ++ src/helpers/issue.ts | 108 +- src/types/config.ts | 28 + src/utils/helpers.ts | 2 +- src/utils/private.ts | 4 +- supabase/config.toml | 2 +- yarn.lock | 2179 ++++++++++++----------- 15 files changed, 1627 insertions(+), 1110 deletions(-) create mode 100644 src/handlers/comment/handlers/ask.ts create mode 100644 src/helpers/gpt.ts diff --git a/.env.example b/.env.example index 213356e0f..819c46da0 100644 --- a/.env.example +++ b/.env.example @@ -10,6 +10,7 @@ SUPABASE_KEY= AUTO_PAY_MODE= ANALYTICS_MODE= + # Use `trace` to get verbose logging or `info` to show less LOG_LEVEL=debug LOGDNA_INGESTION_KEY= diff --git a/package.json b/package.json index 3cf3f50bf..a7c0704c8 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "node-html-parser": "^6.1.5", "node-html-to-image": "^3.3.0", "nodemon": "^2.0.19", + "openai": "^4.2.0", "parse5": "^7.1.2", "prettier": "^2.7.1", "probot": "^12.2.4", diff --git a/src/bindings/config.ts b/src/bindings/config.ts index 4fc29bf11..413e3faef 100644 --- a/src/bindings/config.ts +++ b/src/bindings/config.ts @@ -34,6 +34,8 @@ export const loadConfig = async (context: Context): Promise => { registerWalletWithVerification, staleBountyTime, enableAccessControl, + openAIKey, + openAITokenLimit, } = await getWideConfig(context); const publicKey = await getScalarKey(process.env.X25519_PRIVATE_KEY); @@ -99,6 +101,10 @@ export const loadConfig = async (context: Context): Promise => { wallet: { registerWalletWithVerification: registerWalletWithVerification, }, + ask: { + apiKey: openAIKey, + tokenLimit: openAITokenLimit, + }, accessControl: enableAccessControl, }; diff --git a/src/configs/index.ts b/src/configs/index.ts index d6231b38f..a449ff0d2 100644 --- a/src/configs/index.ts +++ b/src/configs/index.ts @@ -1,4 +1,4 @@ export * from "./shared"; export * from "./strings"; export * from "./abis"; -export * from "./ubiquibot-config-default"; \ No newline at end of file +export * from "./ubiquibot-config-default"; diff --git a/src/configs/ubiquibot-config-default.ts b/src/configs/ubiquibot-config-default.ts index d1d9b7ffd..a5f764862 100644 --- a/src/configs/ubiquibot-config-default.ts +++ b/src/configs/ubiquibot-config-default.ts @@ -1,6 +1,6 @@ import { MergedConfig } from "../types"; -export const DefaultConfig : MergedConfig = { +export const DefaultConfig: MergedConfig = { "evm-network-id": 100, "price-multiplier": 1, "issue-creator-multiplier": 2, @@ -10,88 +10,94 @@ export const DefaultConfig : MergedConfig = { "disable-analytics": false, "comment-incentives": false, "register-wallet-with-verification": false, - "promotion-comment": "\n
If you enjoy the DevPool experience, please follow Ubiquity on GitHub and star this repo to show your support. It helps a lot!
", + "openai-api-key": null, + "openai-token-limit": 8000, + "stale-bounty-time": "0d", + "promotion-comment": + "\n
If you enjoy the DevPool experience, please follow Ubiquity on GitHub and star this repo to show your support. It helps a lot!
", "default-labels": [], "time-labels": [ { - "name": "Time: <1 Hour" + name: "Time: <1 Hour", }, { - "name": "Time: <1 Day" + name: "Time: <1 Day", }, { - "name": "Time: <1 Week" + name: "Time: <1 Week", }, { - "name": "Time: <2 Weeks" + name: "Time: <2 Weeks", }, { - "name": "Time: <1 Month" - } + name: "Time: <1 Month", + }, ], "priority-labels": [ { - "name": "Priority: 1 (Normal)" + name: "Priority: 1 (Normal)", }, { - "name": "Priority: 2 (Medium)" + name: "Priority: 2 (Medium)", }, { - "name": "Priority: 3 (High)" + name: "Priority: 3 (High)", }, { - "name": "Priority: 4 (Urgent)" + name: "Priority: 4 (Urgent)", }, { - "name": "Priority: 5 (Emergency)" - } + name: "Priority: 5 (Emergency)", + }, ], "command-settings": [ { - "name": "start", - "enabled": false + name: "start", + enabled: false, + }, + { + name: "stop", + enabled: false, }, { - "name": "stop", - "enabled": false + name: "wallet", + enabled: false, }, { - "name": "wallet", - "enabled": false + name: "payout", + enabled: false, }, { - "name": "payout", - "enabled": false + name: "multiplier", + enabled: false, }, { - "name": "multiplier", - "enabled": false + name: "query", + enabled: false, }, { - "name": "query", - "enabled": false + name: "ask", + enabled: false, }, { - "name": "allow", - "enabled": false + name: "allow", + enabled: false, }, { - "name": "autopay", - "enabled": false - } + name: "autopay", + enabled: false, + }, ], - "incentives": { - "comment": { - "elements": {}, - "totals": { - "word": 0 - } - } + incentives: { + comment: { + elements: {}, + totals: { + word: 0, + }, + }, }, "enable-access-control": { - "label": false, - "organization": true + label: false, + organization: true, }, - "stale-bounty-time":"0d" -} - +}; diff --git a/src/handlers/comment/commands.ts b/src/handlers/comment/commands.ts index afdab0b03..d009972d8 100644 --- a/src/handlers/comment/commands.ts +++ b/src/handlers/comment/commands.ts @@ -6,6 +6,7 @@ export enum IssueCommentCommands { PAYOUT = "/payout", // request permit payout MULTIPLIER = "/multiplier", // set bounty multiplier (for treasury) QUERY = "/query", + ASK = "/ask", // ask GPT a question // Access Controls ALLOW = "/allow", diff --git a/src/handlers/comment/handlers/ask.ts b/src/handlers/comment/handlers/ask.ts new file mode 100644 index 000000000..63777d4ae --- /dev/null +++ b/src/handlers/comment/handlers/ask.ts @@ -0,0 +1,123 @@ +import { getBotContext, getLogger } from "../../../bindings"; +import { Payload, StreamlinedComment, UserType } from "../../../types"; +import { getAllIssueComments, getAllLinkedIssuesAndPullsInBody } from "../../../helpers"; +import { CreateChatCompletionRequestMessage } from "openai/resources/chat"; +import { askGPT, decideContextGPT, sysMsg } from "../../../helpers/gpt"; +import { ErrorDiff } from "../../../utils/helpers"; + +/** + * @param body The question to ask + */ +export const ask = async (body: string) => { + const context = getBotContext(); + const logger = getLogger(); + + const payload = context.payload as Payload; + const sender = payload.sender.login; + const issue = payload.issue; + + if (!body) { + return `Please ask a question`; + } + + if (!issue) { + return `This command can only be used on issues`; + } + + const chatHistory: CreateChatCompletionRequestMessage[] = []; + const streamlined: StreamlinedComment[] = []; + let linkedPRStreamlined: StreamlinedComment[] = []; + let linkedIssueStreamlined: StreamlinedComment[] = []; + + const regex = /^\/ask\s(.+)$/; + const matches = body.match(regex); + + if (matches) { + const [, body] = matches; + + // standard comments + const comments = await getAllIssueComments(issue.number); + // raw so we can grab the tag + const commentsRaw = await getAllIssueComments(issue.number, "raw"); + + if (!comments) { + logger.info(`Error getting issue comments`); + return ErrorDiff(`Error getting issue comments`); + } + + // add the first comment of the issue/pull request + streamlined.push({ + login: issue.user.login, + body: issue.body, + }); + + // add the rest + comments.forEach(async (comment, i) => { + if (comment.user.type == UserType.User || commentsRaw[i].body.includes("")) { + streamlined.push({ + login: comment.user.login, + body: comment.body, + }); + } + }); + + // returns the conversational context from all linked issues and prs + const links = await getAllLinkedIssuesAndPullsInBody(issue.number); + + if (typeof links === "string") { + logger.info(`Error getting linked issues or prs: ${links}`); + } else { + linkedIssueStreamlined = links.linkedIssues; + linkedPRStreamlined = links.linkedPrs; + } + + // let chatgpt deduce what is the most relevant context + const gptDecidedContext = await decideContextGPT(chatHistory, streamlined, linkedPRStreamlined, linkedIssueStreamlined); + + if (linkedIssueStreamlined.length == 0 && linkedPRStreamlined.length == 0) { + // No external context to add + chatHistory.push( + { + role: "system", + content: sysMsg, + name: "UbiquityAI", + } as CreateChatCompletionRequestMessage, + { + role: "user", + content: body, + name: sender, + } as CreateChatCompletionRequestMessage + ); + } else { + chatHistory.push( + { + role: "system", + content: sysMsg, // provide the answer template + name: "UbiquityAI", + } as CreateChatCompletionRequestMessage, + { + role: "system", + content: "Original Context: " + JSON.stringify(gptDecidedContext), // provide the context + name: "system", + } as CreateChatCompletionRequestMessage, + { + role: "user", + content: "Question: " + JSON.stringify(body), // provide the question + name: "user", + } as CreateChatCompletionRequestMessage + ); + } + + const gptResponse = await askGPT(body, chatHistory); + + if (typeof gptResponse === "string") { + return gptResponse; + } else if (gptResponse.answer) { + return gptResponse.answer; + } else { + return ErrorDiff(`Error getting response from GPT`); + } + } else { + return "Invalid syntax for ask \n usage: '/ask What is pi?"; + } +}; diff --git a/src/handlers/comment/handlers/index.ts b/src/handlers/comment/handlers/index.ts index 244e6a080..490b0b934 100644 --- a/src/handlers/comment/handlers/index.ts +++ b/src/handlers/comment/handlers/index.ts @@ -7,6 +7,7 @@ import { listAvailableCommands } from "./help"; import { unassign } from "./unassign"; import { registerWallet } from "./wallet"; import { setAccess } from "./allow"; +import { ask } from "./ask"; import { multiplier } from "./multiplier"; import { BigNumber, ethers } from "ethers"; import { addPenalty } from "../../../adapters/supabase"; @@ -44,6 +45,7 @@ export * from "./payout"; export * from "./help"; export * from "./multiplier"; export * from "./query"; +export * from "./ask"; export interface RewardsResponse { error: string | null; @@ -284,6 +286,12 @@ export const userCommands = (): UserCommands[] => { handler: query, callback: commandCallback, }, + { + id: IssueCommentCommands.ASK, + description: `Ask a technical question to the Ubiquity AI. \n example usage: "/ask How do I do X?"`, + handler: ask, + callback: commandCallback, + }, { id: IssueCommentCommands.MULTIPLIER, description: `Set the bounty payout multiplier for a specific contributor, and provide the reason for why. \n example usage: "/wallet @user 0.5 'Multiplier reason'"`, diff --git a/src/helpers/gpt.ts b/src/helpers/gpt.ts new file mode 100644 index 000000000..046503d79 --- /dev/null +++ b/src/helpers/gpt.ts @@ -0,0 +1,180 @@ +import { getBotConfig, getBotContext, getLogger } from "../bindings"; +import { Payload, StreamlinedComment, UserType } from "../types"; +import { getAllIssueComments, getAllLinkedIssuesAndPullsInBody } from "../helpers"; +import OpenAI from "openai"; +import { CreateChatCompletionRequestMessage } from "openai/resources/chat"; +import { ErrorDiff } from "../utils/helpers"; + +export const sysMsg = `You are the UbiquityAI, designed to provide accurate technical answers. \n +Whenever appropriate, format your response using GitHub Flavored Markdown. Utilize tables, lists, and code blocks for clear and organized answers. \n +Do not make up answers. If you are unsure, say so. \n +Original Context exists only to provide you with additional information to the current question, use it to formulate answers. \n +Infer the context of the question from the Original Context using your best judgement. \n +All replies MUST end with "\n\n ".\n +`; + +export const gptContextTemplate = ` +You are the UbiquityAI, designed to review and analyze pull requests. +You have been provided with the spec of the issue and all linked issues or pull requests. +Using this full context, Reply in pure JSON format, with the following structure omitting irrelvant information pertaining to the specification. +You MUST provide the following structure, but you may add additional information if you deem it relevant. +Example:[ + { + "source": "issue #123" + "spec": "This is the issue spec" + "relevant": [ + { + "login": "user", + "body": "This is the relevant context" + "relevancy": "Why is this relevant to the spec?" + }, + { + "login": "other_user", + "body": "This is other relevant context" + "relevancy": "Why is this relevant to the spec?" + } + ] + }, + { + "source": "Pull #456" + "spec": "This is the pull request spec" + "relevant": [ + { + "login": "user", + "body": "This is the relevant context" + "relevancy": "Why is this relevant to the spec?" + }, + { + "login": "other_user", + "body": "This is other relevant context" + "relevancy": "Why is this relevant to the spec?" + } + ] + } +] +`; + +/** + * @notice best used alongside getAllLinkedIssuesAndPullsInBody() in helpers/issue + * @param chatHistory the conversational context to provide to GPT + * @param streamlined an array of comments in the form of { login: string, body: string } + * @param linkedPRStreamlined an array of comments in the form of { login: string, body: string } + * @param linkedIssueStreamlined an array of comments in the form of { login: string, body: string } + */ +export const decideContextGPT = async ( + chatHistory: CreateChatCompletionRequestMessage[], + streamlined: StreamlinedComment[], + linkedPRStreamlined: StreamlinedComment[], + linkedIssueStreamlined: StreamlinedComment[] +) => { + const context = getBotContext(); + const logger = getLogger(); + + const payload = context.payload as Payload; + const issue = payload.issue; + + if (!issue) { + return `Payload issue is undefined`; + } + + // standard comments + const comments = await getAllIssueComments(issue.number); + // raw so we can grab the tag + const commentsRaw = await getAllIssueComments(issue.number, "raw"); + + if (!comments) { + logger.info(`Error getting issue comments`); + return `Error getting issue comments`; + } + + // add the first comment of the issue/pull request + streamlined.push({ + login: issue.user.login, + body: issue.body, + }); + + // add the rest + comments.forEach(async (comment, i) => { + if (comment.user.type == UserType.User || commentsRaw[i].body.includes("")) { + streamlined.push({ + login: comment.user.login, + body: comment.body, + }); + } + }); + + // returns the conversational context from all linked issues and prs + const links = await getAllLinkedIssuesAndPullsInBody(issue.number); + + if (typeof links === "string") { + logger.info(`Error getting linked issues or prs: ${links}`); + return `Error getting linked issues or prs: ${links}`; + } + + linkedIssueStreamlined = links.linkedIssues; + linkedPRStreamlined = links.linkedPrs; + + chatHistory.push( + { + role: "system", + content: "This issue/Pr context: \n" + JSON.stringify(streamlined), + name: "UbiquityAI", + } as CreateChatCompletionRequestMessage, + { + role: "system", + content: "Linked issue(s) context: \n" + JSON.stringify(linkedIssueStreamlined), + name: "UbiquityAI", + } as CreateChatCompletionRequestMessage, + { + role: "system", + content: "Linked Pr(s) context: \n" + JSON.stringify(linkedPRStreamlined), + name: "UbiquityAI", + } as CreateChatCompletionRequestMessage + ); + + // we'll use the first response to determine the context of future calls + const res = await askGPT("", chatHistory); + + return res; +}; + +/** + * @notice base askGPT function + * @param question the question to ask + * @param chatHistory the conversational context to provide to GPT + */ +export const askGPT = async (question: string, chatHistory: CreateChatCompletionRequestMessage[]) => { + const logger = getLogger(); + const config = getBotConfig(); + + if (!config.ask.apiKey) { + logger.info(`No OpenAI API Key provided`); + return ErrorDiff("You must configure the `openai-api-key` property in the bot configuration in order to use AI powered features."); + } + + const openAI = new OpenAI({ + apiKey: config.ask.apiKey, + }); + + const res: OpenAI.Chat.Completions.ChatCompletion = await openAI.chat.completions.create({ + messages: chatHistory, + model: "gpt-3.5-turbo-16k", + max_tokens: config.ask.tokenLimit, + temperature: 0, + }); + + const answer = res.choices[0].message.content; + + const tokenUsage = { + output: res.usage?.completion_tokens, + input: res.usage?.prompt_tokens, + total: res.usage?.total_tokens, + }; + + if (!res) { + logger.info(`No answer found for question: ${question}`); + return `No answer found for question: ${question}`; + } + + return { answer, tokenUsage }; +}; diff --git a/src/helpers/issue.ts b/src/helpers/issue.ts index b8b487f35..e014994fe 100644 --- a/src/helpers/issue.ts +++ b/src/helpers/issue.ts @@ -1,6 +1,6 @@ import { Context } from "probot"; import { getBotConfig, getBotContext, getLogger } from "../bindings"; -import { AssignEvent, Comment, IssueType, Payload } from "../types"; +import { AssignEvent, Comment, IssueType, Payload, StreamlinedComment, UserType } from "../types"; import { checkRateLimitGit } from "../utils"; export const clearAllPriceLabelsOnIssue = async (): Promise => { @@ -688,3 +688,109 @@ export const getAvailableOpenedPullRequests = async (username: string) => { } return result; }; + +// Strips out all links from the body of an issue or pull request and fetches the conversational context from each linked issue or pull request +export const getAllLinkedIssuesAndPullsInBody = async (issueNumber: number) => { + const context = getBotContext(); + const logger = getLogger(); + + const issue = await getIssueByNumber(context, issueNumber); + + if (!issue) { + return `Failed to fetch using issueNumber: ${issueNumber}`; + } + + if (!issue.body) { + return `No body found for issue: ${issueNumber}`; + } + + const body = issue.body; + const linkedPRStreamlined: StreamlinedComment[] = []; + const linkedIssueStreamlined: StreamlinedComment[] = []; + + const regex = /https:\/\/github\.com\/[^/\s]+\/[^/\s]+\/(issues|pull)\/(\d+)/gi; + const matches = body.match(regex); + + if (matches) { + try { + const linkedIssues: number[] = []; + const linkedPrs: number[] = []; + + // this finds refs via all patterns: #, full url or [#25](url.to.issue) + const issueRef = issue.body.match(/(#(\d+)|https:\/\/github\.com\/[^/\s]+\/[^/\s]+\/(issues|pull)\/(\d+))/gi); + + // if they exist, strip out the # or the url and push them to their arrays + if (issueRef) { + issueRef.forEach((issue) => { + if (issue.includes("#")) { + linkedIssues.push(Number(issue.slice(1))); + } else { + if (issue.split("/")[5] == "pull") { + linkedPrs.push(Number(issue.split("/")[6])); + } else linkedIssues.push(Number(issue.split("/")[6])); + } + }); + } else { + logger.info(`No linked issues or prs found`); + } + + if (linkedPrs.length > 0) { + for (let i = 0; i < linkedPrs.length; i++) { + const pr = await getPullByNumber(context, linkedPrs[i]); + if (pr) { + linkedPRStreamlined.push({ + login: "system", + body: `=============== Pull Request #${pr.number}: ${pr.title} + ===============\n ${pr.body}}`, + }); + const prComments = await getAllIssueComments(linkedPrs[i]); + const prCommentsRaw = await getAllIssueComments(linkedPrs[i], "raw"); + prComments.forEach(async (comment, i) => { + if (comment.user.type == UserType.User || prCommentsRaw[i].body.includes("")) { + linkedPRStreamlined.push({ + login: comment.user.login, + body: comment.body, + }); + } + }); + } + } + } + + if (linkedIssues.length > 0) { + for (let i = 0; i < linkedIssues.length; i++) { + const issue = await getIssueByNumber(context, linkedIssues[i]); + if (issue) { + linkedIssueStreamlined.push({ + login: "system", + body: `=============== Issue #${issue.number}: ${issue.title} + ===============\n ${issue.body} `, + }); + const issueComments = await getAllIssueComments(linkedIssues[i]); + const issueCommentsRaw = await getAllIssueComments(linkedIssues[i], "raw"); + issueComments.forEach(async (comment, i) => { + if (comment.user.type == UserType.User || issueCommentsRaw[i].body.includes("")) { + linkedIssueStreamlined.push({ + login: comment.user.login, + body: comment.body, + }); + } + }); + } + } + } + + return { + linkedIssues: linkedIssueStreamlined, + linkedPrs: linkedPRStreamlined, + }; + } catch (error) { + logger.info(`Error getting linked issues or prs: ${error}`); + return `Error getting linked issues or prs: ${error}`; + } + } else { + logger.info(`No matches found`); + return { + linkedIssues: [], + linkedPrs: [], + }; + } +}; diff --git a/src/types/config.ts b/src/types/config.ts index b4dedf3d0..4f5dde5ce 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -105,6 +105,11 @@ export const CommentsSchema = Type.Object({ promotionComment: Type.String(), }); +export const AskSchema = Type.Object({ + apiKey: Type.Union([Type.String(), Type.Null()]), + tokenLimit: Type.Number(), +}); + export const CommandConfigSchema = Type.Array(CommandItemSchema); export type CommandConfig = Static; @@ -132,11 +137,30 @@ export const BotConfigSchema = Type.Object({ comments: CommentsSchema, command: CommandConfigSchema, wallet: WalletSchema, + ask: AskSchema, accessControl: AccessControlSchema, }); export type BotConfig = Static; +export const StreamlinedCommentSchema = Type.Object({ + login: Type.Optional(Type.String()), + body: Type.Optional(Type.String()), +}); + +export type StreamlinedComment = Static; + +export const GPTResponseSchema = Type.Object({ + answer: Type.Optional(Type.String()), + tokenUsage: Type.Object({ + output: Type.Optional(Type.Number()), + input: Type.Optional(Type.Number()), + total: Type.Optional(Type.Number()), + }), +}); + +export type GPTResponse = Static; + export const WideConfigSchema = Type.Object( { "evm-network-id": Type.Optional(Type.Number()), @@ -156,6 +180,8 @@ export const WideConfigSchema = Type.Object( "register-wallet-with-verification": Type.Optional(Type.Boolean()), "enable-access-control": Type.Optional(AccessControlSchema), "stale-bounty-time": Type.Optional(Type.String()), + "openai-api-key": AskSchema.apiKey, + "openai-token-limit": Type.Optional(Type.Number()), "private-key-encrypted": Type.Optional(Type.String()), }, { @@ -185,6 +211,8 @@ export const MergedConfigSchema = Type.Object({ "default-labels": Type.Array(Type.String()), "register-wallet-with-verification": Type.Boolean(), "enable-access-control": AccessControlSchema, + "openai-api-key": AskSchema.apiKey, + "openai-token-limit": Type.Number(), "stale-bounty-time": Type.String(), }); diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index c7bad1b2c..3ce69951f 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -1,3 +1,3 @@ export const ErrorDiff = (message: unknown) => { - return "```diff\n- " + message + "\n```"; + return "```diff\n! " + message + "\n```"; }; diff --git a/src/utils/private.ts b/src/utils/private.ts index 683a9014c..87a4ddf63 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -127,7 +127,7 @@ export const getWideConfig = async (context: Context) => { } } const parsedDefault: MergedConfig = DefaultConfig; - + let privateKeyDecrypted; if (parsedRepo && parsedRepo[KEY_NAME]) { privateKeyDecrypted = await getPrivateKey(parsedRepo[KEY_NAME]); @@ -158,6 +158,8 @@ export const getWideConfig = async (context: Context) => { promotionComment: mergedConfigData["promotion-comment"], registerWalletWithVerification: mergedConfigData["register-wallet-with-verification"], enableAccessControl: mergedConfigData["enable-access-control"], + openAIKey: mergedConfigData["openai-api-key"], + openAITokenLimit: mergedConfigData["openai-token-limit"], staleBountyTime: mergedConfigData["stale-bounty-time"], }; diff --git a/supabase/config.toml b/supabase/config.toml index cac964730..2708cc34f 100644 --- a/supabase/config.toml +++ b/supabase/config.toml @@ -69,4 +69,4 @@ secret = "" redirect_uri = "" # Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure, # or any other third-party OIDC providers. -url = "" +url = "" \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 68cf237fc..96647fe75 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + "@actions/core@^1.10.0", "@actions/core@^1.2.6": version "1.10.0" resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.0.tgz#44551c3c71163949a2f06e94d9ca2157a0cfac4f" @@ -11,9 +16,9 @@ uuid "^8.3.2" "@actions/http-client@^2.0.1": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.1.0.tgz#b6d8c3934727d6a50d10d19f00a711a964599a9f" - integrity sha512-BonhODnXr3amchh4qkmjPMUO8mFi/zLaaCeCAJZqch8iQqyDnVIkySjB38VHAC8IJ+bnlgfOqlhpyCUZHlQsqw== + version "2.1.1" + resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.1.1.tgz#a8e97699c315bed0ecaeaaeb640948470d4586a0" + integrity sha512-qhrkRMB40bbbLo7gF+0vu+X+UawOvQQqNAA/5Unx774RS8poaOhThDOG6BGmxvAnxhQnDp2BG/ZUm65xZILTpw== dependencies: tunnel "^0.0.6" @@ -25,59 +30,60 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" - integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== dependencies: - "@babel/highlight" "^7.22.5" + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" -"@babel/compat-data@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.5.tgz#b1f6c86a02d85d2dd3368a2b67c09add8cd0c255" - integrity sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA== +"@babel/compat-data@^7.22.9": + version "7.22.9" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730" + integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ== "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.5.tgz#d67d9747ecf26ee7ecd3ebae1ee22225fe902a89" - integrity sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg== + version "7.22.17" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.17.tgz#2f9b0b395985967203514b24ee50f9fd0639c866" + integrity sha512-2EENLmhpwplDux5PSsZnSbnSkB3tZ6QTksgO25xwEL7pIDcNOMhF5v/s6RzwjMZzZzw9Ofc30gHv5ChCC8pifQ== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.5" - "@babel/helper-compilation-targets" "^7.22.5" - "@babel/helper-module-transforms" "^7.22.5" - "@babel/helpers" "^7.22.5" - "@babel/parser" "^7.22.5" - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.5" - "@babel/types" "^7.22.5" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.22.15" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-module-transforms" "^7.22.17" + "@babel/helpers" "^7.22.15" + "@babel/parser" "^7.22.16" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.22.17" + "@babel/types" "^7.22.17" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.2.2" - semver "^6.3.0" + json5 "^2.2.3" + semver "^6.3.1" -"@babel/generator@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.5.tgz#1e7bf768688acfb05cf30b2369ef855e82d984f7" - integrity sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA== +"@babel/generator@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.15.tgz#1564189c7ec94cb8f77b5e8a90c4d200d21b2339" + integrity sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA== dependencies: - "@babel/types" "^7.22.5" + "@babel/types" "^7.22.15" "@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/helper-compilation-targets@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz#fc7319fc54c5e2fa14b2909cf3c5fd3046813e02" - integrity sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw== +"@babel/helper-compilation-targets@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" + integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== dependencies: - "@babel/compat-data" "^7.22.5" - "@babel/helper-validator-option" "^7.22.5" - browserslist "^4.21.3" + "@babel/compat-data" "^7.22.9" + "@babel/helper-validator-option" "^7.22.15" + browserslist "^4.21.9" lru-cache "^5.1.1" - semver "^6.3.0" + semver "^6.3.1" "@babel/helper-environment-visitor@^7.22.5": version "7.22.5" @@ -99,26 +105,23 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-module-imports@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c" - integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg== +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== dependencies: - "@babel/types" "^7.22.5" + "@babel/types" "^7.22.15" -"@babel/helper-module-transforms@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz#0f65daa0716961b6e96b164034e737f60a80d2ef" - integrity sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw== +"@babel/helper-module-transforms@^7.22.17": + version "7.22.17" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz#7edf129097a51ccc12443adbc6320e90eab76693" + integrity sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ== dependencies: "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-module-imports" "^7.22.5" + "@babel/helper-module-imports" "^7.22.15" "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.5" - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.5" - "@babel/types" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.15" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0": version "7.22.5" @@ -132,10 +135,10 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-split-export-declaration@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz#88cf11050edb95ed08d596f7a044462189127a08" - integrity sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ== +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== dependencies: "@babel/types" "^7.22.5" @@ -144,38 +147,38 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== -"@babel/helper-validator-identifier@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" - integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== +"@babel/helper-validator-identifier@^7.22.15", "@babel/helper-validator-identifier@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz#601fa28e4cc06786c18912dca138cec73b882044" + integrity sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ== -"@babel/helper-validator-option@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" - integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw== +"@babel/helper-validator-option@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040" + integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA== -"@babel/helpers@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.5.tgz#74bb4373eb390d1ceed74a15ef97767e63120820" - integrity sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q== +"@babel/helpers@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.15.tgz#f09c3df31e86e3ea0b7ff7556d85cdebd47ea6f1" + integrity sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw== dependencies: - "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.5" - "@babel/types" "^7.22.5" + "@babel/template" "^7.22.15" + "@babel/traverse" "^7.22.15" + "@babel/types" "^7.22.15" -"@babel/highlight@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" - integrity sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw== +"@babel/highlight@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.13.tgz#9cda839e5d3be9ca9e8c26b6dd69e7548f0cbf16" + integrity sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ== dependencies: "@babel/helper-validator-identifier" "^7.22.5" - chalk "^2.0.0" + chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.5.tgz#721fd042f3ce1896238cf1b341c77eb7dee7dbea" - integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.22.16": + version "7.22.16" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.16.tgz#180aead7f247305cce6551bea2720934e2fa2c95" + integrity sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -261,38 +264,38 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/template@^7.22.5", "@babel/template@^7.3.3": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" - integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw== +"@babel/template@^7.22.15", "@babel/template@^7.22.5", "@babel/template@^7.3.3": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/parser" "^7.22.5" - "@babel/types" "^7.22.5" + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.5.tgz#44bd276690db6f4940fdb84e1cb4abd2f729ccd1" - integrity sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.22.15", "@babel/traverse@^7.22.17": + version "7.22.17" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.17.tgz#b23c203ab3707e3be816043081b4a994fcacec44" + integrity sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg== dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.5" + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.22.15" "@babel/helper-environment-visitor" "^7.22.5" "@babel/helper-function-name" "^7.22.5" "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.5" - "@babel/parser" "^7.22.5" - "@babel/types" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.22.16" + "@babel/types" "^7.22.17" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.3.3": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" - integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.17", "@babel/types@^7.22.5", "@babel/types@^7.3.3": + version "7.22.17" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.17.tgz#f753352c4610ffddf9c8bc6823f9ff03e2303eee" + integrity sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg== dependencies: "@babel/helper-string-parser" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.15" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": @@ -309,13 +312,13 @@ minimist "^1.2.0" "@commitlint/cli@^17.4.3": - version "17.6.6" - resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-17.6.6.tgz#416da9c45901323e5bf931aa1eac5995a3aa251c" - integrity sha512-sTKpr2i/Fjs9OmhU+beBxjPavpnLSqZaO6CzwKVq2Tc4UYVTMFgpKOslDhUBVlfAUBfjVO8ParxC/MXkIOevEA== + version "17.7.1" + resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-17.7.1.tgz#f3ab35bd38d82fcd4ab03ec5a1e9db26d57fe1b0" + integrity sha512-BCm/AT06SNCQtvFv921iNhudOHuY16LswT0R3OeolVGLk8oP+Rk9TfQfgjH7QPMjhvp76bNqGFEcpKojxUNW1g== dependencies: "@commitlint/format" "^17.4.4" - "@commitlint/lint" "^17.6.6" - "@commitlint/load" "^17.5.0" + "@commitlint/lint" "^17.7.0" + "@commitlint/load" "^17.7.1" "@commitlint/read" "^17.5.1" "@commitlint/types" "^17.4.4" execa "^5.0.0" @@ -325,24 +328,24 @@ yargs "^17.0.0" "@commitlint/config-conventional@^17.4.3": - version "17.6.6" - resolved "https://registry.yarnpkg.com/@commitlint/config-conventional/-/config-conventional-17.6.6.tgz#5452aa601d34503b88530ba38432116bcffdd005" - integrity sha512-phqPz3BDhfj49FUYuuZIuDiw+7T6gNAEy7Yew1IBHqSohVUCWOK2FXMSAExzS2/9X+ET93g0Uz83KjiHDOOFag== + version "17.7.0" + resolved "https://registry.yarnpkg.com/@commitlint/config-conventional/-/config-conventional-17.7.0.tgz#1bbf2bce7851db63c1a8aa8d924277ad4938247e" + integrity sha512-iicqh2o6et+9kWaqsQiEYZzfLbtoWv9uZl8kbI8EGfnc0HeGafQBF7AJ0ylN9D/2kj6txltsdyQs8+2fTMwWEw== dependencies: - conventional-changelog-conventionalcommits "^5.0.0" + conventional-changelog-conventionalcommits "^6.1.0" -"@commitlint/config-validator@^17.4.4": - version "17.4.4" - resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-17.4.4.tgz#d0742705719559a101d2ee49c0c514044af6d64d" - integrity sha512-bi0+TstqMiqoBAQDvdEP4AFh0GaKyLFlPPEObgI29utoKEYoPQTvF0EYqIwYYLEoJYhj5GfMIhPHJkTJhagfeg== +"@commitlint/config-validator@^17.6.7": + version "17.6.7" + resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-17.6.7.tgz#c664d42a1ecf5040a3bb0843845150f55734df41" + integrity sha512-vJSncmnzwMvpr3lIcm0I8YVVDJTzyjy7NZAeXbTXy+MPUdAr9pKyyg7Tx/ebOQ9kqzE6O9WT6jg2164br5UdsQ== dependencies: "@commitlint/types" "^17.4.4" ajv "^8.11.0" -"@commitlint/ensure@^17.4.4": - version "17.4.4" - resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-17.4.4.tgz#a36e7719bdb9c2b86c8b8c2e852b463a7bfda5fa" - integrity sha512-AHsFCNh8hbhJiuZ2qHv/m59W/GRE9UeOXbkOqxYMNNg9pJ7qELnFcwj5oYpa6vzTSHtPGKf3C2yUFNy1GGHq6g== +"@commitlint/ensure@^17.6.7": + version "17.6.7" + resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-17.6.7.tgz#77a77a0c05e6a1c34589f59e82e6cb937101fc4b" + integrity sha512-mfDJOd1/O/eIb/h4qwXzUxkmskXDL9vNPnZ4AKYKiZALz4vHzwMxBSYtyL2mUIDeU9DRSpEUins8SeKtFkYHSw== dependencies: "@commitlint/types" "^17.4.4" lodash.camelcase "^4.3.0" @@ -364,34 +367,34 @@ "@commitlint/types" "^17.4.4" chalk "^4.1.0" -"@commitlint/is-ignored@^17.6.6": - version "17.6.6" - resolved "https://registry.yarnpkg.com/@commitlint/is-ignored/-/is-ignored-17.6.6.tgz#b1c869757bdea659aa582669ea0066798ed6a17e" - integrity sha512-4Fw875faAKO+2nILC04yW/2Vy/wlV3BOYCSQ4CEFzriPEprc1Td2LILmqmft6PDEK5Sr14dT9tEzeaZj0V56Gg== +"@commitlint/is-ignored@^17.7.0": + version "17.7.0" + resolved "https://registry.yarnpkg.com/@commitlint/is-ignored/-/is-ignored-17.7.0.tgz#df9b284420bdb1aed5fdb2be44f4e98cc4826014" + integrity sha512-043rA7m45tyEfW7Zv2vZHF++176MLHH9h70fnPoYlB1slKBeKl8BwNIlnPg4xBdRBVNPaCqvXxWswx2GR4c9Hw== dependencies: "@commitlint/types" "^17.4.4" - semver "7.5.2" + semver "7.5.4" -"@commitlint/lint@^17.6.6": - version "17.6.6" - resolved "https://registry.yarnpkg.com/@commitlint/lint/-/lint-17.6.6.tgz#d7ff64b6783f2bda56526195a66e6bb587e1fe1a" - integrity sha512-5bN+dnHcRLkTvwCHYMS7Xpbr+9uNi0Kq5NR3v4+oPNx6pYXt8ACuw9luhM/yMgHYwW0ajIR20wkPAFkZLEMGmg== +"@commitlint/lint@^17.7.0": + version "17.7.0" + resolved "https://registry.yarnpkg.com/@commitlint/lint/-/lint-17.7.0.tgz#33f831298dc43679e4de6b088aea63d1f884c7e7" + integrity sha512-TCQihm7/uszA5z1Ux1vw+Nf3yHTgicus/+9HiUQk+kRSQawByxZNESeQoX9ujfVd3r4Sa+3fn0JQAguG4xvvbA== dependencies: - "@commitlint/is-ignored" "^17.6.6" - "@commitlint/parse" "^17.6.5" - "@commitlint/rules" "^17.6.5" + "@commitlint/is-ignored" "^17.7.0" + "@commitlint/parse" "^17.7.0" + "@commitlint/rules" "^17.7.0" "@commitlint/types" "^17.4.4" -"@commitlint/load@^17.5.0": - version "17.5.0" - resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-17.5.0.tgz#be45dbbb50aaf5eb7e8e940e1e0d6171d1426bab" - integrity sha512-l+4W8Sx4CD5rYFsrhHH8HP01/8jEP7kKf33Xlx2Uk2out/UKoKPYMOIRcDH5ppT8UXLMV+x6Wm5osdRKKgaD1Q== +"@commitlint/load@^17.7.1": + version "17.7.1" + resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-17.7.1.tgz#0723b11723a20043a304a74960602dead89b5cdd" + integrity sha512-S/QSOjE1ztdogYj61p6n3UbkUvweR17FQ0zDbNtoTLc+Hz7vvfS7ehoTMQ27hPSjVBpp7SzEcOQu081RLjKHJQ== dependencies: - "@commitlint/config-validator" "^17.4.4" + "@commitlint/config-validator" "^17.6.7" "@commitlint/execute-rule" "^17.4.0" - "@commitlint/resolve-extends" "^17.4.4" + "@commitlint/resolve-extends" "^17.6.7" "@commitlint/types" "^17.4.4" - "@types/node" "*" + "@types/node" "20.4.7" chalk "^4.1.0" cosmiconfig "^8.0.0" cosmiconfig-typescript-loader "^4.0.0" @@ -407,14 +410,14 @@ resolved "https://registry.yarnpkg.com/@commitlint/message/-/message-17.4.2.tgz#f4753a79701ad6db6db21f69076e34de6580e22c" integrity sha512-3XMNbzB+3bhKA1hSAWPCQA3lNxR4zaeQAQcHj0Hx5sVdO6ryXtgUBGGv+1ZCLMgAPRixuc6en+iNAzZ4NzAa8Q== -"@commitlint/parse@^17.6.5": - version "17.6.5" - resolved "https://registry.yarnpkg.com/@commitlint/parse/-/parse-17.6.5.tgz#7b84b328a6a94ca08ab7c98c491d9d3dab68f09d" - integrity sha512-0zle3bcn1Hevw5Jqpz/FzEWNo2KIzUbc1XyGg6WrWEoa6GH3A1pbqNF6MvE6rjuy6OY23c8stWnb4ETRZyN+Yw== +"@commitlint/parse@^17.7.0": + version "17.7.0" + resolved "https://registry.yarnpkg.com/@commitlint/parse/-/parse-17.7.0.tgz#aacb2d189e50ab8454154b1df150aaf20478ae47" + integrity sha512-dIvFNUMCUHqq5Abv80mIEjLVfw8QNuA4DS7OWip4pcK/3h5wggmjVnlwGCDvDChkw2TjK1K6O+tAEV78oxjxag== dependencies: "@commitlint/types" "^17.4.4" - conventional-changelog-angular "^5.0.11" - conventional-commits-parser "^3.2.2" + conventional-changelog-angular "^6.0.0" + conventional-commits-parser "^4.0.0" "@commitlint/read@^17.5.1": version "17.5.1" @@ -427,24 +430,24 @@ git-raw-commits "^2.0.11" minimist "^1.2.6" -"@commitlint/resolve-extends@^17.4.4": - version "17.4.4" - resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-17.4.4.tgz#8f931467dea8c43b9fe38373e303f7c220de6fdc" - integrity sha512-znXr1S0Rr8adInptHw0JeLgumS11lWbk5xAWFVno+HUFVN45875kUtqjrI6AppmD3JI+4s0uZlqqlkepjJd99A== +"@commitlint/resolve-extends@^17.6.7": + version "17.6.7" + resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-17.6.7.tgz#9c53a4601c96ab2dd20b90fb35c988639307735d" + integrity sha512-PfeoAwLHtbOaC9bGn/FADN156CqkFz6ZKiVDMjuC2N5N0740Ke56rKU7Wxdwya8R8xzLK9vZzHgNbuGhaOVKIg== dependencies: - "@commitlint/config-validator" "^17.4.4" + "@commitlint/config-validator" "^17.6.7" "@commitlint/types" "^17.4.4" import-fresh "^3.0.0" lodash.mergewith "^4.6.2" resolve-from "^5.0.0" resolve-global "^1.0.0" -"@commitlint/rules@^17.6.5": - version "17.6.5" - resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-17.6.5.tgz#fabcacdde923e26ac5ef90d4b3f8fc05526bbaa1" - integrity sha512-uTB3zSmnPyW2qQQH+Dbq2rekjlWRtyrjDo4aLFe63uteandgkI+cc0NhhbBAzcXShzVk0qqp8SlkQMu0mgHg/A== +"@commitlint/rules@^17.7.0": + version "17.7.0" + resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-17.7.0.tgz#b97a4933c5cba11a659a19ee467f6f000f31533e" + integrity sha512-J3qTh0+ilUE5folSaoK91ByOb8XeQjiGcdIdiB/8UT1/Rd1itKo0ju/eQVGyFzgTMYt8HrDJnGTmNWwcMR1rmA== dependencies: - "@commitlint/ensure" "^17.4.4" + "@commitlint/ensure" "^17.6.7" "@commitlint/message" "^17.4.2" "@commitlint/to-lines" "^17.4.0" "@commitlint/types" "^17.4.4" @@ -484,12 +487,12 @@ "@esbuild-kit/core-utils" "^3.0.0" get-tsconfig "^4.4.0" -"@esbuild-kit/core-utils@^3.0.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@esbuild-kit/core-utils/-/core-utils-3.1.0.tgz#49945d533dbd5e1b7620aa0fc522c15e6ec089c5" - integrity sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw== +"@esbuild-kit/core-utils@^3.0.0", "@esbuild-kit/core-utils@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@esbuild-kit/core-utils/-/core-utils-3.2.2.tgz#ac3fe38d6ddcb3aa4658425034bb7a9cefa83495" + integrity sha512-Ub6LaRaAgF80dTSzUdXpFLM1pVDdmEVB9qb5iAzSpyDlX/mfJTFGOnZ516O05p5uWWteNviMKi4PAyEuRxI5gA== dependencies: - esbuild "~0.17.6" + esbuild "~0.18.20" source-map-support "^0.5.21" "@esbuild-kit/esm-loader@^2.5.5": @@ -500,115 +503,115 @@ "@esbuild-kit/core-utils" "^3.0.0" get-tsconfig "^4.4.0" -"@esbuild/android-arm64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd" - integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA== - -"@esbuild/android-arm@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.19.tgz#5898f7832c2298bc7d0ab53701c57beb74d78b4d" - integrity sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A== - -"@esbuild/android-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.19.tgz#658368ef92067866d95fb268719f98f363d13ae1" - integrity sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww== - -"@esbuild/darwin-arm64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz#584c34c5991b95d4d48d333300b1a4e2ff7be276" - integrity sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg== - -"@esbuild/darwin-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz#7751d236dfe6ce136cce343dce69f52d76b7f6cb" - integrity sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw== - -"@esbuild/freebsd-arm64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz#cacd171665dd1d500f45c167d50c6b7e539d5fd2" - integrity sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ== - -"@esbuild/freebsd-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz#0769456eee2a08b8d925d7c00b79e861cb3162e4" - integrity sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ== - -"@esbuild/linux-arm64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz#38e162ecb723862c6be1c27d6389f48960b68edb" - integrity sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg== - -"@esbuild/linux-arm@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz#1a2cd399c50040184a805174a6d89097d9d1559a" - integrity sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA== - -"@esbuild/linux-ia32@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz#e28c25266b036ce1cabca3c30155222841dc035a" - integrity sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ== - -"@esbuild/linux-loong64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz#0f887b8bb3f90658d1a0117283e55dbd4c9dcf72" - integrity sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ== - -"@esbuild/linux-mips64el@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz#f5d2a0b8047ea9a5d9f592a178ea054053a70289" - integrity sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A== - -"@esbuild/linux-ppc64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz#876590e3acbd9fa7f57a2c7d86f83717dbbac8c7" - integrity sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg== - -"@esbuild/linux-riscv64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz#7f49373df463cd9f41dc34f9b2262d771688bf09" - integrity sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA== - -"@esbuild/linux-s390x@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz#e2afd1afcaf63afe2c7d9ceacd28ec57c77f8829" - integrity sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q== - -"@esbuild/linux-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz#8a0e9738b1635f0c53389e515ae83826dec22aa4" - integrity sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw== - -"@esbuild/netbsd-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz#c29fb2453c6b7ddef9a35e2c18b37bda1ae5c462" - integrity sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q== - -"@esbuild/openbsd-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz#95e75a391403cb10297280d524d66ce04c920691" - integrity sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g== - -"@esbuild/sunos-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz#722eaf057b83c2575937d3ffe5aeb16540da7273" - integrity sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg== - -"@esbuild/win32-arm64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz#9aa9dc074399288bdcdd283443e9aeb6b9552b6f" - integrity sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag== - -"@esbuild/win32-ia32@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz#95ad43c62ad62485e210f6299c7b2571e48d2b03" - integrity sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw== - -"@esbuild/win32-x64@0.17.19": - version "0.17.19" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz#8cfaf2ff603e9aabb910e9c0558c26cf32744061" - integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA== +"@esbuild/android-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622" + integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ== + +"@esbuild/android-arm@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682" + integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw== + +"@esbuild/android-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2" + integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg== + +"@esbuild/darwin-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1" + integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA== + +"@esbuild/darwin-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d" + integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ== + +"@esbuild/freebsd-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54" + integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw== + +"@esbuild/freebsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e" + integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ== + +"@esbuild/linux-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0" + integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA== + +"@esbuild/linux-arm@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0" + integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg== + +"@esbuild/linux-ia32@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7" + integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA== + +"@esbuild/linux-loong64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d" + integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg== + +"@esbuild/linux-mips64el@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231" + integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ== + +"@esbuild/linux-ppc64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb" + integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA== + +"@esbuild/linux-riscv64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6" + integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A== + +"@esbuild/linux-s390x@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071" + integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ== + +"@esbuild/linux-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338" + integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w== + +"@esbuild/netbsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1" + integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A== + +"@esbuild/openbsd-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae" + integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg== + +"@esbuild/sunos-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d" + integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ== + +"@esbuild/win32-arm64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9" + integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg== + +"@esbuild/win32-ia32@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102" + integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g== + +"@esbuild/win32-x64@0.18.20": + version "0.18.20" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d" + integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ== "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" @@ -617,19 +620,19 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.4.0": - version "4.5.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" - integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== +"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": + version "4.8.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.8.0.tgz#11195513186f68d42fbf449f9a7136b2c0c92005" + integrity sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg== -"@eslint/eslintrc@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz#4910db5505f4d503f27774bf356e3704818a0331" - integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ== +"@eslint/eslintrc@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" + integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.5.2" + espree "^9.6.0" globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" @@ -637,10 +640,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.43.0": - version "8.43.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.43.0.tgz#559ca3d9ddbd6bf907ad524320a0d14b85586af0" - integrity sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg== +"@eslint/js@8.49.0": + version "8.49.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.49.0.tgz#86f79756004a97fa4df866835093f1df3d03c333" + integrity sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w== "@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.7.0": version "5.7.0" @@ -989,10 +992,10 @@ resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-2.1.0.tgz#66aff77094dc3080bd5df44ec63881f2676eb020" integrity sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q== -"@humanwhocodes/config-array@^0.11.10": - version "0.11.10" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" - integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== +"@humanwhocodes/config-array@^0.11.11": + version "0.11.11" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.11.tgz#88a04c570dbbc7dd943e4712429c3df09bc32844" + integrity sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -1221,261 +1224,260 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jimp/bmp@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/bmp/-/bmp-0.22.8.tgz#19ce17bfef7f3d34a0dbe220d640f384d28178bc" - integrity sha512-JEMKgM1AEvvWfn9ZCHn62nK+QCE3Pb/ZhPdL3NF0ZgKNww6pqOmo6KqXzqY18JLB7c0epuTp4GPDPDhOh/ou1g== +"@jimp/bmp@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/bmp/-/bmp-0.22.10.tgz#e4fe8934a83f1e677cbfd74ad22a684bf1aad529" + integrity sha512-1UXRl1Nw1KptZ1r0ANqtXOst9vGH51dq7keVKQzyyTO2lz4dOaezS9StuSTNh+RmiHg/SVPaFRpPfB0S/ln4Kg== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" bmp-js "^0.1.0" -"@jimp/core@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/core/-/core-0.22.8.tgz#6851513756e81887864d64d1786f212795076065" - integrity sha512-vkN28aFikzQieA6bGxN+qe20pseCAemCyUI0YmRkJIArlb6OujtAwWAKyokv2lylV56bq8EQGIz+Y30OXUnRqg== +"@jimp/core@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/core/-/core-0.22.10.tgz#a106e719a9e1bc668c9595065a0872767cda3934" + integrity sha512-ZKyrehVy6wu1PnBXIUpn/fXmyMRQiVSbvHDubgXz4bfTOao3GiOurKHjByutQIgozuAN6ZHWiSge1dKA+dex3w== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" any-base "^1.1.0" buffer "^5.2.0" exif-parser "^0.1.12" file-type "^16.5.4" isomorphic-fetch "^3.0.0" - mkdirp "^2.1.3" pixelmatch "^4.0.2" tinycolor2 "^1.6.0" -"@jimp/custom@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/custom/-/custom-0.22.8.tgz#098cee27bb3e460d24cdcc6774c1680f164b5e50" - integrity sha512-u6lP9x/HNeGHB0Oojv4c2mhuDvn7G0ikzYbK4IKLsH4HzHxt62faMjBzQMcFhKJhR6UiiKE/jiHrhGvBT/fMkw== +"@jimp/custom@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/custom/-/custom-0.22.10.tgz#621f3ec418c59c78ca43c5bc6f91a467e48a7a87" + integrity sha512-sPZkUYe1hu0iIgNisjizxPJqq2vaaKvkCkPoXq2U6UV3ZA1si/WVdrg25da3IcGIEV+83AoHgM8TvqlLgrCJsg== dependencies: - "@jimp/core" "^0.22.8" + "@jimp/core" "^0.22.10" -"@jimp/gif@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/gif/-/gif-0.22.8.tgz#6692a9117fb4b25620d92327fa305dd95cd57334" - integrity sha512-I0l6koS67IPU40RPxCJTD1NvePEd8vUIHTejx1ly0jrjGnumbqdarAlBUkDrKfPPc+Fnqp84hBbSN1w5hNPT6w== +"@jimp/gif@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/gif/-/gif-0.22.10.tgz#fc47738edc5f5327a0c023ad40e89417fdb5ef60" + integrity sha512-yEX2dSpamvkSx1PPDWGnKeWDrBz0vrCKjVG/cn4Zr68MRRT75tbZIeOrBa+RiUpY3ho5ix7d36LkYvt3qfUIhQ== dependencies: - "@jimp/utils" "^0.22.8" - gifwrap "^0.9.2" + "@jimp/utils" "^0.22.10" + gifwrap "^0.10.1" omggif "^1.0.9" -"@jimp/jpeg@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/jpeg/-/jpeg-0.22.8.tgz#182c41108833bdc8c88598ef4c11bf4f197228eb" - integrity sha512-hLXrQ7/0QiUhAVAF10dfGCSq3hvyqjKltlpu/87b3wqMDKe9KdvhX1AJHiUUrAbJv1fAcnOmQGTyXGuySa1D6A== +"@jimp/jpeg@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/jpeg/-/jpeg-0.22.10.tgz#b4aba85d607d598d5a4ce0c66cefe69a8fc45c26" + integrity sha512-6bu98pAcVN4DY2oiDLC4TOgieX/lZrLd1tombWZOFCN5PBmqaHQxm7IUmT+Wj4faEvh8QSHgVLSA+2JQQRJWVA== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" jpeg-js "^0.4.4" -"@jimp/plugin-blit@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-blit/-/plugin-blit-0.22.8.tgz#b7ea7cbcbb0d7da87fb4124f0129ee539bf5ae49" - integrity sha512-rQ19txVCKIwo74HtgFodFt4//0ATPCJK+f24riqzb+nx+1JaOo1xRvpJqg4moirHwKR2fhwdDxmY7KX20kCeYA== +"@jimp/plugin-blit@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-blit/-/plugin-blit-0.22.10.tgz#c351a27d52d8273b61d4f3cd68a9b73b03dd7b14" + integrity sha512-6EI8Sl+mxYHEIy6Yteh6eknD+EZguKpNdr3sCKxNezmLR0+vK99vHcllo6uGSjXXiwtwS67Xqxn8SsoatL+UJQ== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-blur@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-blur/-/plugin-blur-0.22.8.tgz#d561de68d7154175b7a443d12949ba7d9fe255ca" - integrity sha512-GWbNK3YW6k2EKiGJdpAFEr0jezPBtiVxj2wG/lCPuWJz7KmzSSN99hQjIy73xQxoBCRdALfJlkhe3leFNRueSQ== +"@jimp/plugin-blur@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-blur/-/plugin-blur-0.22.10.tgz#22a67bb8b21403ac28b44bef6cf9a934846fec83" + integrity sha512-4XRTWuPVdMXJeclJMisXPGizeHtTryVaVV5HnuQXpKqIZtzXReCCpNGH8q/i0kBQOQMXhGWS3mpqOEwtpPePKw== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-circle@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-circle/-/plugin-circle-0.22.8.tgz#2182999a77d0fab7d9eaad94815524104307015f" - integrity sha512-qPCw8XFW8opT89ciFDuvs+eB3EB1mZIJWVajD2qAlprHiE7YGr34TkM7N5MNr3qZ1pJgkYdW6+HbBrJwBaonqw== +"@jimp/plugin-circle@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-circle/-/plugin-circle-0.22.10.tgz#2a4c81b5c1a49f583d2d5090496c1ecb29c52c1a" + integrity sha512-mhcwTO1ywRxiCgtLGge6tDDIDPlX6qkI3CY+BjgGG/XhVHccCddXgOGLdlf+5OuKIEF2Nqs0V01LQEQIJFTmEw== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-color@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-color/-/plugin-color-0.22.8.tgz#3f64888b28438ac986a97c672babe6abec886cb3" - integrity sha512-ogkbg6rpDVH/mMLgAQKg17z3oZE0VN7ZWxNoH12fUHchqKz1I57zpa65fxZe2I8T5Xz97HR3x+7V7oI8qQGdSA== +"@jimp/plugin-color@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-color/-/plugin-color-0.22.10.tgz#cf053aa30eb3bf7df3cceb8547ef78a841bfcd72" + integrity sha512-e4t3L7Kedd96E0x1XjsTM6NcgulKUU66HdFTao7Tc9FYJRFSlttARZ/C6LEryGDm/i69R6bJEpo7BkNz0YL55Q== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" tinycolor2 "^1.6.0" -"@jimp/plugin-contain@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-contain/-/plugin-contain-0.22.8.tgz#5afad638558ccf69abfac0c85b6354534e22c0eb" - integrity sha512-oiaPLdJt9Dk+XEEhM/OU3lFemM51mA9NgMCAdburSCjDzKacJYBGFSHjTOhXzcxOie/ZDpOYN/UzFGKy8Dgl9A== +"@jimp/plugin-contain@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-contain/-/plugin-contain-0.22.10.tgz#5302e088a09884ff0ae6656e0e682e2e487c2199" + integrity sha512-eP8KrzctuEoqibQAxi9WhbnoRosydhiwg+IYya3dKuKDBTrD9UHt+ERlPQ/lTNWHzV/l4S1ntV3r9s9saJgsXA== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-cover@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-cover/-/plugin-cover-0.22.8.tgz#b7e2aa869ff3d68c6b3d68e46f9ddb309bf5fa8a" - integrity sha512-mO68w1m/LhfuHU8LKHY05a4/hhWnY4t+T+8JCw9t+5yfzA4+LofBZZKtFtWgwf/QGe1y3X2rtUU/avAzDUKyyA== +"@jimp/plugin-cover@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-cover/-/plugin-cover-0.22.10.tgz#746b25bbea92aa7f9b130feca5af02717122e6d5" + integrity sha512-kJCwL5T1igfa0InCfkE7bBeqg26m46aoRt10ug+rvm11P6RrvRMGrgINFyIKB+mnB7CiyBN/MOula1CvLhSInQ== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-crop@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-crop/-/plugin-crop-0.22.8.tgz#2683de20d34eac0d457a5d231a0e3885023a2192" - integrity sha512-ns4oH0h0gezYsbuH8RThcMLY5uTLk/vnqOVjWCehMHEzxi0DHMWCmpcb6bC//vJ+XFNhtVGn1ALN7+ROmPrj+A== +"@jimp/plugin-crop@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-crop/-/plugin-crop-0.22.10.tgz#6204fd6be751d7edb64a86ab788ba762843b9877" + integrity sha512-BOZ+YGaZlhU7c5ye65RxikicXH0Ki0It6/XHISvipR5WZrfjLjL2Ke20G+AGnwBQc76gKenVcMXVUCnEjtZV+Q== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-displace@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-displace/-/plugin-displace-0.22.8.tgz#d29992956fcdb01ab860bb00dd923964e88540f0" - integrity sha512-Cj8nHYgsdFynOIx3dbbiVwRuZn3xO+RVfwkTRy0JBye+K2AU8SQJS+hSFNMQFTZt5djivh6kh0TzvR/6LkOd1w== +"@jimp/plugin-displace@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-displace/-/plugin-displace-0.22.10.tgz#6dc277c84c0c6b2c2d793271ddf45b61284cb043" + integrity sha512-llNiWWMTKISDXt5+cXI0GaFmZWAjlT+4fFLYf4eXquuL/9wZoQsEBhv2GdGd48mkiS8jZq1Nnb2Q4ehEPTvrzw== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-dither@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-dither/-/plugin-dither-0.22.8.tgz#75d31db459852bd6c2caf10ff74bc7340c9d3bf5" - integrity sha512-oE0Us/6bEgrgEg56plU3jSBzvB9iGhweKUHmxYMWnQbFCHP4mNCtPAs8+Fmq6c+m98ZgBgRcrJTnC7lphHkGyw== +"@jimp/plugin-dither@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-dither/-/plugin-dither-0.22.10.tgz#9cbad07fb16d2dcb88d86c16d5437dee9232426a" + integrity sha512-05WLmeV5M+P/0FS+bWf13hMew2X0oa8w9AtmevL2UyA/5GqiyvP2Xm5WfGQ8oFiiMvpnL6RFomJQOZtWca0C2w== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-fisheye@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.8.tgz#980bd252ae9ebe903256fc238f224d7deb067813" - integrity sha512-bWvYY/nfMcKclWEaRyAir+YsT6C5St823HUQAsewZowTrJmme+w4U2a6InsryTHUL01BBcV5BLH0aDHuV3StvA== +"@jimp/plugin-fisheye@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.10.tgz#94cbb32947d24cdd596f7259754e390e69c3e7a6" + integrity sha512-InjiXvc7Gkzrx8VWtU97kDqV7ENnhHGPULymJWeZaF2aicud9Fpk4iCtd/DcZIrk7Cbe60A8RwNXN00HXIbSCg== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-flip@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-flip/-/plugin-flip-0.22.8.tgz#c359436260455af0ec4156d9823a55b75b776d94" - integrity sha512-0NFTNzjsdmOQkaIkNjZqO3/yU4SQb9nnWQXsLS1fFo+9QrIL5v8vVkXpk/rhiND6PyTj2mMTNjOa76GuZcC+iQ== +"@jimp/plugin-flip@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-flip/-/plugin-flip-0.22.10.tgz#58f9e05c5038d1ab849bda41cee4f0416fe07fb5" + integrity sha512-42GkGtTHWnhnwTMPVK/kXObZbkYIpQWfuIfy5EMEMk6zRj05zpv4vsjkKWfuemweZINwfvD7wDJF7FVFNNcZZg== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-gaussian@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.8.tgz#bd52b0944055afa9344496af9a1f05c8d7127ded" - integrity sha512-E/f14aLzCS50QAM7K+InI9V61KVy/Zx52vy7Jjfo1h7qKhQHss3PYaydaH0N6qlXRNeXgh+4/32P9JfieLMcdw== +"@jimp/plugin-gaussian@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.10.tgz#69effed5dccd11eada36262bd65fbaa06bd8be84" + integrity sha512-ykrG/6lTp9Q5YA8jS5XzwMHtRxb9HOFMgtmnrUZ8kU+BK8REecfy9Ic5BUEOjCYvS1a/xLsnrZQU07iiYxBxFg== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-invert@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-invert/-/plugin-invert-0.22.8.tgz#d52c4c735720359d942a600827693b2e097c61a7" - integrity sha512-UauP39FF2cwbA5VU+Tz9VlNa9rtULPSHZb0Huwcjqjm9/G/xVN69VJ8+RKiFC4zM1/kYAUp/6IRwPa6qdKJpSw== +"@jimp/plugin-invert@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-invert/-/plugin-invert-0.22.10.tgz#370b4ce4634b3e2c5fbbe88270a74f5673c765bb" + integrity sha512-d8j9BlUJYs/c994t4azUWSWmQq4LLPG4ecm8m6SSNqap+S/HlVQGqjYhJEBbY9EXkOTYB9vBL9bqwSM1Rr6paA== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-mask@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-mask/-/plugin-mask-0.22.8.tgz#80adff958c1cec3d4727a21018f4f7062a697394" - integrity sha512-bhg5+3i8x1CmYj6cjvPBQZLwZEI3iK3gJWF25ZHF+12d3cqDuJngtr8oRQOQLlAgvKmrj9FXIiEPDczUI9cnWQ== +"@jimp/plugin-mask@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-mask/-/plugin-mask-0.22.10.tgz#6404f54a782c952fecf7b6ae0f3d894d4fc99c51" + integrity sha512-yRBs1230XZkz24uFTdTcSlZ0HXZpIWzM3iFQN56MzZ7USgdVZjPPDCQ8I9RpqfZ36nDflQkUO0wV7ucsi4ogow== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-normalize@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-normalize/-/plugin-normalize-0.22.8.tgz#e60e864c7b0270920517e6276d847c4604154051" - integrity sha512-Yg5nreAR1JYuSObu3ExlgaLxVeW6VvjVL5qFwiPFxSNlG8JIwL1Ir3K3ChSnnvymyZvJMHb6YKTYNfXKw5Da6g== +"@jimp/plugin-normalize@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-normalize/-/plugin-normalize-0.22.10.tgz#6a8d0f57a8f90a3ec15f2391c338b94f3eb49e72" + integrity sha512-Wk9GX6eJMchX/ZAazVa70Fagu+OXMvHiPY+HrcEwcclL+p1wo8xAHEsf9iKno7Ja4EU9lLhbBRY5hYJyiKMEkg== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" -"@jimp/plugin-print@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-print/-/plugin-print-0.22.8.tgz#fa1e6659a1cc34dddceee33e887cbf6fc0d99038" - integrity sha512-86O5ejCDi543IYl0TykSmNWErzAjEYhiAxNQb2F7rFRT38WJYNVsvJ6QhxhDQHKxSmF5iwmqbk0jYk5Wp2Z1kw== +"@jimp/plugin-print@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-print/-/plugin-print-0.22.10.tgz#8c96df70851c1ead0b79c8ea74c8411445d921ca" + integrity sha512-1U3VloIR+beE1kWPdGEJMiE2h1Do29iv3w8sBbvPyRP4qXxRFcDpmCGtctsrKmb1krlBFlj8ubyAY90xL+5n9w== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" load-bmfont "^1.4.1" -"@jimp/plugin-resize@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-resize/-/plugin-resize-0.22.8.tgz#d111c164512fb54c096da55dcabf681a5b57d458" - integrity sha512-kg8ArQRPqv/iU3DWNXCa8kcVIhoq64Ze0aGCAeFLKlAq/59f5pzAci6m6vV4L/uOVdYmUa9/kYwIFY6RWKpfzQ== - dependencies: - "@jimp/utils" "^0.22.8" - -"@jimp/plugin-rotate@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-rotate/-/plugin-rotate-0.22.8.tgz#3b61655a1a38600e01c73210c201c690041c3bcb" - integrity sha512-9a+VPZWMN/Cks76wf8LjM5RVA3ntP9+NAdsS1SZhhXel7U3Re/dWMouIEbo3QTt6K+igRo4txUCdZiw4ZucvkQ== - dependencies: - "@jimp/utils" "^0.22.8" - -"@jimp/plugin-scale@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-scale/-/plugin-scale-0.22.8.tgz#b5a4f798aebefa914e942a0feae6dc179230d974" - integrity sha512-dQS4pG6DX6endu8zUpvBBOEtGC+ljDDDNw0scSXY71TxyQdNo5Ro0apfsppjmuAr8rNotRkfyxbITKkXQDRUDQ== - dependencies: - "@jimp/utils" "^0.22.8" - -"@jimp/plugin-shadow@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-shadow/-/plugin-shadow-0.22.8.tgz#ba6c14074aafbc47c550878044e7c18498c91907" - integrity sha512-HyAhr7OblTQh+BoKHQg4qbS9MweNlH77yfpBqUEyDtfyjI5r06+5chf1ZdLRIPEWv/BdCfdI/g81Wv69muCMwA== - dependencies: - "@jimp/utils" "^0.22.8" - -"@jimp/plugin-threshold@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugin-threshold/-/plugin-threshold-0.22.8.tgz#63b96ce4f82250ef993bfb7e88f12dae94e17a04" - integrity sha512-ZmkfH0PtjvF1UcKsjw0H7V6r+LC0yKzEfg76Jhs2nIqIgsxsSOVfHwS7z0/1IWnyXxSw36m+NjCAotNHRILGmA== - dependencies: - "@jimp/utils" "^0.22.8" - -"@jimp/plugins@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/plugins/-/plugins-0.22.8.tgz#07683e350d3578b319580bf445650df88fb7eccd" - integrity sha512-ieI2+kCpmIfjwVlT7B67ULCzxMizfj7LspJh9HnIZCDXQB9GBOZ9KImLYc75Krae0dP/3FR7FglLiSI7fkOHbw== - dependencies: - "@jimp/plugin-blit" "^0.22.8" - "@jimp/plugin-blur" "^0.22.8" - "@jimp/plugin-circle" "^0.22.8" - "@jimp/plugin-color" "^0.22.8" - "@jimp/plugin-contain" "^0.22.8" - "@jimp/plugin-cover" "^0.22.8" - "@jimp/plugin-crop" "^0.22.8" - "@jimp/plugin-displace" "^0.22.8" - "@jimp/plugin-dither" "^0.22.8" - "@jimp/plugin-fisheye" "^0.22.8" - "@jimp/plugin-flip" "^0.22.8" - "@jimp/plugin-gaussian" "^0.22.8" - "@jimp/plugin-invert" "^0.22.8" - "@jimp/plugin-mask" "^0.22.8" - "@jimp/plugin-normalize" "^0.22.8" - "@jimp/plugin-print" "^0.22.8" - "@jimp/plugin-resize" "^0.22.8" - "@jimp/plugin-rotate" "^0.22.8" - "@jimp/plugin-scale" "^0.22.8" - "@jimp/plugin-shadow" "^0.22.8" - "@jimp/plugin-threshold" "^0.22.8" +"@jimp/plugin-resize@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-resize/-/plugin-resize-0.22.10.tgz#d968f0167069c9f7e612bceefdbcc4b3c65934b5" + integrity sha512-ixomxVcnAONXDgaq0opvAx4UAOiEhOA/tipuhFFOvPKFd4yf1BAnEviB5maB0SBHHkJXPUSzDp/73xVTMGSe7g== + dependencies: + "@jimp/utils" "^0.22.10" + +"@jimp/plugin-rotate@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-rotate/-/plugin-rotate-0.22.10.tgz#93d3781eca02d549a632db74bc63d27a6bb9a38c" + integrity sha512-eeFX8dnRyf3LAdsdXWKWuN18hLRg8zy1cP0cP9rHzQVWRK7ck/QsLxK1vHq7MADGwQalNaNTJ9SQxH6c8mz6jw== + dependencies: + "@jimp/utils" "^0.22.10" + +"@jimp/plugin-scale@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-scale/-/plugin-scale-0.22.10.tgz#69127d45eb0837cd23cd04cff3677344064670ac" + integrity sha512-TG/H0oUN69C9ArBCZg4PmuoixFVKIiru8282KzSB/Tp1I0xwX0XLTv3dJ5pobPlIgPcB+TmD4xAIdkCT4rtWxg== + dependencies: + "@jimp/utils" "^0.22.10" + +"@jimp/plugin-shadow@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-shadow/-/plugin-shadow-0.22.10.tgz#ccf379a8d41861eb07c35a60f3dcdede8e856de7" + integrity sha512-TN9xm6fI7XfxbMUQqFPZjv59Xdpf0tSiAQdINB4g6pJMWiVANR/74OtDONoy3KKpenu5Y38s+FkrtID/KcQAhw== + dependencies: + "@jimp/utils" "^0.22.10" + +"@jimp/plugin-threshold@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugin-threshold/-/plugin-threshold-0.22.10.tgz#590bda5ddf9071adad36f98197e710f33cb47a26" + integrity sha512-DA2lSnU0TgIRbAgmXaxroYw3Ad6J2DOFEoJp0NleSm2h3GWbZEE5yW9U2B6hD3iqn4AenG4E2b2WzHXZyzSutw== + dependencies: + "@jimp/utils" "^0.22.10" + +"@jimp/plugins@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/plugins/-/plugins-0.22.10.tgz#7062b6a36dc2d9c8dbd574a7697b6efaccecdee8" + integrity sha512-KDMZyM6pmvS8freB+UBLko1TO/k4D7URS/nphCozuH+P7i3UMe7NdckXKJ8u+WD6sqN0YFYvBehpkpnUiw/91w== + dependencies: + "@jimp/plugin-blit" "^0.22.10" + "@jimp/plugin-blur" "^0.22.10" + "@jimp/plugin-circle" "^0.22.10" + "@jimp/plugin-color" "^0.22.10" + "@jimp/plugin-contain" "^0.22.10" + "@jimp/plugin-cover" "^0.22.10" + "@jimp/plugin-crop" "^0.22.10" + "@jimp/plugin-displace" "^0.22.10" + "@jimp/plugin-dither" "^0.22.10" + "@jimp/plugin-fisheye" "^0.22.10" + "@jimp/plugin-flip" "^0.22.10" + "@jimp/plugin-gaussian" "^0.22.10" + "@jimp/plugin-invert" "^0.22.10" + "@jimp/plugin-mask" "^0.22.10" + "@jimp/plugin-normalize" "^0.22.10" + "@jimp/plugin-print" "^0.22.10" + "@jimp/plugin-resize" "^0.22.10" + "@jimp/plugin-rotate" "^0.22.10" + "@jimp/plugin-scale" "^0.22.10" + "@jimp/plugin-shadow" "^0.22.10" + "@jimp/plugin-threshold" "^0.22.10" timm "^1.6.1" -"@jimp/png@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/png/-/png-0.22.8.tgz#3fd5e546087aede4011ceb1f75e912dbc8ff696e" - integrity sha512-XOj11kcCr8zKg24QSwlRfH9k4hbV6rkMGUVxMS3puRzzB0FBSQy42NBYEfYf2XlY2QJSAByPl4AYerOtKb805w== +"@jimp/png@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/png/-/png-0.22.10.tgz#397da6479f515dc87525b0f25efe4cb11cb75156" + integrity sha512-RYinU7tZToeeR2g2qAMn42AU+8OUHjXPKZZ9RkmoL4bguA1xyZWaSdr22/FBkmnHhOERRlr02KPDN1OTOYHLDQ== dependencies: - "@jimp/utils" "^0.22.8" + "@jimp/utils" "^0.22.10" pngjs "^6.0.0" -"@jimp/tiff@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/tiff/-/tiff-0.22.8.tgz#e584e087633cbfad90fcca82439fabcba4b6786e" - integrity sha512-K0hYUVW5MLgwq3jiHVHa6LvP05J1rXOlRCC+5dMTUnAXVwi45+MKsqA/8lzzwhHYJ65CNhZwy6D3+ZNzM9SIBQ== +"@jimp/tiff@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/tiff/-/tiff-0.22.10.tgz#e5511e21c73719a308545732f1ec050f52a8e0ad" + integrity sha512-OaivlSYzpNTHyH/h7pEtl3A7F7TbsgytZs52GLX/xITW92ffgDgT6PkldIrMrET6ERh/hdijNQiew7IoEEr2og== dependencies: utif2 "^4.0.1" -"@jimp/types@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/types/-/types-0.22.8.tgz#4dedda51186a1d950108ed9856f5d17a9f003597" - integrity sha512-9+xc+mzuYwu0i+6dsnhXiUgfcS+Ktqn5q2jczoKyyBT0cOKgsk+57EIeFLgpTfVGRKRR0y/UIdHByeCzGguF3A== +"@jimp/types@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/types/-/types-0.22.10.tgz#1ae01dfea9f36ba9751e63a1eedecb4c4da9ef16" + integrity sha512-u/r+XYzbCx4zZukDmxx8S0er3Yq3iDPI6+31WKX0N18i2qPPJYcn8qwIFurfupRumGvJ8SlGLCgt/T+Y8zzUIw== dependencies: - "@jimp/bmp" "^0.22.8" - "@jimp/gif" "^0.22.8" - "@jimp/jpeg" "^0.22.8" - "@jimp/png" "^0.22.8" - "@jimp/tiff" "^0.22.8" + "@jimp/bmp" "^0.22.10" + "@jimp/gif" "^0.22.10" + "@jimp/jpeg" "^0.22.10" + "@jimp/png" "^0.22.10" + "@jimp/tiff" "^0.22.10" timm "^1.6.1" -"@jimp/utils@^0.22.8": - version "0.22.8" - resolved "https://registry.yarnpkg.com/@jimp/utils/-/utils-0.22.8.tgz#04039431a00f62e0c630b376aab848f8718fb9a1" - integrity sha512-AaqjfqDeLzSFzrbGRKHMXg/ntiWKvoG9tpVgWzgOx5/gPWj/IyGfztojLTTvY8HqZCr25z8z91u2lAQD2v46Jw== +"@jimp/utils@^0.22.10": + version "0.22.10" + resolved "https://registry.yarnpkg.com/@jimp/utils/-/utils-0.22.10.tgz#d05934fae1c4bd988205d3decc2a649df0724a26" + integrity sha512-ztlOK9Mm2iLG2AMoabzM4i3WZ/FtshcgsJCbZCRUs/DKoeS2tySRJTnQZ1b7Roq0M4Ce+FUAxnCAcBV0q7PH9w== dependencies: regenerator-runtime "^0.13.3" @@ -1488,12 +1490,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/resolve-uri@^3.0.3": +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== @@ -1503,12 +1500,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/sourcemap-codec@1.4.14": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/sourcemap-codec@^1.4.10": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== @@ -1522,12 +1514,12 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.18" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" - integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + version "0.3.19" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" + integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw== dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" "@netlify/functions@^1.4.0": version "1.6.0" @@ -1821,9 +1813,9 @@ aggregate-error "^3.1.0" "@probot/adapter-aws-lambda-serverless@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@probot/adapter-aws-lambda-serverless/-/adapter-aws-lambda-serverless-3.0.2.tgz#1945144f4d3dffa39c495b9fc72d49770524a65c" - integrity sha512-1e7EHI6gkMbCdOK+caplqgDTW/x+J+2NSE0CdhqeHHiLUHkwzi4cgoP7/cJaTHBuCkZGJiyn6elI8cQtko+OfQ== + version "3.0.3" + resolved "https://registry.yarnpkg.com/@probot/adapter-aws-lambda-serverless/-/adapter-aws-lambda-serverless-3.0.3.tgz#e841201ba9d8bb408cc578c423422a3a5b8bf32f" + integrity sha512-zYx4pavXqxHj3ohILX2NeAcVF2eO0qmZ79/eBabSMqna+tixrlV8W6oUKkSvuyRQs5fZQjjw79ZhvK40GwhuhA== dependencies: "@probot/get-private-key" "^1.1.0" "@types/aws-lambda" "^8.10.85" @@ -1948,25 +1940,32 @@ "@sinonjs/commons" "^1.7.0" "@supabase/functions-js@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@supabase/functions-js/-/functions-js-2.1.2.tgz#340a8d3845ef2014338b13a6d33cfa90eb745b14" - integrity sha512-QCR6pwJs9exCl37bmpMisUd6mf+0SUBJ6mUpiAjEkSJ/+xW8TCuO14bvkWHADd5hElJK9MxNlMQXxSA4DRz9nQ== + version "2.1.4" + resolved "https://registry.yarnpkg.com/@supabase/functions-js/-/functions-js-2.1.4.tgz#57da24829ffe8f15c002dfcc615ef4ab5735156d" + integrity sha512-5EEhei1hFCMBX4Pig4kGKjJ59DZvXwilcIBYYp4wyK/iHdAN6Vw9di9VN6/oRXRVS/6jgZd0jdmI+QgGGSxZsA== dependencies: cross-fetch "^3.1.5" "@supabase/gotrue-js@^2.46.1": - version "2.47.0" - resolved "https://registry.yarnpkg.com/@supabase/gotrue-js/-/gotrue-js-2.47.0.tgz#67cca8f7be726fcfcc6dd49f515bbb20b2278f74" - integrity sha512-3e34/vsKH/DoSZCpB85UZpFWSJ2p4GRUUlqgAgeTPagPlx4xS+Nc5v7g7ic7vp3gK0J5PsYVCn9Qu2JQUp4vXg== + version "2.51.0" + resolved "https://registry.yarnpkg.com/@supabase/gotrue-js/-/gotrue-js-2.51.0.tgz#9e66f974c69242a01ec4c5b81088c0678dac6fd3" + integrity sha512-9bXV38OTd4tNHukwPDkfYNLyoGuzKeNPRaQ675rsv4JV7YCTliGLJiDadTCZjsMo2v1gVDDUtrJHF8kIxxPP1w== dependencies: - cross-fetch "^3.1.5" + "@supabase/node-fetch" "^2.6.14" + +"@supabase/node-fetch@^2.6.14": + version "2.6.14" + resolved "https://registry.yarnpkg.com/@supabase/node-fetch/-/node-fetch-2.6.14.tgz#6a3e2924e3de8aeeb82c193c786ffb25da9af23f" + integrity sha512-w/Tsd22e/5fAeoxqQ4P2MX6EyF+iM6rc9kmlMVFkHuG0rAltt2TLhFbDJfemnHbtvnazWaRfy5KnFU/SYT37dQ== + dependencies: + whatwg-url "^5.0.0" "@supabase/postgrest-js@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@supabase/postgrest-js/-/postgrest-js-1.8.0.tgz#c10b65e120c6523fc947225bcb9131869cf509f1" - integrity sha512-R6leDIC92NgjyG2/tCRJ42rWN7+fZY6ulTEE+c00tcnghn6cX4IYUlnTNMtrdfYC2JYNOTyM+rWj63Wdhr7Zig== + version "1.8.4" + resolved "https://registry.yarnpkg.com/@supabase/postgrest-js/-/postgrest-js-1.8.4.tgz#89e8355503979ad25e7340b910d17704507ab325" + integrity sha512-ELjpvhb04wILUiJz9zIsTSwaz9LQNlX+Ig5/LgXQ7k68qQI6NqHVn+ISRNt53DngUIyOnLHjeqqIRHBZ7zpgGA== dependencies: - cross-fetch "^3.1.5" + "@supabase/node-fetch" "^2.6.14" "@supabase/realtime-js@^2.7.4": version "2.7.4" @@ -1978,9 +1977,9 @@ websocket "^1.0.34" "@supabase/storage-js@^2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@supabase/storage-js/-/storage-js-2.5.1.tgz#16c4c088996e0395034717836e626f14df63a349" - integrity sha512-nkR0fQA9ScAtIKA3vNoPEqbZv1k5B5HVRYEvRWdlP6mUpFphM9TwPL2jZ/ztNGMTG5xT6SrHr+H7Ykz8qzbhjw== + version "2.5.3" + resolved "https://registry.yarnpkg.com/@supabase/storage-js/-/storage-js-2.5.3.tgz#6d6023d0420151a4c65339e762eca7838fd0f97c" + integrity sha512-wyCkBFMTiehvyLUvvvSszvhPkhaHKHcPx//fYN8NoKEa1TQwC2HuO5EIaJ5EagtAVmI1N3EFQ+M4RER6mnTaNg== dependencies: cross-fetch "^3.1.5" @@ -1996,6 +1995,11 @@ "@supabase/storage-js" "^2.5.1" cross-fetch "^3.1.5" +"@telegraf/types@^6.8.1": + version "6.8.1" + resolved "https://registry.yarnpkg.com/@telegraf/types/-/types-6.8.1.tgz#c9c567e8ba4fb3c656494f3901a7dfb22cb7d676" + integrity sha512-JCRQuPPDCreYQaAeOwnqIlWrs8pJVvaNEUWBVNvdK3oJoTUKyBV+3TsPrIcnGqLeapptznuTk5s4udTlZPvGTA== + "@tokenizer/token@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" @@ -2078,16 +2082,16 @@ integrity sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg== "@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + version "3.4.36" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.36.tgz#e511558c15a39cb29bd5357eebb57bd1459cd1ab" + integrity sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w== dependencies: "@types/node" "*" "@types/eslint@^8.40.2": - version "8.40.2" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.40.2.tgz#2833bc112d809677864a4b0e7d1de4f04d7dac2d" - integrity sha512-PRVjQ4Eh9z9pmmtaq8nTjZjQwKFk7YIHIud3lRoKRBgUQjgjRmoGxxGEPXQkF+lH7QkHJRNr5F4aBgYCW0lqpQ== + version "8.44.2" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.44.2.tgz#0d21c505f98a89b8dd4d37fa162b09da6089199a" + integrity sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -2098,9 +2102,9 @@ integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== "@types/express-serve-static-core@^4.17.33": - version "4.17.35" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz#c95dd4424f0d32e525d23812aa8ab8e4d3906c4f" - integrity sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg== + version "4.17.36" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz#baa9022119bdc05a4adfe740ffc97b5f9360e545" + integrity sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q== dependencies: "@types/node" "*" "@types/qs" "*" @@ -2186,14 +2190,14 @@ "@types/node" "*" "@types/libsodium-wrappers@^0.7.10": - version "0.7.10" - resolved "https://registry.yarnpkg.com/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz#a6ebde70d3b4af960fd802af8d0e3c7cfe281eb2" - integrity sha512-BqI9B92u+cM3ccp8mpHf+HzJ8fBlRwdmyd6+fz3p99m3V6ifT5O3zmOMi612PGkpeFeG/G6loxUnzlDNhfjPSA== + version "0.7.11" + resolved "https://registry.yarnpkg.com/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.11.tgz#4ac53b8a16a4c80d062e32b3849e9d5b8c2f92ed" + integrity sha512-8avZYJny690B6lFZQEDz4PEdCgC8D8qmGE/mhJBzCwzZvsqne61tCRbtJOhxsjYMItEZd3k4SoR4xKKLnI9Ztg== "@types/lodash@^4.14.197": - version "4.14.197" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.197.tgz#e95c5ddcc814ec3e84c891910a01e0c8a378c54b" - integrity sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g== + version "4.14.198" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.198.tgz#4d27465257011aedc741a809f1269941fa2c5d4c" + integrity sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg== "@types/mime@*": version "3.0.1" @@ -2215,20 +2219,38 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== +"@types/node-fetch@^2.6.4": + version "2.6.4" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" + integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*": - version "20.3.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.2.tgz#fa6a90f2600e052a03c18b8cb3fd83dd4e599898" - integrity sha512-vOBLVQeCQfIcF/2Y7eKFTqrMnizK5lRNQ7ykML/5RuwVXVWxYkgwS7xbt4B6fKCUPgbSL5FSsjHQpaGQP/dQmw== + version "20.6.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.0.tgz#9d7daa855d33d4efec8aea88cd66db1c2f0ebe16" + integrity sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg== "@types/node@16.9.1": version "16.9.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.1.tgz#0611b37db4246c937feef529ddcc018cf8e35708" integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g== +"@types/node@20.4.7": + version "20.4.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.7.tgz#74d323a93f1391a63477b27b9aec56669c98b2ab" + integrity sha512-bUBrPjEry2QUTsnuEjzjbS7voGWCc30W0qzgMf90GPeDGFRakvrz47ju+oqDAKCXLUCe39u57/ORMl/O/04/9g== + "@types/node@^14.18.37": - version "14.18.52" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.52.tgz#214674cbff9f86fad4bf0c25f31ab9b9fa31110f" - integrity sha512-DGhiXKOHSFVVm+PJD+9Y0ObxXLeG6qwc0HoOn+ooQKeNNu+T2mEJCM5UBDUREKAggl9MHYjb5E71PAmx6MbzIg== + version "14.18.59" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.59.tgz#2b61a51d875e2a4deb0c6b498ff21a78e691edc6" + integrity sha512-NWJMpBL2Xs3MY93yrD6YrrTKep8eIA6iMnfG4oIc6LrTRlBZgiSCGiY3V/Owlp6umIBLyKb4F8Q7hxWatjYH5A== + +"@types/node@^18.11.18": + version "18.17.15" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.17.15.tgz#31301a273b9ca7d568fe6d1c35ae52e0fb3f8d6a" + integrity sha512-2yrWpBk32tvV/JAd3HNHWuZn/VDN1P+72hWirHnvsvTGSqbANi+kSeuQR9yAHnbvaBvHDsoTdXV0Fe+iRtHLKA== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -2243,9 +2265,9 @@ parse5 "*" "@types/phoenix@^1.5.4": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@types/phoenix/-/phoenix-1.6.0.tgz#eb7536259ee695646e75c4c7b0c9a857ea174781" - integrity sha512-qwfpsHmFuhAS/dVd4uBIraMxRd56vwBUYQGZ6GpXnFuM2XMRFJbIyruFKKlW2daQliuYZwe0qfn/UjFCDKic5g== + version "1.6.1" + resolved "https://registry.yarnpkg.com/@types/phoenix/-/phoenix-1.6.1.tgz#9551cd77a8f4c70c5d81db899f2af762066aabde" + integrity sha512-g2/8Ogi2zfiS25jdGT5iDSo5yjruhhXaOuOJCkOxMW28w16VxFvjtAXjBNRo7WlRS4+UXAMj3mK46UwieNM/5g== "@types/pino-http@^5.0.6": version "5.8.1" @@ -2284,9 +2306,9 @@ integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== "@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + version "6.9.8" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.8.tgz#f2a7de3c107b89b441e071d5472e6b726b4adf45" + integrity sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg== "@types/range-parser@*": version "1.2.4" @@ -2294,9 +2316,9 @@ integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== "@types/semver@^7.3.12": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" - integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== + version "7.5.1" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.1.tgz#0480eeb7221eb9bc398ad7432c9d7e14b1a5a367" + integrity sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg== "@types/send@*": version "0.17.1" @@ -2316,9 +2338,9 @@ "@types/node" "*" "@types/source-map-support@^0.5.6": - version "0.5.6" - resolved "https://registry.yarnpkg.com/@types/source-map-support/-/source-map-support-0.5.6.tgz#aa4a8c98ec73a1f1f30a813573a9b2154a6eb39a" - integrity sha512-b2nJ9YyXmkhGaa2b8VLM0kJ04xxwNyijcq12/kDoomCt43qbHBeK2SLNJ9iJmETaAj+bKUT05PQUu3Q66GvLhQ== + version "0.5.7" + resolved "https://registry.yarnpkg.com/@types/source-map-support/-/source-map-support-0.5.7.tgz#68b3cc568cc4cc4d141d58edfca164c1354044b9" + integrity sha512-rJqBfLel8jPuL5MwXxMH2Cdb6D80Snu3YJxDE+VJAmtT04l7j3OA7h+FYXlYDys0WeBVH/MPbExj3B8NCaDw9g== dependencies: source-map "^0.6.0" @@ -2328,9 +2350,9 @@ integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== "@types/websocket@^1.0.3": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.5.tgz#3fb80ed8e07f88e51961211cd3682a3a4a81569c" - integrity sha512-NbsqiNX9CnEfC1Z0Vf4mE1SgAJ07JnRYcNex7AJ9zAVzmiGHmjKFEk7O4TJIsgv2B1sLEb6owKFZrACwdYngsQ== + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.6.tgz#ec8dce5915741632ac3a4b1f951b6d4156e32d03" + integrity sha512-JXkliwz93B2cMWOI1ukElQBPN88vMg3CruvW4KVSKpflt3NyNCJImnhIuB/f97rG7kakqRJGFiwkA895Kn02Dg== dependencies: "@types/node" "*" @@ -2361,87 +2383,87 @@ "@types/node" "*" "@typescript-eslint/eslint-plugin@^5.59.11": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.1.tgz#81382d6ecb92b8dda70e91f9035611cb2fecd1c3" - integrity sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw== + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" + integrity sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag== dependencies: "@eslint-community/regexpp" "^4.4.0" - "@typescript-eslint/scope-manager" "5.60.1" - "@typescript-eslint/type-utils" "5.60.1" - "@typescript-eslint/utils" "5.60.1" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/type-utils" "5.62.0" + "@typescript-eslint/utils" "5.62.0" debug "^4.3.4" - grapheme-splitter "^1.0.4" + graphemer "^1.4.0" ignore "^5.2.0" natural-compare-lite "^1.4.0" semver "^7.3.7" tsutils "^3.21.0" "@typescript-eslint/parser@^5.59.11": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.60.1.tgz#0f2f58209c0862a73e3d5a56099abfdfa21d0fd3" - integrity sha512-pHWlc3alg2oSMGwsU/Is8hbm3XFbcrb6P5wIxcQW9NsYBfnrubl/GhVVD/Jm/t8HXhA2WncoIRfBtnCgRGV96Q== + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" + integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA== dependencies: - "@typescript-eslint/scope-manager" "5.60.1" - "@typescript-eslint/types" "5.60.1" - "@typescript-eslint/typescript-estree" "5.60.1" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.60.1.tgz#35abdb47f500c68c08f2f2b4f22c7c79472854bb" - integrity sha512-Dn/LnN7fEoRD+KspEOV0xDMynEmR3iSHdgNsarlXNLGGtcUok8L4N71dxUgt3YvlO8si7E+BJ5Fe3wb5yUw7DQ== +"@typescript-eslint/scope-manager@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c" + integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w== dependencies: - "@typescript-eslint/types" "5.60.1" - "@typescript-eslint/visitor-keys" "5.60.1" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/type-utils@5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.60.1.tgz#17770540e98d65ab4730c7aac618003f702893f4" - integrity sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A== +"@typescript-eslint/type-utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz#286f0389c41681376cdad96b309cedd17d70346a" + integrity sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew== dependencies: - "@typescript-eslint/typescript-estree" "5.60.1" - "@typescript-eslint/utils" "5.60.1" + "@typescript-eslint/typescript-estree" "5.62.0" + "@typescript-eslint/utils" "5.62.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.60.1.tgz#a17473910f6b8d388ea83c9d7051af89c4eb7561" - integrity sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg== +"@typescript-eslint/types@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" + integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/typescript-estree@5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.1.tgz#8c71824b7165b64d5ebd7aa42968899525959834" - integrity sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw== +"@typescript-eslint/typescript-estree@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" + integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA== dependencies: - "@typescript-eslint/types" "5.60.1" - "@typescript-eslint/visitor-keys" "5.60.1" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/visitor-keys" "5.62.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.60.1.tgz#6861ebedbefba1ac85482d2bdef6f2ff1eb65b80" - integrity sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ== +"@typescript-eslint/utils@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.62.0.tgz#141e809c71636e4a75daa39faed2fb5f4b10df86" + integrity sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.60.1" - "@typescript-eslint/types" "5.60.1" - "@typescript-eslint/typescript-estree" "5.60.1" + "@typescript-eslint/scope-manager" "5.62.0" + "@typescript-eslint/types" "5.62.0" + "@typescript-eslint/typescript-estree" "5.62.0" eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.60.1": - version "5.60.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.1.tgz#19a877358bf96318ec35d90bfe6bd1445cce9434" - integrity sha512-xEYIxKcultP6E/RMKqube11pGjXH1DCo60mQoWhVYyKfLkwbIVVjYxmOenNMxILx0TjCujPTjjnTIVzm09TXIw== +"@typescript-eslint/visitor-keys@5.62.0": + version "5.62.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" + integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw== dependencies: - "@typescript-eslint/types" "5.60.1" + "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" "@uniswap/permit2-sdk@^1.2.0": @@ -2457,7 +2479,7 @@ resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.34.0.tgz#d0139528320e46670d949c82967044a8f66db054" integrity sha512-G9h5ZLBJ/V57Ou9vz5hI8pda/YQX5HQszCs3AmIus3XzsmRn/0Ptic5otD3xVST8QLKk7AMk7AqpsyQGN7MZ9A== -JSONStream@^1.0.4: +JSONStream@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== @@ -2518,10 +2540,10 @@ acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.2.4, acorn@^8.4.1, acorn@^8.8.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" - integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== +acorn@^8.2.4, acorn@^8.4.1, acorn@^8.9.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== aes-js@3.0.0: version "3.0.0" @@ -2535,7 +2557,14 @@ agent-base@6: dependencies: debug "4" -aggregate-error@^3.0.0, aggregate-error@^3.1.0: +agentkeepalive@^4.2.1: + version "4.5.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" + integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== + dependencies: + humanize-ms "^1.2.1" + +aggregate-error@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== @@ -2550,7 +2579,7 @@ ajv-formats@^2.1.1: dependencies: ajv "^8.0.0" -ajv@^6.10.0, ajv@^6.12.4: +ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2570,13 +2599,20 @@ ajv@^8.0.0, ajv@^8.11.0, ajv@^8.11.2: require-from-string "^2.0.2" uri-js "^4.2.2" -ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: +ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: type-fest "^0.21.3" +ansi-escapes@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-5.0.0.tgz#b6a0caf0eef0c41af190e9a749e0c00ec04bb2a6" + integrity sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA== + dependencies: + type-fest "^1.0.2" + ansi-regex@^5.0.0, ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -2606,7 +2642,7 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansi-styles@^6.0.0: +ansi-styles@^6.0.0, ansi-styles@^6.1.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== @@ -2709,11 +2745,6 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -2730,9 +2761,9 @@ atomic-sleep@^1.0.0: integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== axios@^1.3.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" - integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== + version "1.5.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.0.tgz#f02e4af823e2e46a9768cfc74691fdd0517ea267" + integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ== dependencies: follow-redirects "^1.15.0" form-data "^4.0.0" @@ -2804,6 +2835,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base-64@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" + integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA== + base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -2840,9 +2876,9 @@ before-after-hook@^2.2.0: integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== bin-links@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.1.tgz#afeb0549e642f61ff889b58ea2f8dca78fb9d8d3" - integrity sha512-bmFEM39CyX336ZGGRsGPlc6jZHriIoHacOQcTt72MktIjpPhZoP4te2jOyUXF3BLILmJ8aNLncoPVeIIFlrDeA== + version "4.0.2" + resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.2.tgz#13321472ea157e9530caded2b7281496d698665b" + integrity sha512-jxJ0PbXR8eQyPlExCvCs3JFnikvs1Yp4gUJt6nmgathdOwvur+q22KWC3h20gvWl4T/14DXKj2IlkJwwZkZPOw== dependencies: cmd-shim "^6.0.0" npm-normalize-package-bin "^3.0.0" @@ -2954,14 +2990,14 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserslist@^4.21.3: - version "4.21.9" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635" - integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg== +browserslist@^4.21.9: + version "4.21.10" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.10.tgz#dbbac576628c13d3b2231332cb2ec5a46e015bb0" + integrity sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ== dependencies: - caniuse-lite "^1.0.30001503" - electron-to-chromium "^1.4.431" - node-releases "^2.0.12" + caniuse-lite "^1.0.30001517" + electron-to-chromium "^1.4.477" + node-releases "^2.0.13" update-browserslist-db "^1.0.11" bs-logger@0.x: @@ -3101,10 +3137,10 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001503: - version "1.0.30001508" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001508.tgz#4461bbc895c692a96da399639cc1e146e7302a33" - integrity sha512-sdQZOJdmt3GJs1UMNpCCCyeuS2IEGLXnHyAo9yIO5JJDjbjoVRij4M1qep6P6gFpptD1PqIYgzM+gwJbOi92mw== +caniuse-lite@^1.0.30001517: + version "1.0.30001532" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001532.tgz#c6a4d5d2da6d2b967f0ee5e12e7f680db6ad2fca" + integrity sha512-FbDFnNat3nMnrROzqrsg314zhqN5LGQ1kyyMk2opcrwGbVGpHRhgCWtAgD5YJUqNAiQ+dklreil/c3Qf1dfCTw== capture-exit@^2.0.0: version "2.0.0" @@ -3113,7 +3149,7 @@ capture-exit@^2.0.0: dependencies: rsvp "^4.8.4" -chalk@2.4.2, chalk@^2.0.0: +chalk@2.4.2, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3122,10 +3158,10 @@ chalk@2.4.2, chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3" - integrity sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA== +chalk@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" @@ -3140,6 +3176,11 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +charenc@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== + chokidar@^3.5.2: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -3195,20 +3236,12 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" - integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== +cli-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" + integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" + restore-cursor "^4.0.0" cli-truncate@^3.1.0: version "3.1.0" @@ -3261,9 +3294,9 @@ co@^4.6.0: integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== collect-v8-coverage@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" - integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== collection-visit@^1.0.0: version "1.0.0" @@ -3302,7 +3335,7 @@ colorette@^1.3.0: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== -colorette@^2.0.19, colorette@^2.0.7: +colorette@^2.0.20, colorette@^2.0.7: version "2.0.20" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== @@ -3314,10 +3347,10 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -commander@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== +commander@11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-11.0.0.tgz#43e19c25dbedc8256203538e8d7e9346877a6f67" + integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ== commander@^2.19.0: version "2.20.3" @@ -3359,34 +3392,29 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== -conventional-changelog-angular@^5.0.11: - version "5.0.13" - resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz#896885d63b914a70d4934b59d2fe7bde1832b28c" - integrity sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA== +conventional-changelog-angular@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz#a9a9494c28b7165889144fd5b91573c4aa9ca541" + integrity sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg== dependencies: compare-func "^2.0.0" - q "^1.5.1" -conventional-changelog-conventionalcommits@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz#41bdce54eb65a848a4a3ffdca93e92fa22b64a86" - integrity sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw== +conventional-changelog-conventionalcommits@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-6.1.0.tgz#3bad05f4eea64e423d3d90fc50c17d2c8cf17652" + integrity sha512-3cS3GEtR78zTfMzk0AizXKKIdN4OvSh7ibNz6/DPbhWWQu7LqE/8+/GqSodV+sywUR2gpJAdP/1JFf4XtN7Zpw== dependencies: compare-func "^2.0.0" - lodash "^4.17.15" - q "^1.5.1" -conventional-commits-parser@^3.2.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz#a7d3b77758a202a9b2293d2112a8d8052c740972" - integrity sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q== +conventional-commits-parser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz#02ae1178a381304839bce7cea9da5f1b549ae505" + integrity sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg== dependencies: - JSONStream "^1.0.4" + JSONStream "^1.3.5" is-text-path "^1.0.1" - lodash "^4.17.15" - meow "^8.0.0" - split2 "^3.0.0" - through2 "^4.0.0" + meow "^8.1.2" + split2 "^3.2.2" convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" @@ -3437,18 +3465,18 @@ core-util-is@~1.0.0: integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== cosmiconfig-typescript-loader@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.3.0.tgz#c4259ce474c9df0f32274ed162c0447c951ef073" - integrity sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q== + version "4.4.0" + resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.4.0.tgz#f3feae459ea090f131df5474ce4b1222912319f9" + integrity sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw== cosmiconfig@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.2.0.tgz#f7d17c56a590856cd1e7cee98734dca272b0d8fd" - integrity sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ== + version "8.3.5" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.5.tgz#3b3897ddd042d022d5a207d4c8832e54f5301977" + integrity sha512-A5Xry3xfS96wy2qbiLkQLAg4JUrR2wvfybxj6yqLmrUfMAvhS3MZxIP2oQn0grgYIvJqzpeTEWu4vK0t+12NNw== dependencies: - import-fresh "^3.2.1" + import-fresh "^3.3.0" js-yaml "^4.1.0" - parse-json "^5.0.0" + parse-json "^5.2.0" path-type "^4.0.0" create-require@^1.1.0: @@ -3464,11 +3492,11 @@ cross-fetch@3.1.5: node-fetch "2.6.7" cross-fetch@^3.1.5: - version "3.1.6" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.6.tgz#bae05aa31a4da760969756318feeee6e70f15d6c" - integrity sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g== + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== dependencies: - node-fetch "^2.6.11" + node-fetch "^2.6.12" cross-spawn@^6.0.0: version "6.0.5" @@ -3490,6 +3518,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +crypt@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== + css-select@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" @@ -3599,7 +3632,7 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== -deep-is@^0.1.3, deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== @@ -3689,6 +3722,14 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +digest-fetch@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/digest-fetch/-/digest-fetch-1.3.0.tgz#898e69264d00012a23cf26e8a3e40320143fc661" + integrity sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA== + dependencies: + base-64 "^0.1.0" + md5 "^2.3.0" + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -3774,10 +3815,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.431: - version "1.4.441" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.441.tgz#94dd9c1cbf081d83f032a4f1cd9f787e21fc24ce" - integrity sha512-LlCgQ8zgYZPymf5H4aE9itwiIWH4YlCiv1HFLmmcBeFYi5E+3eaIFnjHzYtcFQbaKfAW+CqZ9pgxo33DZuoqPg== +electron-to-chromium@^1.4.477: + version "1.4.513" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz#41a50bf749aa7d8058ffbf7a131fc3327a7b1675" + integrity sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw== elliptic@6.5.4: version "6.5.4" @@ -3857,33 +3898,33 @@ es6-symbol@^3.1.1, es6-symbol@^3.1.3: d "^1.0.1" ext "^1.1.2" -esbuild@~0.17.6: - version "0.17.19" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955" - integrity sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw== +esbuild@~0.18.20: + version "0.18.20" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.20.tgz#4709f5a34801b43b799ab7d6d82f7284a9b7a7a6" + integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA== optionalDependencies: - "@esbuild/android-arm" "0.17.19" - "@esbuild/android-arm64" "0.17.19" - "@esbuild/android-x64" "0.17.19" - "@esbuild/darwin-arm64" "0.17.19" - "@esbuild/darwin-x64" "0.17.19" - "@esbuild/freebsd-arm64" "0.17.19" - "@esbuild/freebsd-x64" "0.17.19" - "@esbuild/linux-arm" "0.17.19" - "@esbuild/linux-arm64" "0.17.19" - "@esbuild/linux-ia32" "0.17.19" - "@esbuild/linux-loong64" "0.17.19" - "@esbuild/linux-mips64el" "0.17.19" - "@esbuild/linux-ppc64" "0.17.19" - "@esbuild/linux-riscv64" "0.17.19" - "@esbuild/linux-s390x" "0.17.19" - "@esbuild/linux-x64" "0.17.19" - "@esbuild/netbsd-x64" "0.17.19" - "@esbuild/openbsd-x64" "0.17.19" - "@esbuild/sunos-x64" "0.17.19" - "@esbuild/win32-arm64" "0.17.19" - "@esbuild/win32-ia32" "0.17.19" - "@esbuild/win32-x64" "0.17.19" + "@esbuild/android-arm" "0.18.20" + "@esbuild/android-arm64" "0.18.20" + "@esbuild/android-x64" "0.18.20" + "@esbuild/darwin-arm64" "0.18.20" + "@esbuild/darwin-x64" "0.18.20" + "@esbuild/freebsd-arm64" "0.18.20" + "@esbuild/freebsd-x64" "0.18.20" + "@esbuild/linux-arm" "0.18.20" + "@esbuild/linux-arm64" "0.18.20" + "@esbuild/linux-ia32" "0.18.20" + "@esbuild/linux-loong64" "0.18.20" + "@esbuild/linux-mips64el" "0.18.20" + "@esbuild/linux-ppc64" "0.18.20" + "@esbuild/linux-riscv64" "0.18.20" + "@esbuild/linux-s390x" "0.18.20" + "@esbuild/linux-x64" "0.18.20" + "@esbuild/netbsd-x64" "0.18.20" + "@esbuild/openbsd-x64" "0.18.20" + "@esbuild/sunos-x64" "0.18.20" + "@esbuild/win32-arm64" "0.18.20" + "@esbuild/win32-ia32" "0.18.20" + "@esbuild/win32-x64" "0.18.20" escalade@^3.1.1: version "3.1.1" @@ -3911,14 +3952,13 @@ escape-string-regexp@^4.0.0: integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== escodegen@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" - integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + version "2.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== dependencies: esprima "^4.0.1" estraverse "^5.2.0" esutils "^2.0.2" - optionator "^0.8.1" optionalDependencies: source-map "~0.6.1" @@ -3930,40 +3970,40 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" - integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" - integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^8.43.0: - version "8.43.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.43.0.tgz#3e8c6066a57097adfd9d390b8fc93075f257a094" - integrity sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q== + version "8.49.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.49.0.tgz#09d80a89bdb4edee2efcf6964623af1054bf6d42" + integrity sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.4.0" - "@eslint/eslintrc" "^2.0.3" - "@eslint/js" "8.43.0" - "@humanwhocodes/config-array" "^0.11.10" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.2" + "@eslint/js" "8.49.0" + "@humanwhocodes/config-array" "^0.11.11" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" - ajv "^6.10.0" + ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.3.2" doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.2.0" - eslint-visitor-keys "^3.4.1" - espree "^9.5.2" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -3973,7 +4013,6 @@ eslint@^8.43.0: globals "^13.19.0" graphemer "^1.4.0" ignore "^5.2.0" - import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" is-path-inside "^3.0.3" @@ -3983,17 +4022,16 @@ eslint@^8.43.0: lodash.merge "^4.6.2" minimatch "^3.1.2" natural-compare "^1.4.0" - optionator "^0.9.1" + optionator "^0.9.3" strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" text-table "^0.2.0" -espree@^9.5.2: - version "9.5.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b" - integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw== +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: - acorn "^8.8.0" + acorn "^8.9.0" acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" @@ -4077,6 +4115,11 @@ event-target-shim@^5.0.0: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== +eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" @@ -4097,6 +4140,21 @@ exec-sh@^0.3.2: resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w== +execa@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9" + integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" + execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -4140,21 +4198,6 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^7.0.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43" - integrity sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.1" - human-signals "^4.3.0" - is-stream "^3.0.0" - merge-stream "^2.0.0" - npm-run-path "^5.1.0" - onetime "^6.0.0" - signal-exit "^3.0.7" - strip-final-newline "^3.0.0" - exif-parser@^0.1.12: version "0.1.12" resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922" @@ -4310,9 +4353,9 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-glob@^3.2.9: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -4325,15 +4368,15 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fast-redact@^3.0.0, fast-redact@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.2.0.tgz#b1e2d39bc731376d28bde844454fa23e26919987" - integrity sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw== + version "3.3.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.3.0.tgz#7c83ce3a7be4898241a46560d51de10f653f7634" + integrity sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ== fast-safe-stringify@^2.0.7, fast-safe-stringify@^2.0.8, fast-safe-stringify@^2.1.1: version "2.1.1" @@ -4446,11 +4489,12 @@ find-up@^5.0.0: path-exists "^4.0.0" flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.1.0.tgz#0e54ab4a1a60fe87e2946b6b00657f1c99e1af3f" + integrity sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew== dependencies: - flatted "^3.1.0" + flatted "^3.2.7" + keyv "^4.5.3" rimraf "^3.0.2" flatstr@^1.0.12: @@ -4458,7 +4502,7 @@ flatstr@^1.0.12: resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" integrity sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw== -flatted@^3.1.0: +flatted@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== @@ -4473,6 +4517,11 @@ for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== +form-data-encoder@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040" + integrity sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A== + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -4491,6 +4540,14 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +formdata-node@^4.3.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2" + integrity sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ== + dependencies: + node-domexception "1.0.0" + web-streams-polyfill "4.0.0-beta.3" + formdata-polyfill@^4.0.10: version "4.0.10" resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" @@ -4552,9 +4609,9 @@ fs.realpath@^1.0.0: integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^2.1.2, fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.1: version "1.1.1" @@ -4606,9 +4663,9 @@ get-stream@^6.0.0, get-stream@^6.0.1: integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== get-tsconfig@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.6.0.tgz#e977690993a42f3e320e932427502a40f7af6d05" - integrity sha512-lgbo68hHTQnFddybKbbs/RDRJnJT5YyGy2kQzVwbq+g67X73i+5MVTval34QxGkOe9X5Ujf1UYpCaphLyltjEg== + version "4.7.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.0.tgz#06ce112a1463e93196aa90320c35df5039147e34" + integrity sha512-pmjiZ7xtB8URYm74PlGJozDNyhvsVLUcpBa8DZBG3bWHwaHa9bPiRpiSfovw+fjhwONSCWKRyk+JQHEGZmMrzw== dependencies: resolve-pkg-maps "^1.0.0" @@ -4617,10 +4674,10 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== -gifwrap@^0.9.2: - version "0.9.4" - resolved "https://registry.yarnpkg.com/gifwrap/-/gifwrap-0.9.4.tgz#f4eb6169ba027d61df64aafbdcb1f8ae58ccc0c5" - integrity sha512-MDMwbhASQuVeD4JKd1fKgNgCRL3fGqMM4WaqpNhWO0JiMOAjbQdumbs4BbBZEy9/M00EHEjKN3HieVhCUlwjeQ== +gifwrap@^0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/gifwrap/-/gifwrap-0.10.1.tgz#9ed46a5d51913b482d4221ce9c727080260b681e" + integrity sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw== dependencies: image-q "^4.0.0" omggif "^1.0.10" @@ -4694,9 +4751,9 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.19.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + version "13.21.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.21.0.tgz#163aae12f34ef502f5153cfbdd3600f36c63c571" + integrity sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg== dependencies: type-fest "^0.20.2" @@ -4717,11 +4774,6 @@ graceful-fs@^4.1.15, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" @@ -4733,12 +4785,12 @@ growly@^1.3.0: integrity sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw== handlebars@^4.5.3, handlebars@^4.7.7: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== dependencies: minimist "^1.2.5" - neo-async "^2.6.0" + neo-async "^2.6.2" source-map "^0.6.1" wordwrap "^1.0.0" optionalDependencies: @@ -4909,6 +4961,13 @@ human-signals@^4.3.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" + husky@^8.0.2: version "8.0.3" resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" @@ -4943,7 +5002,7 @@ image-q@^4.0.0: dependencies: "@types/node" "16.9.1" -import-fresh@^3.0.0, import-fresh@^3.2.1: +import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -5040,7 +5099,7 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-buffer@^1.1.5: +is-buffer@^1.1.5, is-buffer@~1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -5052,10 +5111,10 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.11.0, is-core-module@^2.5.0: - version "2.12.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" - integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== +is-core-module@^2.13.0, is-core-module@^2.5.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== dependencies: has "^1.0.3" @@ -5290,12 +5349,12 @@ istanbul-lib-instrument@^5.0.4: semver "^6.3.0" istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== dependencies: istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" + make-dir "^4.0.0" supports-color "^7.1.0" istanbul-lib-source-maps@^4.0.0: @@ -5308,9 +5367,9 @@ istanbul-lib-source-maps@^4.0.0: source-map "^0.6.1" istanbul-reports@^3.0.2: - version "3.1.5" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" - integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + version "3.1.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" + integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" @@ -5741,13 +5800,13 @@ jest@^26.6.3: jest-cli "^26.6.3" jimp@^0.22.4: - version "0.22.8" - resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.22.8.tgz#85db9a2de69370c36d8b5ae070381af83dbbb40f" - integrity sha512-pBbrooJMX7795sDcxx1XpwNZC8B/ITyDV+JK2/1qNbQl/1UWqWeh5Dq7qQpMZl5jLdcFDv5IVTM+OhpafSqSFA== + version "0.22.10" + resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.22.10.tgz#2cc3e265a99cdbe69ec60ddd57cbcde6a6cf0519" + integrity sha512-lCaHIJAgTOsplyJzC1w/laxSxrbSsEBw4byKwXgUdMmh+ayPsnidTblenQm+IvhIs44Gcuvlb6pd2LQ0wcKaKg== dependencies: - "@jimp/custom" "^0.22.8" - "@jimp/plugins" "^0.22.8" - "@jimp/types" "^0.22.8" + "@jimp/custom" "^0.22.10" + "@jimp/plugins" "^0.22.10" + "@jimp/types" "^0.22.10" regenerator-runtime "^0.13.3" jmespath@^0.15.0: @@ -5828,6 +5887,11 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -5858,7 +5922,7 @@ json-stringify-safe@^5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json5@2.x, json5@^2.2.2: +json5@2.x, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -5878,14 +5942,20 @@ jsonparse@^1.2.0: integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== jsonwebtoken@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz#d0faf9ba1cc3a56255fe49c0961a67e520c1926d" - integrity sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw== + version "9.0.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== dependencies: jws "^3.2.2" - lodash "^4.17.21" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" ms "^2.1.1" - semver "^7.3.8" + semver "^7.5.4" jwa@^1.4.1: version "1.4.1" @@ -5904,6 +5974,13 @@ jws@^3.2.2: jwa "^1.4.1" safe-buffer "^5.0.1" +keyv@^4.5.3: + version "4.5.3" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25" + integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug== + dependencies: + json-buffer "3.0.1" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -5951,14 +6028,6 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - libsodium-wrappers@^0.7.11: version "0.7.11" resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.7.11.tgz#53bd20606dffcc54ea2122133c7da38218f575f7" @@ -5982,37 +6051,32 @@ lines-and-columns@^1.1.6: integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== lint-staged@^13.1.0: - version "13.2.2" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.2.2.tgz#5e711d3139c234f73402177be2f8dd312e6508ca" - integrity sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA== + version "13.3.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.3.0.tgz#7965d72a8d6a6c932f85e9c13ccf3596782d28a5" + integrity sha512-mPRtrYnipYYv1FEE134ufbWpeggNTo+O/UPzngoaKzbzHAthvR55am+8GfHTnqNRQVRRrYQLGW9ZyUoD7DsBHQ== dependencies: - chalk "5.2.0" - cli-truncate "^3.1.0" - commander "^10.0.0" - debug "^4.3.4" - execa "^7.0.0" + chalk "5.3.0" + commander "11.0.0" + debug "4.3.4" + execa "7.2.0" lilconfig "2.1.0" - listr2 "^5.0.7" - micromatch "^4.0.5" - normalize-path "^3.0.0" - object-inspect "^1.12.3" - pidtree "^0.6.0" - string-argv "^0.3.1" - yaml "^2.2.2" + listr2 "6.6.1" + micromatch "4.0.5" + pidtree "0.6.0" + string-argv "0.3.2" + yaml "2.3.1" -listr2@^5.0.7: - version "5.0.8" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23" - integrity sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA== +listr2@6.6.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-6.6.1.tgz#08b2329e7e8ba6298481464937099f4a2cd7f95d" + integrity sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg== dependencies: - cli-truncate "^2.1.0" - colorette "^2.0.19" - log-update "^4.0.0" - p-map "^4.0.0" + cli-truncate "^3.1.0" + colorette "^2.0.20" + eventemitter3 "^5.0.1" + log-update "^5.0.1" rfdc "^1.3.0" - rxjs "^7.8.0" - through "^2.3.8" - wrap-ansi "^7.0.0" + wrap-ansi "^8.1.0" load-bmfont@^1.4.1: version "1.4.1" @@ -6076,21 +6140,46 @@ lodash.flatten@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + lodash.isarguments@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + lodash.isfunction@^3.0.9: version "3.0.9" resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw== +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + lodash.kebabcase@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" @@ -6106,6 +6195,11 @@ lodash.mergewith@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + lodash.snakecase@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" @@ -6131,15 +6225,16 @@ lodash@4.x, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.7.0: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-update@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" - integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== +log-update@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-5.0.1.tgz#9e928bf70cb183c1f0c9e91d9e6b7115d597ce09" + integrity sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw== dependencies: - ansi-escapes "^4.3.0" - cli-cursor "^3.1.0" - slice-ansi "^4.0.0" - wrap-ansi "^6.2.0" + ansi-escapes "^5.0.0" + cli-cursor "^4.0.0" + slice-ansi "^5.0.0" + strip-ansi "^7.0.1" + wrap-ansi "^8.0.1" lowercase-keys@^2.0.0: version "2.0.0" @@ -6170,12 +6265,12 @@ lru_map@^0.3.3: resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== dependencies: - semver "^6.0.0" + semver "^7.5.3" make-error@1.x, make-error@^1.1.1: version "1.3.6" @@ -6211,12 +6306,21 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +md5@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" + integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== + dependencies: + charenc "0.0.2" + crypt "0.0.2" + is-buffer "~1.1.6" + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -meow@^8.0.0: +meow@^8.0.0, meow@^8.1.2: version "8.1.2" resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897" integrity sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q== @@ -6253,6 +6357,14 @@ methods@^1.1.2, methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micromatch@4.0.5, micromatch@^4.0.2, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -6272,14 +6384,6 @@ micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -6400,11 +6504,6 @@ mkdirp@1.x, mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^2.1.3: - version "2.1.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19" - integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A== - morgan@^1.9.1: version "1.10.0" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" @@ -6436,7 +6535,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1, ms@^2.1.3: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -6473,7 +6572,7 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -neo-async@^2.6.0: +neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -6489,16 +6588,16 @@ nice-try@^1.0.4: integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== nock@^13.0.5: - version "13.3.1" - resolved "https://registry.yarnpkg.com/nock/-/nock-13.3.1.tgz#f22d4d661f7a05ebd9368edae1b5dc0a62d758fc" - integrity sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw== + version "13.3.3" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.3.3.tgz#179759c07d3f88ad3e794ace885629c1adfd3fe7" + integrity sha512-z+KUlILy9SK/RjpeXDiDUEAq4T94ADPHE3qaRkf66mpEhzc/ytOMm3Bwdrbq6k1tMWkbdujiKim3G2tfQARuJw== dependencies: debug "^4.1.0" json-stringify-safe "^5.0.1" lodash "^4.17.21" propagate "^2.0.0" -node-domexception@^1.0.0: +node-domexception@1.0.0, node-domexception@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== @@ -6510,39 +6609,39 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^2.6.1, node-fetch@^2.6.11, node-fetch@^2.6.7, node-fetch@^2.6.8: - version "2.6.11" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" - integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== +node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7, node-fetch@^2.6.8: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" node-fetch@^3.2.10: - version "3.3.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.1.tgz#b3eea7b54b3a48020e46f4f88b9c5a7430d20b2e" - integrity sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow== + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== dependencies: data-uri-to-buffer "^4.0.0" fetch-blob "^3.1.4" formdata-polyfill "^4.0.10" node-gyp-build@^4.3.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" - integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + version "4.6.1" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.1.tgz#24b6d075e5e391b8d5539d98c7fc5c210cac8a3e" + integrity sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ== node-html-parser@^6.1.5: - version "6.1.5" - resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-6.1.5.tgz#c819dceb13a10a7642ff92f94f870b4f77968097" - integrity sha512-fAaM511feX++/Chnhe475a0NHD8M7AxDInsqQpz6x63GRF7xYNdS8Vo5dKsIVPgsOvG7eioRRTZQnWBrhDHBSg== + version "6.1.8" + resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-6.1.8.tgz#e4865b891d4e356c1e3171d25101cbb062b68940" + integrity sha512-bi3ChNi5Ne8XM2vDPvE2TOS6+AjgD9ASRJ81P1+45VTe9odNbsNb3SvVZzHho4qnu5gJ1yUYLGlQZ7tveSYNSg== dependencies: css-select "^5.1.0" he "1.2.0" node-html-to-image@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/node-html-to-image/-/node-html-to-image-3.3.0.tgz#065cd4ea15fa6ba9feb39aab91fdedad8b61be17" - integrity sha512-DIuQYuNzelE4r6K61F4JwBsK3dt/HwZUDD+f7j2qRBCAR9lBtRG+QwwpVG+ra/hrAH/WEtVmhPjEbIkyLAVSKQ== + version "3.4.0" + resolved "https://registry.yarnpkg.com/node-html-to-image/-/node-html-to-image-3.4.0.tgz#d31174e5df71299280899b3884a619221c6f21f0" + integrity sha512-oQlQmOaiUZP2gG7rokVvynJaEEaWCaa0JxN24DQmFdkQY6QQ4tFSiFw2wcP52ddvdQ+WetFL90QdTZXS7V7uiQ== dependencies: handlebars "^4.5.3" puppeteer "^15.3.0" @@ -6565,10 +6664,10 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" -node-releases@^2.0.12: - version "2.0.12" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039" - integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ== +node-releases@^2.0.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== nodemon@^2.0.19: version "2.0.22" @@ -6667,9 +6766,9 @@ nth-check@^2.0.1: boolbase "^1.0.0" nwsapi@^2.2.0: - version "2.2.5" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.5.tgz#a52744c61b3889dd44b0a158687add39b8d935e2" - integrity sha512-6xpotnECFy/og7tKSBVmUNft7J3jyXAka4XvG6AUhFWRz+Q/Ljus7znJAA3bxColfQLdS+XsjoodtJfCgeTEFQ== + version "2.2.7" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30" + integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ== object-copy@^0.1.0: version "0.1.0" @@ -6680,7 +6779,7 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.12.3, object-inspect@^1.9.0: +object-inspect@^1.9.0: version "1.12.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== @@ -6759,29 +6858,31 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== +openai@^4.2.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/openai/-/openai-4.6.0.tgz#0335111cf71c608b68dbdca19f8ccbd9cfb0cd97" + integrity sha512-LuONkTgoe4D172raQCv+eEK5OdLGnY/M4JrUz/pxRGevZwqDqy3xhBbCeWX8QLCbFcnITYsu/VBJXZJ0rDAMpA== dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" + "@types/node" "^18.11.18" + "@types/node-fetch" "^2.6.4" + abort-controller "^3.0.0" + agentkeepalive "^4.2.1" + digest-fetch "^1.3.0" + form-data-encoder "1.7.2" + formdata-node "^4.3.2" + node-fetch "^2.6.7" -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" deep-is "^0.1.3" fast-levenshtein "^2.0.6" levn "^0.4.1" prelude-ls "^1.2.1" type-check "^0.4.0" - word-wrap "^1.2.3" p-each-series@^2.1.0: version "2.2.0" @@ -6833,13 +6934,6 @@ p-map@^2.1.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - p-timeout@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-4.1.0.tgz#788253c0452ab0ffecf18a62dff94ff1bd09ca0a" @@ -6893,7 +6987,7 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" -parse-json@^5.0.0: +parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -6995,7 +7089,7 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pidtree@^0.6.0: +pidtree@0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== @@ -7005,10 +7099,10 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3" - integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA== +pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz#083d98f966262164504afb989bccd05f665937a8" + integrity sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA== dependencies: readable-stream "^4.0.0" split2 "^4.0.0" @@ -7023,9 +7117,9 @@ pino-http@^5.3.0: pino-std-serializers "^4.0.0" pino-pretty@*: - version "10.0.0" - resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-10.0.0.tgz#fd2f307ee897289f63d09b0b804ac2ecc9a18516" - integrity sha512-zKFjYXBzLaLTEAN1ayKpHXtL5UeRQC7R3lvhKe7fWs7hIVEjKGG/qIXwQt9HmeUp71ogUd/YcW+LmMwRp4KT6Q== + version "10.2.0" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-10.2.0.tgz#c674a153e15c08d7032a826d0051d786feace1d9" + integrity sha512-tRvpyEmGtc2D+Lr3FulIZ+R1baggQ4S3xD2Ar93KixFEDx6SEAUP3W5aYuEw1C73d6ROrNcB2IXLteW8itlwhA== dependencies: colorette "^2.0.7" dateformat "^4.6.3" @@ -7089,14 +7183,14 @@ pino@^6.13.0, pino@^6.7.0: sonic-boom "^1.0.2" pino@^8.5.0: - version "8.14.1" - resolved "https://registry.yarnpkg.com/pino/-/pino-8.14.1.tgz#bb38dcda8b500dd90c1193b6c9171eb777a47ac8" - integrity sha512-8LYNv7BKWXSfS+k6oEc6occy5La+q2sPwU3q2ljTX5AZk7v+5kND2o5W794FyRaqha6DJajmkNRsWtPpFyMUdw== + version "8.15.1" + resolved "https://registry.yarnpkg.com/pino/-/pino-8.15.1.tgz#04b815ff7aa4e46b1bbab88d8010aaa2b17eaba4" + integrity sha512-Cp4QzUQrvWCRJaQ8Lzv0mJzXVk4z2jlq8JNKMGaixC2Pz5L4l2p95TkuRvYbrEbe85NQsDKrAd4zalf7Ml6WiA== dependencies: atomic-sleep "^1.0.0" fast-redact "^3.1.1" on-exit-leak-free "^2.1.0" - pino-abstract-transport v1.0.0 + pino-abstract-transport v1.1.0 pino-std-serializers "^6.0.0" process-warning "^2.0.0" quick-format-unescaped "^4.0.3" @@ -7152,11 +7246,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== - prettier@^2.7.1: version "2.8.8" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" @@ -7325,11 +7414,6 @@ puppeteer@^15.3.0: unbzip2-stream "1.4.3" ws "8.8.0" -q@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== - qs@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -7423,14 +7507,15 @@ readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.1.1, readable-stre util-deprecate "^1.0.1" readable-stream@^4.0.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.4.0.tgz#55ce132d60a988c460d75c631e9ccf6a7229b468" - integrity sha512-kDMOq0qLtxV9f/SQv522h8cxZBqNZXuXNyjyezmfAAuribMyVXziljpQ/uQhfE1XLg2/TLTW2DsnoE4VAi/krg== + version "4.4.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.4.2.tgz#e6aced27ad3b9d726d8308515b9a1b98dc1b9d13" + integrity sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA== dependencies: abort-controller "^3.0.0" buffer "^6.0.3" events "^3.3.0" process "^0.11.10" + string_decoder "^1.3.0" readable-stream@~1.0.31: version "1.0.34" @@ -7582,18 +7667,18 @@ resolve-url@^0.2.1: integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== resolve@^1.10.0, resolve@^1.18.1, resolve@^1.19.0: - version "1.22.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" - integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== dependencies: - is-core-module "^2.11.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== +restore-cursor@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" + integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== dependencies: onetime "^5.1.0" signal-exit "^3.0.2" @@ -7632,13 +7717,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^7.8.0: - version "7.8.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== - dependencies: - tslib "^2.1.0" - safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -7716,28 +7794,21 @@ secure-json-parse@^2.4.0: integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== "semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.7.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@7.5.2: - version "7.5.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.2.tgz#5b851e66d1be07c1cdaf37dfc856f543325a2beb" - integrity sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ== - dependencies: - lru-cache "^6.0.0" + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@7.x, semver@^7.3.2, semver@^7.3.4, semver@^7.3.7, semver@^7.3.8: - version "7.5.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" - integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== +semver@7.5.4, semver@7.x, semver@^7.3.2, semver@^7.3.4, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@~7.0.0: version "7.0.0" @@ -7837,9 +7908,9 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== signal-exit@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.0.2.tgz#ff55bb1d9ff2114c13b400688fa544ac63c36967" - integrity sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q== + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== simple-update-notifier@^1.0.7: version "1.1.0" @@ -7858,24 +7929,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" - integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - slice-ansi@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" @@ -8019,7 +8072,7 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" -split2@^3.0.0, split2@^3.1.1: +split2@^3.0.0, split2@^3.1.1, split2@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== @@ -8061,7 +8114,7 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -string-argv@^0.3.1: +string-argv@0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== @@ -8083,7 +8136,7 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^5.0.0: +string-width@^5.0.0, string-width@^5.0.1: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== @@ -8092,7 +8145,7 @@ string-width@^5.0.0: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string_decoder@^1.1.1: +string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -8157,7 +8210,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -8171,9 +8224,9 @@ strtok3@^6.2.4: peek-readable "^4.1.0" supabase@^1.38.1: - version "1.74.0" - resolved "https://registry.yarnpkg.com/supabase/-/supabase-1.74.0.tgz#7dd497d520874c26d44b5ef7fb5d065d6fb41207" - integrity sha512-xWn0fEf+51Y/ed8JKJMfFK+VDc2Ev8QYJ6V/mq1qfo+JTJcDN+6Dv3FhqbS1c66HZBMptssnm7YF0uqMa4p2rg== + version "1.93.0" + resolved "https://registry.yarnpkg.com/supabase/-/supabase-1.93.0.tgz#35bd2706120379c7151622c548bdf95663b05e2f" + integrity sha512-7VKWPVy1QSnBcx/ubKIGFOWw9LjL6C1sMTh0d+ox0TP69+KhzphlA4Z/iFPvC6x9gUwhe9UTI0AdqJYsIwrPEA== dependencies: bin-links "^4.0.1" node-fetch "^3.2.10" @@ -8262,10 +8315,11 @@ tar@6.1.15: yallist "^4.0.0" telegraf@^4.11.2: - version "4.12.2" - resolved "https://registry.yarnpkg.com/telegraf/-/telegraf-4.12.2.tgz#1cf4f38c275e04416f1282f3581833994870f0bc" - integrity sha512-PgwqI4wD86cMqVfFtEM9JkGGnMHgvgLJbReZMmwW4z35QeOi4DvbdItONld4bPnYn3A1jcO0SRKs0BXmR+x+Ew== + version "4.13.1" + resolved "https://registry.yarnpkg.com/telegraf/-/telegraf-4.13.1.tgz#ad0b6df452aa133bf6561b4a182bdedb558046b6" + integrity sha512-WXITwqE3ivqDqjHFxj94xaQhHddldBZdE2g/hRJXyCMTkwZYw69q9I7La7nsDpsHLn5ADSQlGv0KAbwFkFpmlA== dependencies: + "@telegraf/types" "^6.8.1" abort-controller "^3.0.0" debug "^4.3.4" mri "^1.2.0" @@ -8273,7 +8327,6 @@ telegraf@^4.11.2: p-timeout "^4.1.0" safe-compare "^1.1.4" sandwich-stream "^2.0.2" - typegram "^4.3.0" terminal-link@^2.0.0: version "2.1.1" @@ -8303,9 +8356,9 @@ text-table@^0.2.0: integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== thread-stream@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.3.0.tgz#4fc07fb39eff32ae7bad803cb7dd9598349fed33" - integrity sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA== + version "2.4.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.4.0.tgz#5def29598d1d4171ba3bace7e023a71d87d99c07" + integrity sha512-xZYtOtmnA63zj04Q+F9bdEay5r47bvpo1CaNqsKi7TpoJHcotUez8Fkfo2RJWpW91lnnaApdpRbVwCWsy+ifcw== dependencies: real-require "^0.2.0" @@ -8478,11 +8531,6 @@ tslib@^1.8.1, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.1.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" - integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== - tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -8491,12 +8539,12 @@ tsutils@^3.21.0: tslib "^1.8.1" tsx@^3.12.7: - version "3.12.7" - resolved "https://registry.yarnpkg.com/tsx/-/tsx-3.12.7.tgz#b3b8b0fc79afc8260d1e14f9e995616c859a91e9" - integrity sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw== + version "3.12.8" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-3.12.8.tgz#e9ec95c6b116e28f0187467f839029a3ce17a851" + integrity sha512-Lt9KYaRGF023tlLInPj8rgHwsZU8qWLBj4iRXNWxTfjIkU7canGL806AqKear1j722plHuiYNcL2ZCo6uS9UJA== dependencies: "@esbuild-kit/cjs-loader" "^2.4.2" - "@esbuild-kit/core-utils" "^3.0.0" + "@esbuild-kit/core-utils" "^3.2.2" "@esbuild-kit/esm-loader" "^2.5.5" optionalDependencies: fsevents "~2.3.2" @@ -8513,13 +8561,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" - type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -8555,6 +8596,11 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-fest@^1.0.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" + integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -8580,15 +8626,10 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typegram@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/typegram/-/typegram-4.3.0.tgz#690ec1287f771608070e149c92de4fca42e54db0" - integrity sha512-pS4STyOZoJ++Mwa9GPMTNjOwEzMkxFfFt1By6IbMOJfheP0utMP/H1ga6J9R4DTjAYBr0UDn4eQg++LpWBvcAg== - "typescript@^4.6.4 || ^5.0.0": - version "5.1.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.3.tgz#8d84219244a6b40b6fb2b33cc1c062f715b9e826" - integrity sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw== + version "5.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== typescript@^4.9.5: version "4.9.5" @@ -8754,9 +8795,9 @@ validate-npm-package-license@^3.0.1: spdx-expression-parse "^3.0.0" validator@^13.7.0: - version "13.9.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855" - integrity sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA== + version "13.11.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.11.0.tgz#23ab3fd59290c61248364eabf4067f04955fbb1b" + integrity sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ== vary@~1.1.2: version "1.1.2" @@ -8784,6 +8825,11 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.12" +web-streams-polyfill@4.0.0-beta.3: + version "4.0.0-beta.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38" + integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug== + web-streams-polyfill@^3.0.3: version "3.2.1" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" @@ -8824,9 +8870,9 @@ whatwg-encoding@^1.0.5: iconv-lite "0.4.24" whatwg-fetch@^3.4.1: - version "3.6.2" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" - integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== + version "3.6.18" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.18.tgz#2f640cdee315abced7daeaed2309abd1e44e62d4" + integrity sha512-ltN7j66EneWn5TFDO4L9inYC1D+Czsxlrw2SalgjMmEMkLfA5SIZxEFdE6QtHFiiM6Q7WL32c7AkI3w6yxM84Q== whatwg-mimetype@^2.3.0: version "2.3.0" @@ -8869,11 +8915,6 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - wordwrap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" @@ -8897,6 +8938,15 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -9003,11 +9053,16 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^2.2.2: +yaml@2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== +yaml@^2.2.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144" + integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg== + yargs-parser@20.x, yargs-parser@^20.2.2, yargs-parser@^20.2.3: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" From b417336356e2ad7df62aa1fcf04e1ed71f4ea87c Mon Sep 17 00:00:00 2001 From: Sadaf Ahmed <119438857+Sadaf-A@users.noreply.github.com> Date: Fri, 22 Sep 2023 08:54:36 +0530 Subject: [PATCH 88/88] refactor: config Name Format (#761) * feat(camelCase): changing config file case from kebab case to camel case * refactor(config): reverting file name to ubiquibot-config.yml * feat(camelCase): - changing ubiquibot-config-default.json to cameCase * feat(private): - changing to camelCase in private * feat(config.ts): - updating WideConfigSchema and MergedConfigSchema * feat(update-base): - updating price-multiplier to camelCase counterpart priceMultiplier * fix(config): - removing quotes * fix(quotes): - removing left out quotes * fix(ts-errors): - fixing ts errors * fix: build --------- Co-authored-by: 0xCodercrane <108444211+0xcodercrane@users.noreply.github.com> --- .github/ubiquibot-config.yml | 2 +- src/bindings/config.ts | 2 +- src/configs/ubiquibot-config-default.ts | 57 +++++++++--------- src/handlers/push/update-base.ts | 4 +- src/types/config.ts | 78 ++++++++++++------------- src/utils/private.ts | 41 ++++++------- 6 files changed, 92 insertions(+), 92 deletions(-) diff --git a/.github/ubiquibot-config.yml b/.github/ubiquibot-config.yml index 336f1f1a4..3f02c40eb 100644 --- a/.github/ubiquibot-config.yml +++ b/.github/ubiquibot-config.yml @@ -1 +1 @@ -price-multiplier: 1.5 \ No newline at end of file +priceMultiplier: 1.5 \ No newline at end of file diff --git a/src/bindings/config.ts b/src/bindings/config.ts index 413e3faef..38e72260d 100644 --- a/src/bindings/config.ts +++ b/src/bindings/config.ts @@ -103,7 +103,7 @@ export const loadConfig = async (context: Context): Promise => { }, ask: { apiKey: openAIKey, - tokenLimit: openAITokenLimit, + tokenLimit: openAITokenLimit || 0, }, accessControl: enableAccessControl, }; diff --git a/src/configs/ubiquibot-config-default.ts b/src/configs/ubiquibot-config-default.ts index a5f764862..310450835 100644 --- a/src/configs/ubiquibot-config-default.ts +++ b/src/configs/ubiquibot-config-default.ts @@ -1,22 +1,19 @@ import { MergedConfig } from "../types"; -export const DefaultConfig: MergedConfig = { - "evm-network-id": 100, - "price-multiplier": 1, - "issue-creator-multiplier": 2, - "payment-permit-max-price": 9007199254740991, - "max-concurrent-assigns": 9007199254740991, - "assistive-pricing": false, - "disable-analytics": false, - "comment-incentives": false, - "register-wallet-with-verification": false, - "openai-api-key": null, - "openai-token-limit": 8000, - "stale-bounty-time": "0d", - "promotion-comment": - "\n
If you enjoy the DevPool experience, please follow Ubiquity on GitHub and star this repo to show your support. It helps a lot!
", - "default-labels": [], - "time-labels": [ +export const DefaultConfig : MergedConfig = { + evmNetworkId: 100, + priceMultiplier: 1, + issueCreatorMultiplier: 2, + paymentPermitMaxPrice: 9007199254740991, + maxConcurrentAssigns: 9007199254740991, + assistivePricing: false, + disableAnalytics: false, + commentIncentives: false, + registerWalletWithVerification: false, + promotionComment: "\n
If you enjoy the DevPool experience, please follow Ubiquity on GitHub and star this repo to show your support. It helps a lot!
", + defaultLabels: [], + timeLabels: [ + { name: "Time: <1 Hour", }, @@ -33,7 +30,7 @@ export const DefaultConfig: MergedConfig = { name: "Time: <1 Month", }, ], - "priority-labels": [ + priorityLabels: [ { name: "Priority: 1 (Normal)", }, @@ -50,7 +47,7 @@ export const DefaultConfig: MergedConfig = { name: "Priority: 5 (Emergency)", }, ], - "command-settings": [ + commandSettings: [ { name: "start", enabled: false, @@ -89,15 +86,17 @@ export const DefaultConfig: MergedConfig = { }, ], incentives: { - comment: { - elements: {}, - totals: { - word: 0, - }, - }, + + "comment": { + "elements": {}, + "totals": { + "word": 0 + } + } }, - "enable-access-control": { - label: false, - organization: true, + enableAccessControl: { + "label": false, + "organization": true }, -}; + staleBountyTime:"0d" +} diff --git a/src/handlers/push/update-base.ts b/src/handlers/push/update-base.ts index 4141d811f..da67c8e6c 100644 --- a/src/handlers/push/update-base.ts +++ b/src/handlers/push/update-base.ts @@ -21,12 +21,12 @@ export const updateBaseRate = async (context: Context, payload: PushPayload, fil const previousContent = Buffer.from(preFileContent, "base64").toString(); const previousConfig = await parseYAML(previousContent); - if (!previousConfig || !previousConfig["price-multiplier"]) { + if (!previousConfig || !previousConfig["priceMultiplier"]) { logger.debug("No multiplier found in file object"); return; } - const previousBaseRate = previousConfig["price-multiplier"]; + const previousBaseRate = previousConfig["priceMultiplier"]; // fetch all labels const repoLabels = await listLabelsForRepo(); diff --git a/src/types/config.ts b/src/types/config.ts index 4f5dde5ce..d2ea2fb75 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -106,7 +106,7 @@ export const CommentsSchema = Type.Object({ }); export const AskSchema = Type.Object({ - apiKey: Type.Union([Type.String(), Type.Null()]), + apiKey: Type.Optional(Type.String()), tokenLimit: Type.Number(), }); @@ -163,26 +163,26 @@ export type GPTResponse = Static; export const WideConfigSchema = Type.Object( { - "evm-network-id": Type.Optional(Type.Number()), - "price-multiplier": Type.Optional(Type.Number()), - "issue-creator-multiplier": Type.Optional(Type.Number()), - "time-labels": Type.Optional(Type.Array(LabelItemSchema)), - "priority-labels": Type.Optional(Type.Array(LabelItemSchema)), - "payment-permit-max-price": Type.Optional(Type.Number()), - "command-settings": Type.Optional(Type.Array(CommandItemSchema)), - "promotion-comment": Type.Optional(Type.String()), - "disable-analytics": Type.Optional(Type.Boolean()), - "comment-incentives": Type.Optional(Type.Boolean()), - "assistive-pricing": Type.Optional(Type.Boolean()), - "max-concurrent-assigns": Type.Optional(Type.Number()), + evmNetworkId: Type.Optional(Type.Number()), + priceMultiplier: Type.Optional(Type.Number()), + issueCreatorMultiplier: Type.Optional(Type.Number()), + timeLabels: Type.Optional(Type.Array(LabelItemSchema)), + priorityLabels: Type.Optional(Type.Array(LabelItemSchema)), + paymentPermitMaxPrice: Type.Optional(Type.Number()), + commandSettings: Type.Optional(Type.Array(CommandItemSchema)), + promotionComment: Type.Optional(Type.String()), + disableAnalytics: Type.Optional(Type.Boolean()), + commentIncentives: Type.Optional(Type.Boolean()), + assistivePricing: Type.Optional(Type.Boolean()), + maxConcurrentAssigns: Type.Optional(Type.Number()), incentives: Type.Optional(IncentivesSchema), - "default-labels": Type.Optional(Type.Array(Type.String())), - "register-wallet-with-verification": Type.Optional(Type.Boolean()), - "enable-access-control": Type.Optional(AccessControlSchema), - "stale-bounty-time": Type.Optional(Type.String()), - "openai-api-key": AskSchema.apiKey, - "openai-token-limit": Type.Optional(Type.Number()), - "private-key-encrypted": Type.Optional(Type.String()), + defaultLabels: Type.Optional(Type.Array(Type.String())), + registerWalletWithVerification: Type.Optional(Type.Boolean()), + enableAccessControl: Type.Optional(AccessControlSchema), + openAIKey: Type.Optional(Type.String()), + openAITokenLimit: Type.Optional(Type.Number()), + staleBountyTime: Type.Optional(Type.String()), + privateKeyEncrypted: Type.Optional(Type.String()), }, { additionalProperties: false, @@ -194,26 +194,26 @@ export type WideConfig = Static; export type WideRepoConfig = WideConfig; export const MergedConfigSchema = Type.Object({ - "evm-network-id": Type.Number(), - "price-multiplier": Type.Number(), - "private-key-encrypted": Type.Optional(Type.String()), - "issue-creator-multiplier": Type.Number(), - "time-labels": Type.Array(LabelItemSchema), - "priority-labels": Type.Array(LabelItemSchema), - "payment-permit-max-price": Type.Number(), - "command-settings": Type.Array(CommandItemSchema), - "promotion-comment": Type.String(), - "disable-analytics": Type.Boolean(), - "comment-incentives": Type.Boolean(), - "assistive-pricing": Type.Boolean(), - "max-concurrent-assigns": Type.Number(), + evmNetworkId: Type.Number(), + priceMultiplier: Type.Number(), + privateKeyEncrypted: Type.Optional(Type.String()), + issueCreatorMultiplier: Type.Number(), + timeLabels: Type.Array(LabelItemSchema), + priorityLabels: Type.Array(LabelItemSchema), + paymentPermitMaxPrice: Type.Number(), + commandSettings: Type.Array(CommandItemSchema), + promotionComment: Type.String(), + disableAnalytics: Type.Boolean(), + commentIncentives: Type.Boolean(), + assistivePricing: Type.Boolean(), + maxConcurrentAssigns: Type.Number(), incentives: IncentivesSchema, - "default-labels": Type.Array(Type.String()), - "register-wallet-with-verification": Type.Boolean(), - "enable-access-control": AccessControlSchema, - "openai-api-key": AskSchema.apiKey, - "openai-token-limit": Type.Number(), - "stale-bounty-time": Type.String(), + defaultLabels: Type.Array(Type.String()), + registerWalletWithVerification: Type.Boolean(), + enableAccessControl: AccessControlSchema, + openAIKey: Type.Optional(Type.String()), + openAITokenLimit: Type.Optional(Type.Number()), + staleBountyTime: Type.String(), }); export type MergedConfig = Static; diff --git a/src/utils/private.ts b/src/utils/private.ts index 87a4ddf63..2e2a730e6 100644 --- a/src/utils/private.ts +++ b/src/utils/private.ts @@ -10,7 +10,7 @@ import { WideConfig, WideRepoConfig, WideConfigSchema } from "../types"; const CONFIG_REPO = "ubiquibot-config"; const CONFIG_PATH = ".github/ubiquibot-config.yml"; -const KEY_NAME = "private-key-encrypted"; +const KEY_NAME = "privateKeyEncrypted"; const KEY_PREFIX = "HSK_"; export const getConfigSuperset = async (context: Context, type: "org" | "repo", filePath: string): Promise => { @@ -141,26 +141,27 @@ export const getWideConfig = async (context: Context) => { const mergedConfigData: MergedConfig = mergeConfigs(configs); const configData = { - networkId: mergedConfigData["evm-network-id"], + networkId: mergedConfigData.evmNetworkId, privateKey: privateKeyDecrypted ?? "", - assistivePricing: mergedConfigData["assistive-pricing"], - commandSettings: mergedConfigData["command-settings"], - baseMultiplier: mergedConfigData["price-multiplier"], - issueCreatorMultiplier: mergedConfigData["issue-creator-multiplier"], - timeLabels: mergedConfigData["time-labels"], - priorityLabels: mergedConfigData["priority-labels"], - paymentPermitMaxPrice: mergedConfigData["payment-permit-max-price"], - disableAnalytics: mergedConfigData["disable-analytics"], - bountyHunterMax: mergedConfigData["max-concurrent-assigns"], - incentiveMode: mergedConfigData["comment-incentives"], - incentives: mergedConfigData["incentives"], - defaultLabels: mergedConfigData["default-labels"], - promotionComment: mergedConfigData["promotion-comment"], - registerWalletWithVerification: mergedConfigData["register-wallet-with-verification"], - enableAccessControl: mergedConfigData["enable-access-control"], - openAIKey: mergedConfigData["openai-api-key"], - openAITokenLimit: mergedConfigData["openai-token-limit"], - staleBountyTime: mergedConfigData["stale-bounty-time"], + assistivePricing: mergedConfigData.assistivePricing, + commandSettings: mergedConfigData.commandSettings, + baseMultiplier: mergedConfigData.priceMultiplier, + issueCreatorMultiplier: mergedConfigData.issueCreatorMultiplier, + timeLabels: mergedConfigData.timeLabels, + priorityLabels: mergedConfigData.priorityLabels, + paymentPermitMaxPrice: mergedConfigData.paymentPermitMaxPrice, + disableAnalytics: mergedConfigData.disableAnalytics, + bountyHunterMax: mergedConfigData.maxConcurrentAssigns, + incentiveMode: mergedConfigData.commentIncentives, + incentives: mergedConfigData.incentives, + defaultLabels: mergedConfigData.defaultLabels, + promotionComment: mergedConfigData.promotionComment, + registerWalletWithVerification: mergedConfigData.registerWalletWithVerification, + enableAccessControl: mergedConfigData.enableAccessControl, + openAIKey: mergedConfigData.openAIKey, + openAITokenLimit: mergedConfigData.openAITokenLimit, + staleBountyTime: mergedConfigData.staleBountyTime, + }; return configData;