Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/development' into september-up…
Browse files Browse the repository at this point in the history
…date-adjustment
  • Loading branch information
whilefoo committed Oct 3, 2023
2 parents 5003f80 + 9d00d7f commit 326b471
Show file tree
Hide file tree
Showing 23 changed files with 493 additions and 229 deletions.
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ CHATGPT_USER_PROMPT_FOR_MEASURE_SIMILARITY='I have two github issues and I need
SIMILARITY_THRESHOLD=80
MEASURE_SIMILARITY_AI_TEMPERATURE=0
IMPORTANT_WORDS_AI_TEMPERATURE=0

# Telegram Log Notification Envs
LOG_WEBHOOK_BOT_URL= # URL of cloudflare worker without trailing /
LOG_WEBHOOK_SECRET= # Random Secret, Shared between the telegram bot and the sender
LOG_WEBHOOK_GROUP_ID= # Group Id, ex: -100124234325
LOG_WEBHOOK_TOPIC_ID= # Topic Id (Optional), Only provide if group is a topic and you're not using General
4 changes: 2 additions & 2 deletions .github/ubiquibot-config.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
priceMultiplier: 1.5
price-multiplier: 1.5
# newContributorGreeting:
# enabled: true
# header: "Thank you for contributing to UbiquiBot! Please be sure to set your wallet address before completing your first bounty so that the automatic payout upon task completion will work for you."
# helpMenu: true
# footer: "###### Also please star this repository and [@ubiquity/devpool-directory](https://github.com/ubiquity/devpool-directory/) to show your support. It helps a lot!"
# footer: "###### Also please star this repository and [@ubiquity/devpool-directory](https://github.com/ubiquity/devpool-directory/) to show your support. It helps a lot!"
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"husky": "^8.0.2",
"jimp": "^0.22.4",
"js-yaml": "^4.1.0",
"jsonwebtoken": "^9.0.2",
"libsodium-wrappers": "^0.7.11",
"lint-staged": "^13.1.0",
"lodash": "^4.17.21",
Expand Down
83 changes: 80 additions & 3 deletions src/adapters/supabase/helpers/log.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import axios from "axios";
import { getAdapters, getBotContext, Logger } from "../../../bindings";
import { Payload, LogLevel } from "../../../types";
import { Payload, LogLevel, LogNotification } from "../../../types";
import { getOrgAndRepoFromPath } from "../../../utils/private";

