From 3056bc91e062ab9e1b161d34d2da1418a3771a30 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Sat, 23 Sep 2023 22:08:01 +0200 Subject: [PATCH 1/7] feat: adjustments --- README.md | 16 ------- src/configs/ubiquibot-config-default.ts | 30 ++++++++++-- src/handlers/comment/handlers/ask.ts | 2 +- src/handlers/comment/handlers/index.ts | 2 +- src/handlers/comment/handlers/table.ts | 64 ++++++++++++++++++------- src/handlers/push/index.ts | 4 +- src/helpers/gpt.ts | 10 ++-- src/types/config.ts | 6 +-- src/utils/private.ts | 16 +++---- 9 files changed, 92 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index e8d09c845..6c4c121d7 100644 --- a/README.md +++ b/README.md @@ -224,22 +224,6 @@ 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.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. - -```jsonc -{ - "payment-permit-max-price": 9007199254740991, // Number.MAX_SAFE_INTEGER - "max-concurrent-assigns": 9007199254740991, // Number.MAX_SAFE_INTEGER - "comment-element-pricing": { - /* https://github.com/syntax-tree/mdast#nodes */ - "strong": 0 // Also includes italics, unfortunately https://github.com/syntax-tree/mdast#strong - /* https://github.com/syntax-tree/mdast#gfm */ - } -} -``` - ## Supabase Cron Job (`logs-cleaner`) ##### Dashboard > Project > Database > Extensions diff --git a/src/configs/ubiquibot-config-default.ts b/src/configs/ubiquibot-config-default.ts index 4a989995f..5a5e29e5d 100644 --- a/src/configs/ubiquibot-config-default.ts +++ b/src/configs/ubiquibot-config-default.ts @@ -4,8 +4,8 @@ export const DefaultConfig: MergedConfig = { evmNetworkId: 100, priceMultiplier: 1, issueCreatorMultiplier: 2, - paymentPermitMaxPrice: 9007199254740991, - maxConcurrentAssigns: 9007199254740991, + paymentPermitMaxPrice: Number.MAX_SAFE_INTEGER, + maxConcurrentAssigns: Number.MAX_SAFE_INTEGER, assistivePricing: false, disableAnalytics: false, commentIncentives: false, @@ -87,7 +87,31 @@ export const DefaultConfig: MergedConfig = { ], incentives: { comment: { - elements: {}, + elements: { + h1: 0, + h2: 0, + h3: 0, + h4: 0, + h5: 0, + h6: 0, + a: 0, + ul: 0, + li: 0, + p: 0, + img: 0, + code: 0, + table: 0, + td: 0, + tr: 0, + br: 0, + blockquote: 0, + em: 0, + strong: 0, + hr: 0, + del: 0, + pre: 0, + ol: 0, + }, totals: { word: 0, }, diff --git a/src/handlers/comment/handlers/ask.ts b/src/handlers/comment/handlers/ask.ts index 63777d4ae..e2a4d2e36 100644 --- a/src/handlers/comment/handlers/ask.ts +++ b/src/handlers/comment/handlers/ask.ts @@ -21,7 +21,7 @@ export const ask = async (body: string) => { } if (!issue) { - return `This command can only be used on issues`; + return `This command can only be used on issues on pull requests`; } const chatHistory: CreateChatCompletionRequestMessage[] = []; diff --git a/src/handlers/comment/handlers/index.ts b/src/handlers/comment/handlers/index.ts index 490b0b934..47bf8eccb 100644 --- a/src/handlers/comment/handlers/index.ts +++ b/src/handlers/comment/handlers/index.ts @@ -288,7 +288,7 @@ export const userCommands = (): UserCommands[] => { }, { id: IssueCommentCommands.ASK, - description: `Ask a technical question to the Ubiquity AI. \n example usage: "/ask How do I do X?"`, + description: `Ask a technical question to the UbiquiBot. \n example usage: "/ask How do I do X?"`, handler: ask, callback: commandCallback, }, diff --git a/src/handlers/comment/handlers/table.ts b/src/handlers/comment/handlers/table.ts index 97f154e0b..a54769f77 100644 --- a/src/handlers/comment/handlers/table.ts +++ b/src/handlers/comment/handlers/table.ts @@ -16,23 +16,51 @@ export const tableComment = ({ days?: number; }) => { return ` - -${ - 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}
`; + ${ + isBountyStale + ? ` + + Warning! + This task was created over ${days} days ago. Please confirm that this issue specification is accurate before starting. + ` + : `` + } + + Deadline + ${deadline} + + + Registered Wallet + ${wallet} + + ${ + multiplier + ? ` + + Payment Multiplier + ${multiplier} + ` + : `` + } + ${ + reason + ? ` + + Multiplier Reason + ${reason} + ` + : `` + } + ${ + bounty + ? ` + + Total Bounty + ${bounty} + ` + : `` + } + +`; }; diff --git a/src/handlers/push/index.ts b/src/handlers/push/index.ts index 340143439..2abc418c8 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, WideConfigSchema } from "../../types"; +import { CommitsPayload, PushPayload, ConfigSchema } 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(WideConfigSchema, config); + const { valid, error } = validate(ConfigSchema, config); if (!valid) { await createCommitComment(`@${payload.sender.login} Config validation failed! ${error}`, commitSha, BASE_RATE_FILE); } diff --git a/src/helpers/gpt.ts b/src/helpers/gpt.ts index 046503d79..dc78cf3e3 100644 --- a/src/helpers/gpt.ts +++ b/src/helpers/gpt.ts @@ -5,7 +5,7 @@ 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 +export const sysMsg = `You are the UbiquiBot, 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 @@ -14,7 +14,7 @@ All replies MUST end with "\n\n ".\n `; export const gptContextTemplate = ` -You are the UbiquityAI, designed to review and analyze pull requests. +You are the UbiquiBot, 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. @@ -118,17 +118,17 @@ export const decideContextGPT = async ( { role: "system", content: "This issue/Pr context: \n" + JSON.stringify(streamlined), - name: "UbiquityAI", + name: "UbiquiBot", } as CreateChatCompletionRequestMessage, { role: "system", content: "Linked issue(s) context: \n" + JSON.stringify(linkedIssueStreamlined), - name: "UbiquityAI", + name: "UbiquiBot", } as CreateChatCompletionRequestMessage, { role: "system", content: "Linked Pr(s) context: \n" + JSON.stringify(linkedPRStreamlined), - name: "UbiquityAI", + name: "UbiquiBot", } as CreateChatCompletionRequestMessage ); diff --git a/src/types/config.ts b/src/types/config.ts index cd6d6d109..8614a7416 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -170,7 +170,7 @@ export const GPTResponseSchema = Type.Object({ export type GPTResponse = Static; -export const WideConfigSchema = Type.Object( +export const ConfigSchema = Type.Object( { evmNetworkId: Type.Optional(Type.Number()), priceMultiplier: Type.Optional(Type.Number()), @@ -199,9 +199,7 @@ export const WideConfigSchema = Type.Object( } ); -export type WideConfig = Static; - -export type WideRepoConfig = WideConfig; +export type Config = Static; export const MergedConfigSchema = Type.Object({ evmNetworkId: Type.Number(), diff --git a/src/utils/private.ts b/src/utils/private.ts index 9568f45dd..a92d73b02 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, WideRepoConfig, WideConfigSchema } from "../types"; +import { Config, ConfigSchema } from "../types"; const CONFIG_REPO = "ubiquibot-config"; const CONFIG_PATH = ".github/ubiquibot-config.yml"; @@ -34,12 +34,12 @@ export const getConfigSuperset = async (context: Context, type: "org" | "repo", }; export interface MergedConfigs { - parsedRepo: WideRepoConfig | undefined; - parsedOrg: WideRepoConfig | undefined; + parsedRepo: Config | undefined; + parsedOrg: Config | undefined; parsedDefault: MergedConfig; } -export const parseYAML = (data?: string): WideConfig | undefined => { +export const parseYAML = (data?: string): Config | undefined => { try { if (data) { const parsedData = YAML.parse(data); @@ -111,17 +111,17 @@ export const getWideConfig = async (context: Context) => { const orgConfig = await getConfigSuperset(context, "org", CONFIG_PATH); const repoConfig = await getConfigSuperset(context, "repo", CONFIG_PATH); - const parsedOrg: WideRepoConfig | undefined = parseYAML(orgConfig); + const parsedOrg: Config | undefined = parseYAML(orgConfig); if (parsedOrg) { - const { valid, error } = validate(WideConfigSchema, parsedOrg); + const { valid, error } = validate(ConfigSchema, parsedOrg); if (!valid) { throw new Error(`Invalid org config: ${error}`); } } - const parsedRepo: WideRepoConfig | undefined = parseYAML(repoConfig); + const parsedRepo: Config | undefined = parseYAML(repoConfig); if (parsedRepo) { - const { valid, error } = validate(WideConfigSchema, parsedRepo); + const { valid, error } = validate(ConfigSchema, parsedRepo); if (!valid) { throw new Error(`Invalid repo config: ${error}`); } From e3449066c12419e78c987e9722d6e41f84d1a97a Mon Sep 17 00:00:00 2001 From: whilefoo Date: Sun, 24 Sep 2023 22:33:48 +0200 Subject: [PATCH 2/7] feat: rename priceInEth and retrieve decimals for payment token --- src/handlers/payout/post.ts | 18 +++++++++--------- src/helpers/permit.ts | 21 ++++++++++++++------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index 18d9aa1df..0b64c7693 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -12,7 +12,7 @@ import { BigNumber } from "ethers"; export interface CreatorCommentResult { title: string; account?: string | undefined; - amountInETH?: Decimal | undefined; + rewardInTokens?: Decimal | undefined; userId?: string | undefined; tokenSymbol?: string | undefined; node_id?: string | undefined; @@ -148,8 +148,8 @@ export const calculateIssueCreatorReward = async (incentivesCalculation: Incenti incentivesCalculation.paymentPermitMaxPrice ); - if (!result || !result.account || !result.amountInETH) { - throw new Error("Failed to generate permit for issue creator because of missing account or amountInETH"); + if (!result || !result.account || !result.rewardInTokens) { + throw new Error("Failed to generate permit for issue creator because of missing account or rewardInTokens"); } return { @@ -159,7 +159,7 @@ export const calculateIssueCreatorReward = async (incentivesCalculation: Incenti username: creator.login, reward: [ { - priceInEth: result?.amountInETH ?? new Decimal(0), + priceInEth: result?.rewardInTokens ?? new Decimal(0), account: result?.account, userId: "", user: "", @@ -278,7 +278,7 @@ const generatePermitForComments = async ( multiplier: number, incentives: Incentives, paymentPermitMaxPrice: number -): Promise => { +): Promise => { const logger = getLogger(); const commentsByNode = await parseComments(comments, ItemsToExclude); const rewardValue = calculateRewardValue(commentsByNode, incentives); @@ -288,15 +288,15 @@ const generatePermitForComments = async ( } 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)) { + const rewardInTokens = rewardValue.mul(multiplier); + if (rewardInTokens.gt(paymentPermitMaxPrice)) { logger.info(`Skipping issue creator reward for user ${user} because reward is higher than payment permit max price`); return; } if (account) { - return { account, amountInETH }; + return { account, rewardInTokens }; } else { - return { account: "0x", amountInETH: new Decimal(0) }; + return { account: "0x", rewardInTokens: new Decimal(0) }; } }; /** diff --git a/src/helpers/permit.ts b/src/helpers/permit.ts index 064b8918c..c56188a94 100644 --- a/src/helpers/permit.ts +++ b/src/helpers/permit.ts @@ -5,6 +5,7 @@ import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; import Decimal from "decimal.js"; import { Payload } from "../types"; import { savePermit } from "../adapters/supabase"; +import { ERC20ABI } from "../configs"; const PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3"; // same on all networks @@ -45,16 +46,16 @@ type TxData = { }; /** - * Generates permit2 signature data with `spender` and `amountInETH` + * Generates permit2 signature data with `spender` and `amountInTokens` * * @param spender The recipient address we're going to send tokens - * @param amountInETH The token amount in ETH + * @param amountInTokens The token amount * * @returns Permit2 url including base64 encocded data */ export const generatePermit2Signature = async ( spender: string, - amountInEth: Decimal, + amountInTokens: Decimal, identifier: string, userId = "" ): Promise<{ txData: TxData; payoutUrl: string }> => { @@ -65,12 +66,15 @@ export const generatePermit2Signature = async ( const provider = new ethers.providers.JsonRpcProvider(rpc); const adminWallet = new ethers.Wallet(privateKey, provider); + const tokenContract = new ethers.Contract(paymentToken, ERC20ABI, provider); + const decimals = await tokenContract.decimals(); + const permitTransferFromData: PermitTransferFrom = { permitted: { // token we are permitting to be transferred token: paymentToken, // amount we are permitting to be transferred - amount: ethers.utils.parseUnits(amountInEth.toString(), 18), + amount: ethers.utils.parseUnits(amountInTokens.toString(), decimals), }, // who can transfer the tokens spender: spender, @@ -101,9 +105,12 @@ export const generatePermit2Signature = async ( const base64encodedTxData = Buffer.from(JSON.stringify(txData)).toString("base64"); - const payoutUrl = `${permitBaseUrl}?claim=${base64encodedTxData}&network=${networkId}`; - logger.info(`Generated permit2 url: ${payoutUrl}`); - return { txData, payoutUrl }; + const payoutUrl = new URL(permitBaseUrl); + payoutUrl.searchParams.append("claim", base64encodedTxData); + payoutUrl.searchParams.append("network", networkId.toString()); + logger.info(`Generated permit2 of amount ${amountInTokens} for user ${spender}, url: ${payoutUrl}`); + + return { txData, payoutUrl: payoutUrl.toString() }; }; export const savePermitToDB = async (bountyHunterId: number, txData: TxData): Promise => { From 2df5613127b89bb81f9903ca1adc578928083b14 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Sun, 24 Sep 2023 22:42:08 +0200 Subject: [PATCH 3/7] feat: use permitBaseUrl instead of hardcoded --- src/handlers/comment/handlers/payout.ts | 7 +++++-- src/handlers/payout/post.ts | 17 +++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/handlers/comment/handlers/payout.ts b/src/handlers/comment/handlers/payout.ts index d5aabc7d6..2255f8599 100644 --- a/src/handlers/comment/handlers/payout.ts +++ b/src/handlers/comment/handlers/payout.ts @@ -1,4 +1,4 @@ -import { getBotContext, getLogger } from "../../../bindings"; +import { getBotConfig, getBotContext, getLogger } from "../../../bindings"; import { Payload } from "../../../types"; import { IssueCommentCommands } from "../commands"; import { @@ -14,6 +14,9 @@ import { GLOBAL_STRINGS } from "../../../configs"; export const payout = async (body: string) => { const { payload: _payload } = getBotContext(); + const { + payout: { permitBaseUrl }, + } = getBotConfig(); const logger = getLogger(); if (body != IssueCommentCommands.PAYOUT && body.replace(/`/g, "") != IssueCommentCommands.PAYOUT) { logger.info(`Skipping to payout. body: ${body}`); @@ -39,7 +42,7 @@ export const payout = async (body: string) => { return `Permit generation failed due to internal GitHub Error`; } - const hasPosted = IssueComments.find((e) => e.user.type === "Bot" && e.body.includes("https://pay.ubq.fi?claim")); + const hasPosted = IssueComments.find((e) => e.user.type === "Bot" && e.body.includes(permitBaseUrl)); if (hasPosted) { logger.info(`Permit already generated for ${payload.issue?.number}`); return; diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index 0b64c7693..4b24cadce 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -1,5 +1,5 @@ import { getWalletAddress } from "../../adapters/supabase"; -import { getBotContext, getLogger } from "../../bindings"; +import { getBotConfig, getBotContext, getLogger } from "../../bindings"; import { getAllIssueComments, getAllPullRequestReviews, getIssueDescription, parseComments } from "../../helpers"; import { getLatestPullRequest, gitLinkedPrParser } from "../../helpers/parser"; import { Incentives, MarkdownItem, Payload, UserType } from "../../types"; @@ -29,11 +29,14 @@ export const calculateIssueConversationReward = async (calculateIncentives: Ince const logger = getLogger(); const context = getBotContext(); + const { + payout: { permitBaseUrl }, + } = getBotConfig(); const payload = context.payload as Payload; const issue = payload.issue; const permitComments = calculateIncentives.comments.filter( - (content) => content.body.includes(title) && content.body.includes("https://pay.ubq.fi?claim=") && content.user.type == UserType.Bot + (content) => content.body.includes(title) && content.body.includes(permitBaseUrl) && content.user.type == UserType.Bot ); if (permitComments.length > 0) { logger.info(`incentivizeComments: skip to generate a permit url because it has been already posted`); @@ -105,6 +108,9 @@ export const calculateIssueConversationReward = async (calculateIncentives: Ince export const calculateIssueCreatorReward = async (incentivesCalculation: IncentivesCalculationResult): Promise => { const title = `Task Creator`; const logger = getLogger(); + const { + payout: { permitBaseUrl }, + } = getBotConfig(); const issueDetailed = bountyInfo(incentivesCalculation.issue); if (!issueDetailed.isBounty) { @@ -114,7 +120,7 @@ export const calculateIssueCreatorReward = async (incentivesCalculation: Incenti 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 + (content) => content.body.includes(title) && content.body.includes(permitBaseUrl) && content.user.type == UserType.Bot ); if (permitComments.length > 0) { logger.info(`incentivizeCreatorComment: skip to generate a permit url because it has been already posted`); @@ -172,6 +178,9 @@ export const calculateIssueCreatorReward = async (incentivesCalculation: Incenti export const calculatePullRequestReviewsReward = async (incentivesCalculation: IncentivesCalculationResult): Promise => { const logger = getLogger(); const context = getBotContext(); + const { + payout: { permitBaseUrl }, + } = getBotConfig(); const title = "Reviewer"; const linkedPullRequest = await gitLinkedPrParser({ @@ -189,7 +198,7 @@ export const calculatePullRequestReviewsReward = async (incentivesCalculation: I 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 + (content) => content.body.includes(title) && content.body.includes(permitBaseUrl) && content.user.type == UserType.Bot ); if (permitComments.length > 0) { logger.info(`calculatePullRequestReviewsReward: skip to generate a permit url because it has been already posted`); From 660e205fb34756eeaea12bef1ff473445328eaa5 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Sun, 24 Sep 2023 22:50:12 +0200 Subject: [PATCH 4/7] feat: improve regex --- 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 0afe9c424..b5aa4895b 100644 --- a/src/handlers/payout/action.ts +++ b/src/handlers/payout/action.ts @@ -91,8 +91,8 @@ export const incentivesCalculation = async (): Promise e.user.type === UserType.Bot && e.body.match(claimUrlRegex)); + const claimUrlRegex = new RegExp(`\\((${permitBaseUrl}\\S+)\\)`); + const permitCommentIdx = comments.findIndex((e) => e.user.type === UserType.Bot && e.body.match(claimUrlRegex) && e.body.includes("Task Assignee Reward")); if (wasReopened && permitCommentIdx !== -1) { const permitComment = comments[permitCommentIdx]; From 85425383511a601488c1e83e75a4a88c834b5cc4 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Sun, 24 Sep 2023 23:08:17 +0200 Subject: [PATCH 5/7] feat: remove restriction where issue creator will not get reward if they were also the assignee --- src/handlers/payout/post.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/handlers/payout/post.ts b/src/handlers/payout/post.ts index 4b24cadce..a4ef8f8b4 100644 --- a/src/handlers/payout/post.ts +++ b/src/handlers/payout/post.ts @@ -136,14 +136,14 @@ export const calculateIssueCreatorReward = async (incentivesCalculation: Incenti 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(`Skipping issue creator reward because issue description is empty. description: ${description}`); + return { error: `Skipping issue creator reward 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." }; + if (creator.type === UserType.Bot) { + logger.info("Skipping issue creator reward because Bot created this issue."); + return { error: "Skipping issue creator reward because Bot created this issue." }; } const result = await generatePermitForComments( From 31f8e8081c7d43ac4e041a6a13333be41e8e4b10 Mon Sep 17 00:00:00 2001 From: whilefoo <139262667+whilefoo@users.noreply.github.com> Date: Tue, 26 Sep 2023 10:41:30 +0200 Subject: [PATCH 6/7] fix: wording MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: アレクサンダー.eth <4975670+pavlovcik@users.noreply.github.com> --- src/handlers/comment/handlers/ask.ts | 2 +- src/handlers/comment/handlers/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/handlers/comment/handlers/ask.ts b/src/handlers/comment/handlers/ask.ts index e2a4d2e36..27c841574 100644 --- a/src/handlers/comment/handlers/ask.ts +++ b/src/handlers/comment/handlers/ask.ts @@ -21,7 +21,7 @@ export const ask = async (body: string) => { } if (!issue) { - return `This command can only be used on issues on pull requests`; + return `This command can only be used on issues or pull requests`; } const chatHistory: CreateChatCompletionRequestMessage[] = []; diff --git a/src/handlers/comment/handlers/index.ts b/src/handlers/comment/handlers/index.ts index 47bf8eccb..87cb03717 100644 --- a/src/handlers/comment/handlers/index.ts +++ b/src/handlers/comment/handlers/index.ts @@ -288,7 +288,7 @@ export const userCommands = (): UserCommands[] => { }, { id: IssueCommentCommands.ASK, - description: `Ask a technical question to the UbiquiBot. \n example usage: "/ask How do I do X?"`, + description: `Ask a technical question to UbiquiBot. \n example usage: "/ask How do I do X?"`, handler: ask, callback: commandCallback, }, From 5003f80d60b58a78f063664c75c68eb8623e0370 Mon Sep 17 00:00:00 2001 From: whilefoo Date: Tue, 26 Sep 2023 11:02:06 +0200 Subject: [PATCH 7/7] feat: rename --- supabase/migrations/20230926105600_debit_rename.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 supabase/migrations/20230926105600_debit_rename.sql diff --git a/supabase/migrations/20230926105600_debit_rename.sql b/supabase/migrations/20230926105600_debit_rename.sql new file mode 100644 index 000000000..efcd40c75 --- /dev/null +++ b/supabase/migrations/20230926105600_debit_rename.sql @@ -0,0 +1 @@ +ALTER TABLE Debits RENAME TO debits; \ No newline at end of file