diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 3d204b11..b9eac11b 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -1,4 +1,4 @@ -name: "the name of the plugin" +name: "contributor rewards" on: workflow_dispatch: @@ -18,7 +18,7 @@ on: jobs: compute: - name: "plugin name" + name: "contributor rewards" runs-on: ubuntu-latest permissions: write-all env: @@ -38,7 +38,7 @@ jobs: - name: execute directive run: npx tsx ./src/main.ts - id: plugin-name + id: contributor-rewards env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} diff --git a/manifest.json b/manifest.json index a6f2a101..d80f1521 100644 --- a/manifest.json +++ b/manifest.json @@ -2,12 +2,49 @@ "name": "ts-template", "description": "ts-template for UbiquityOS plugins.", "ubiquity:listeners": [ - "issue_comment.created" + "issue_comment.created", + "issue_comment.deleted", + "issue_comment.edited", + "pull_request.assigned", + "pull_request.auto_merge_disabled", + "pull_request.auto_merge_enabled", + "pull_request.closed", + "pull_request.converted_to_draft", + "pull_request.demilestoned", + "pull_request.dequeued", + "pull_request.edited", + "pull_request.enqueued", + "pull_request.labeled", + "pull_request.locked", + "pull_request.milestoned", + "pull_request.opened", + "pull_request.ready_for_review", + "pull_request.reopened", + "pull_request.review_request_removed", + "pull_request.review_requested", + "pull_request.synchronize", + "pull_request.unassigned", + "pull_request.unlabeled", + "pull_request.unlocked", + "pull_request_review", + "pull_request_review.dismissed", + "pull_request_review.edited", + "pull_request_review.submitted", + "pull_request_review_comment", + "pull_request_review_comment.created", + "pull_request_review_comment.deleted", + "pull_request_review_comment.edited", + "pull_request_review_thread", + "pull_request_review_thread.resolved", + "pull_request_review_thread.unresolved" ], "commands": { "command1": { "ubiquity:example": "/command1 argument", "description": "Command 1 with an argument." + }, + "rewards": { + "description": "Calculate rewards for contributors." } }, "configuration": { diff --git a/src/handlers/contrib-reward.ts b/src/handlers/contrib-reward.ts new file mode 100644 index 00000000..8bc18b5d --- /dev/null +++ b/src/handlers/contrib-reward.ts @@ -0,0 +1,55 @@ +import { Context } from "../types"; + +export async function contributorReward(context: Context) { + const { + logger, + payload, + octokit, + // config: { configurableResponse, }, + } = context; + const contributors: Record = {}; + + const sender = payload.comment.user?.login; + const repo = payload.repository.name; + const issueNumber = payload.issue.number; + const owner = payload.repository.owner.login; + + logger.info("Calculating rewards for contributor."); + logger.debug(`Executing contribReward:`, { sender, repo, issueNumber, owner }); + + try { + const events = await octokit.issues.listEventsForTimeline({ + owner, + repo, + issue_number: issueNumber, + }); + + events.data.forEach((event) => { + const contributor = event.actor?.login; + if (!contributors[contributor]) { + contributors[contributor] = 0; + } + contributors[contributor]++; + }); + + await octokit.issues.createComment({ + owner: payload.repository.owner.login, + repo: payload.repository.name, + issue_number: payload.issue.number, + body: JSON.stringify(contributors), + }); + + logger.info(`Contributors: ${JSON.stringify(contributors)}`); + } catch (error) { + if (error instanceof Error) { + logger.error(`Error calculating rewards:`, { error }); + throw error; + } else { + logger.error(`Error calculating rewards:`, { error: new Error(String(error)) }); + throw error; + } + } + + logger.ok(`Successfully created comment!`); + logger.verbose(`Exiting contribReward`); +} diff --git a/src/handlers/hello-world.ts b/src/handlers/hello-world.ts deleted file mode 100644 index f1f9d35c..00000000 --- a/src/handlers/hello-world.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Context } from "../types"; - -/** - * NOTICE: Remove this file or use it as a template for your own plugins. - * - * This encapsulates the logic for a plugin if the only thing it does is say "Hello, world!". - * - * Try it out by running your local kernel worker and running the `yarn worker` command. - * Comment on an issue in a repository where your GitHub App is installed and see the magic happen! - * - * Logger examples are provided to show how to log different types of data. - */ -export async function helloWorld(context: Context) { - const { - logger, - payload, - octokit, - config: { configurableResponse, customStringsUrl }, - } = context; - - const sender = payload.comment.user?.login; - const repo = payload.repository.name; - const issueNumber = payload.issue.number; - const owner = payload.repository.owner.login; - const body = payload.comment.body; - - if (!body.match(/hello/i)) { - logger.error(`Invalid use of slash command, use "/hello".`, { body }); - return; - } - - logger.info("Hello, world!"); - logger.debug(`Executing helloWorld:`, { sender, repo, issueNumber, owner }); - - try { - await octokit.issues.createComment({ - owner: payload.repository.owner.login, - repo: payload.repository.name, - issue_number: payload.issue.number, - body: configurableResponse, - }); - if (customStringsUrl) { - const response = await fetch(customStringsUrl).then((value) => value.json()); - await octokit.issues.createComment({ - owner: payload.repository.owner.login, - repo: payload.repository.name, - issue_number: payload.issue.number, - body: response.greeting, - }); - } - } catch (error) { - /** - * logger.fatal should not be used in 9/10 cases. Use logger.error instead. - * - * Below are examples of passing error objects to the logger, only one is needed. - */ - if (error instanceof Error) { - logger.error(`Error creating comment:`, { error: error, stack: error.stack }); - throw error; - } else { - logger.error(`Error creating comment:`, { err: error, error: new Error() }); - throw error; - } - } - - logger.ok(`Successfully created comment!`); - logger.verbose(`Exiting helloWorld`); -} diff --git a/src/plugin.ts b/src/plugin.ts index 01fc3118..dd58c9a7 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -3,7 +3,7 @@ import { returnDataToKernel } from "./helpers/validator"; import { Env, PluginInputs } from "./types"; import { Context } from "./types"; import { isIssueCommentEvent } from "./types/typeguards"; -import { helloWorld } from "./handlers/hello-world"; +import { contribReward } from "./handlers/contrib-reward"; import { LogLevel, Logs } from "@ubiquity-dao/ubiquibot-logger"; /** @@ -13,7 +13,7 @@ export async function runPlugin(context: Context) { const { logger, eventName } = context; if (isIssueCommentEvent(context)) { - return await helloWorld(context); + return await contribReward(context); } logger.error(`Unsupported event: ${eventName}`); diff --git a/src/types/context.ts b/src/types/context.ts index 0a59f93c..04938316 100644 --- a/src/types/context.ts +++ b/src/types/context.ts @@ -9,7 +9,42 @@ import { Logs } from "@ubiquity-dao/ubiquibot-logger"; * * ubiquity:listeners: ["issue_comment.created", ...] */ -export type SupportedEventsU = "issue_comment.created"; +export type SupportedEventsU = + | "issue_comment.created" + | "issue_comment.deleted" + | "issue_comment.edited" + | "pull_request.assigned" + | "pull_request.auto_merge_disabled" + | "pull_request.auto_merge_enabled" + | "pull_request.closed" + | "pull_request.converted_to_draft" + | "pull_request.demilestoned" + | "pull_request.dequeued" + | "pull_request.edited" + | "pull_request.enqueued" + | "pull_request.labeled" + | "pull_request.locked" + | "pull_request.milestoned" + | "pull_request.opened" + | "pull_request.ready_for_review" + | "pull_request.reopened" + | "pull_request.review_request_removed" + | "pull_request.review_requested" + | "pull_request.synchronize" + | "pull_request.unassigned" + | "pull_request.unlabeled" + | "pull_request.unlocked" + | "pull_request_review" + | "pull_request_review.dismissed" + | "pull_request_review.edited" + | "pull_request_review.submitted" + | "pull_request_review_comment" + | "pull_request_review_comment.created" + | "pull_request_review_comment.deleted" + | "pull_request_review_comment.edited" + | "pull_request_review_thread" + | "pull_request_review_thread.resolved" + | "pull_request_review_thread.unresolved"; export type SupportedEvents = { [K in SupportedEventsU]: K extends WebhookEventName ? WebhookEvent : never;