import jwt from "jsonwebtoken";
interface Log {
repo: string | null;
org: string | null;
Expand Down Expand Up @@ -43,13 +44,15 @@ export class GitHubLogger implements Logger {
private retryDelay = 1000; // Delay between retries in milliseconds
private throttleCount = 0;
private retryLimit = 0; // Retries disabled by default
private logNotification;

constructor(app: string, logEnvironment: string, maxLevel: LogLevel, retryLimit: number) {
constructor(app: string, logEnvironment: string, maxLevel: LogLevel, retryLimit: number, logNotification: LogNotification) {
this.app = app;
this.logEnvironment = logEnvironment;
this.maxLevel = getNumericLevel(maxLevel);
this.retryLimit = retryLimit;
this.supabase = getAdapters().supabase;
this.logNotification = logNotification;
}

async sendLogsToSupabase({ repo, org, commentId, issueNumber, logMessage, level, timestamp }: Log) {
Expand Down Expand Up @@ -80,6 +83,66 @@ export class GitHubLogger implements Logger {
}
}

private sendDataWithJwt(message: string | object, errorPayload?: string | object) {
const context = getBotContext();
const payload = context.payload as Payload;

const { comment, issue, repository } = payload;
const commentId = comment?.id;
const issueNumber = issue?.number;
const repoFullName = repository?.full_name;

const { org, repo } = getOrgAndRepoFromPath(repoFullName);

const issueLink = `https://github.com/${org}/${repo}/issues/${issueNumber}${commentId ? `#issuecomment-${commentId}` : ""}`;

return new Promise((resolve, reject) => {
try {
if (!this.logNotification?.enabled) {
reject("Telegram Log Notification is disabled, please check that url, secret and group is provided");
}

if (typeof message === "object") {
message = JSON.stringify(message);
}

if (errorPayload && typeof errorPayload === "object") {
errorPayload = JSON.stringify(errorPayload);
}

const errorMessage = `\`${message}${errorPayload ? " - " + errorPayload : ""}\`\n\nContext: ${issueLink}`;

// Step 1: Sign a JWT with the provided parameter
const jwtToken = jwt.sign(
{
group: this.logNotification.groupId,
topic: this.logNotification.topicId,
msg: errorMessage,
},
this.logNotification.secret,
{ noTimestamp: true }
);

const apiUrl = `${this.logNotification.url}/sendLogs`;
const headers = {
Authorization: `${jwtToken}`,
};

axios
.get(apiUrl, { headers })
.then((response) => {
resolve(response.data);
})
.catch((error) => {
reject(error);
});
} catch (error) {
// Reject the promise with the error
reject(error);
}
});
}

async retryLog(log: Log, retryCount = 0) {
if (retryCount >= this.retryLimit) {
console.error("Max retry limit reached for log:", log);
Expand Down Expand Up @@ -169,6 +232,13 @@ export class GitHubLogger implements Logger {

warn(message: string | object, errorPayload?: string | object) {
this.save(message, LogLevel.WARN, errorPayload);
this.sendDataWithJwt(message, errorPayload)
.then((response) => {
this.save(`Log Notification Success: ${response}`, LogLevel.DEBUG, "");
})
.catch((error) => {
this.save(`Log Notification Error: ${error}`, LogLevel.DEBUG, "");
});
}

debug(message: string | object, errorPayload?: string | object) {
Expand All @@ -177,6 +247,13 @@ export class GitHubLogger implements Logger {

error(message: string | object, errorPayload?: string | object) {
this.save(message, LogLevel.ERROR, errorPayload);
this.sendDataWithJwt(message, errorPayload)
.then((response) => {
this.save(`Log Notification Success: ${response}`, LogLevel.DEBUG, "");
})
.catch((error) => {
this.save(`Log Notification Error: ${error}`, LogLevel.DEBUG, "");
});
}

async get() {
Expand Down
39 changes: 23 additions & 16 deletions src/bindings/config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import ms from "ms";

import { BotConfig, BotConfigSchema, LogLevel } from "../types";
import {
DEFAULT_BOT_DELAY,
DEFAULT_DISQUALIFY_TIME,
DEFAULT_FOLLOWUP_TIME,
DEFAULT_PERMIT_BASE_URL,
DEFAULT_TIME_RANGE_FOR_MAX_ISSUE,
DEFAULT_TIME_RANGE_FOR_MAX_ISSUE_ENABLED,
} from "../configs";
import { getPayoutConfigByNetworkId } from "../helpers";
import { ajv } from "../utils";
import { Context } from "probot";
Expand Down Expand Up @@ -37,6 +29,12 @@ export const loadConfig = async (context: Context): Promise<BotConfig> => {
openAIKey,
openAITokenLimit,
newContributorGreeting,
timeRangeForMaxIssueEnabled,
timeRangeForMaxIssue,
permitBaseUrl,
botDelay,
followUpTime,
disqualifyTime,
} = await getWideConfig(context);

const publicKey = await getScalarKey(process.env.X25519_PRIVATE_KEY);
Expand Down Expand Up @@ -64,25 +62,30 @@ export const loadConfig = async (context: Context): Promise<BotConfig> => {
rpc: rpc,
privateKey: privateKey,
paymentToken: paymentToken,
permitBaseUrl: process.env.PERMIT_BASE_URL || DEFAULT_PERMIT_BASE_URL,
permitBaseUrl: process.env.PERMIT_BASE_URL || permitBaseUrl,
},
unassign: {
timeRangeForMaxIssue: process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE
? Number(process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE)
: DEFAULT_TIME_RANGE_FOR_MAX_ISSUE,
timeRangeForMaxIssue: process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE ? Number(process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE) : timeRangeForMaxIssue,
timeRangeForMaxIssueEnabled: process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE_ENABLED
? process.env.DEFAULT_TIME_RANGE_FOR_MAX_ISSUE_ENABLED == "true"
: DEFAULT_TIME_RANGE_FOR_MAX_ISSUE_ENABLED,
followUpTime: ms(process.env.FOLLOW_UP_TIME || DEFAULT_FOLLOWUP_TIME),
disqualifyTime: ms(process.env.DISQUALIFY_TIME || DEFAULT_DISQUALIFY_TIME),
: timeRangeForMaxIssueEnabled,
followUpTime: ms(process.env.FOLLOW_UP_TIME || followUpTime),
disqualifyTime: ms(process.env.DISQUALIFY_TIME || disqualifyTime),
},
supabase: {
url: process.env.SUPABASE_URL ?? "",
key: process.env.SUPABASE_KEY ?? "",
},
telegram: {
token: process.env.TELEGRAM_BOT_TOKEN ?? "",
delay: process.env.TELEGRAM_BOT_DELAY ? Number(process.env.TELEGRAM_BOT_DELAY) : DEFAULT_BOT_DELAY,
delay: process.env.TELEGRAM_BOT_DELAY ? Number(process.env.TELEGRAM_BOT_DELAY) : botDelay,
},
logNotification: {
url: process.env.LOG_WEBHOOK_BOT_URL || "",
secret: process.env.LOG_WEBHOOK_SECRET || "",
groupId: Number(process.env.LOG_WEBHOOK_GROUP_ID) || 0,
topicId: Number(process.env.LOG_WEBHOOK_TOPIC_ID) || 0,
enabled: true,
},
mode: {
paymentPermitMaxPrice: paymentPermitMaxPrice,
Expand Down Expand Up @@ -114,6 +117,10 @@ export const loadConfig = async (context: Context): Promise<BotConfig> => {
botConfig.mode.paymentPermitMaxPrice = 0;
}

if (botConfig.logNotification.secret == "" || botConfig.logNotification.groupId == 0 || botConfig.logNotification.url == "") {
botConfig.logNotification.enabled = false;
}

const validate = ajv.compile(BotConfigSchema);
const valid = validate(botConfig);
if (!valid) {
Expand Down
3 changes: 2 additions & 1 deletion src/bindings/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ export const bindEvents = async (context: Context): Promise<void> => {
options.app,
botConfig?.log?.logEnvironment ?? "development",
botConfig?.log?.level ?? LogLevel.DEBUG,
botConfig?.log?.retryLimit ?? 0
botConfig?.log?.retryLimit ?? 0,
botConfig.logNotification
); // contributors will see logs in console while on development env
if (!logger) {
return;
Expand Down
1 change: 0 additions & 1 deletion src/configs/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from "./shared";
export * from "./strings";
export * from "./abis";
export * from "./ubiquibot-config-default";
31 changes: 0 additions & 31 deletions src/configs/shared.ts

This file was deleted.

6 changes: 6 additions & 0 deletions src/configs/ubiquibot-config-default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ export const DefaultConfig: MergedConfig = {
organization: true,
},
staleBountyTime: "0d",
timeRangeForMaxIssue: 24, //24
timeRangeForMaxIssueEnabled: false,
permitBaseUrl: "https://pay.ubq.fi",
botDelay: 100, // 100ms
followUpTime: "4 days",
disqualifyTime: "7 days",
newContributorGreeting: {
enabled: true,
header:
Expand Down
5 changes: 3 additions & 2 deletions src/handlers/comment/handlers/assign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { deadLinePrefix } from "../../shared";
import { getWalletAddress, getWalletMultiplier } from "../../../adapters/supabase";
import { tableComment } from "./table";
import { bountyInfo } from "../../wildcard";
import { ASSIGN_COMMAND_ENABLED, GLOBAL_STRINGS } from "../../../configs";
import { GLOBAL_STRINGS } from "../../../configs";
import { isParentIssue } from "../../pricing";

export const assign = async (body: string) => {
Expand All @@ -19,6 +19,7 @@ export const assign = async (body: string) => {
const id = organization?.id || repository?.id; // repository?.id as fallback

const staleBounty = config.assign.staleBountyTime;
const startEnabled = config.command.find((command) => command.name === "start");

logger.info(`Received '/start' command from user: ${payload.sender.login}, body: ${body}`);
const issue = (_payload as Payload).issue;
Expand All @@ -28,7 +29,7 @@ export const assign = async (body: string) => {
return "Skipping '/start' because of no issue instance";
}

if (!ASSIGN_COMMAND_ENABLED) {
if (!startEnabled?.enabled) {
logger.info(`Ignore '/start' command from user: ASSIGN_COMMAND_ENABLED config is set false`);
return GLOBAL_STRINGS.assignCommandDisabledComment;
}
Expand Down
9 changes: 5 additions & 4 deletions src/handlers/comment/handlers/help.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { userCommands } from ".";
import { getBotContext, getLogger } from "../../../bindings";
import { ASSIGN_COMMAND_ENABLED } from "../../../configs";
import { getBotConfig, getBotContext, getLogger } from "../../../bindings";
import { IssueType, Payload } from "../../../types";
import { IssueCommentCommands } from "../commands";

Expand Down Expand Up @@ -28,13 +27,15 @@ export const listAvailableCommands = async (body: string) => {
};

export const generateHelpMenu = () => {
const config = getBotConfig();
const startEnabled = config.command.find((command) => command.name === "start");
let helpMenu = "### Available commands\n```";
const commands = userCommands();
commands.map((command) => {
// if first command, add a new line
if (command.id === commands[0].id) {
helpMenu += `\n`;
if (!ASSIGN_COMMAND_ENABLED) return;
if (!startEnabled) return;
}
helpMenu += `- ${command.id}: ${command.description}`;
// if not last command, add a new line (fixes too much space below)
Expand All @@ -43,6 +44,6 @@ export const generateHelpMenu = () => {
}
});

if (!ASSIGN_COMMAND_ENABLED) helpMenu += "```\n***_To assign yourself to an issue, please open a draft pull request that is linked to it._***";
if (!startEnabled) helpMenu += "```\n***_To assign yourself to an issue, please open a draft pull request that is linked to it._***";
return helpMenu;
};
5 changes: 3 additions & 2 deletions src/handlers/comment/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,15 @@ export * from "./authorize";
export interface RewardsResponse {
error: string | null;
title?: string;
userId?: string;
userId?: number;
username?: string;
reward?: {
account: string;
priceInEth: Decimal;
penaltyAmount: BigNumber;
user: string;
userId: string;
userId: number;
debug: Record<string, { count: number; reward: Decimal }>;
}[];
fallbackReward?: Record<string, Decimal>;
}
Expand Down
Loading

0 comments on commit 326b471

Please sign in to comment.