Skip to content
This repository has been archived by the owner on Sep 19, 2024. It is now read-only.

Commit

Permalink
Merge branch 'development' into start-disclaimer
Browse files Browse the repository at this point in the history
  • Loading branch information
Keyrxng authored Sep 5, 2023
2 parents 2855d0b + 3eaedcc commit 03a78ac
Show file tree
Hide file tree
Showing 36 changed files with 489 additions and 171 deletions.
14 changes: 10 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ SUPABASE_KEY=
AUTO_PAY_MODE=
ANALYTICS_MODE=

# Log environment
LOG_ENVIRONMENT=production # development to see logs in console
LOG_LEVEL=debug # 0: error 1: warn 2: info 3: http 4: verbose 5: debug 6: silly
LOG_RETRY=0 # 0 for no retry, more than 0 for the number of retries
# Use `trace` to get verbose logging or `info` to show less
LOG_LEVEL=debug
LOGDNA_INGESTION_KEY=
OPENAI_API_HOST=https://api.openai.com
OPENAI_API_KEY=
CHATGPT_USER_PROMPT_FOR_IMPORTANT_WORDS="I need your help to find important words (e.g. unique adjectives) from github issue below and I want to parse them easily so please separate them using #(No other contexts needed). Please separate the words by # so I can parse them easily. Please answer simply as I only need the important words. Here is the issue content.\n"
CHATGPT_USER_PROMPT_FOR_MEASURE_SIMILARITY='I have two github issues and I need to measure the possibility of the 2 issues are the same content (No other contents needed and give me only the number in %).\n Give me in number format and add % after the number.\nDo not tell other things since I only need the number (e.g. 85%). Here are two issues:\n 1. "%first%"\n2. "%second%"'
SIMILARITY_THRESHOLD=80
MEASURE_SIMILARITY_AI_TEMPERATURE=0
IMPORTANT_WORDS_AI_TEMPERATURE=0
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1 +1 @@

* @0xcodercrane
48 changes: 1 addition & 47 deletions .github/ubiquibot-config.yml
Original file line number Diff line number Diff line change
@@ -1,50 +1,4 @@
evm-network-id: 100
price-multiplier: 1.5
issue-creator-multiplier: 2
time-labels:
- name: "Time: <1 Hour"
weight: 0.125
value: 3600
- name: "Time: <2 Hours"
weight: 0.25
value: 7200
- name: "Time: <4 Hours"
weight: 0.5
value: 14400
- name: "Time: <1 Day"
weight: 1
value: 86400
- name: "Time: <1 Week"
weight: 2
value: 604800
priority-labels:
- name: "Priority: 0 (Normal)"
weight: 1
- name: "Priority: 1 (Medium)"
weight: 2
- name: "Priority: 2 (High)"
weight: 3
- name: "Priority: 3 (Urgent)"
weight: 4
- name: "Priority: 4 (Emergency)"
weight: 5
default-labels:
- "Time: <1 Hour"
- "Priority: 0 (Normal)"
payment-permit-max-price: 1000
comment-incentives: true
max-concurrent-bounties: 2
promotion-comment: "<h6>If you've enjoyed your experience in the DevPool, we'd appreciate your support. Follow <a href='https://github.com/ubiquity'>Ubiquity on GitHub</a> and star <a href='https://github.com/ubiquity/devpool-directory'>this repo</a>. Your endorsement means the world to us and helps us grow!</h6><h6>We are excited to announce that the DevPool and UbiquiBot are now available to partners! Our ideal collaborators are globally distributed crypto-native organizations, who actively work on open source on GitHub, and excel in research & development. If you can introduce us to the repository maintainers in these types of companies, we have a special bonus in store for you!</h6>"
incentives:
comment:
elements:
code: 5
img: 5
h1: 1
li: 0.5
a: 0.5
blockquote: 0
totals:
word: 0.1
register-wallet-with-verification: false
assistive-pricing: true
- "Priority: 1 (Normal)"
2 changes: 1 addition & 1 deletion .github/workflows/bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,4 @@ jobs:
X25519_PRIVATE_KEY: 'QCDb30UHUkwJAGhLWC-R2N0PiEbd4vQY6qH2Wloybyo'
FOLLOW_UP_TIME: '4 days'
DISQUALIFY_TIME: '7 days'
run: yarn start:serverless
run: yarn start:serverless
35 changes: 33 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ yarn start:watch
- `LOGDNA_INGESTION_KEY`: Get it from [Memzo](https://app.mezmo.com/) by creating an account, adding an organization, and copying the ingestion key on the next screen.
- `FOLLOWUP_TIME`: (optional) Set a custom follow-up time (default: 4 days).
- `DISQUALIFY_TIME`: (optional) Set a custom disqualify time (default: 7 days).
- `OPENAI_API_HOST`: (optional) Set OpenAI host url (default: https://api.openai.com).
- `OPENAI_API_KEY`: Set OpenAI key.
- `CHATGPT_USER_PROMPT_FOR_IMPORTANT_WORDS`: (optional) Set a custom user prompt for finding important words
(default: "I need your help to find important words (e.g. unique adjectives) from github issue below and I want to parse them easily so please separate them using #(No other contexts needed). Please separate the words by # so I can parse them easily. Please answer simply as I only need the important words. Here is the issue content.\n").
- `CHATGPT_USER_PROMPT_FOR_MEASURE_SIMILARITY`: (optional) Set a custom user prompt for measuring similarity
(default: 'I have two github issues and I need to measure the possibility of the 2 issues are the same content (No other contents needed and give me only the number in %).\n Give me in number format and add % after the number.\nDo not tell other things since I only need the number (e.g. 85%). Here are two issues:\n 1. "%first%"\n2. "%second%"').
- `SIMILARITY_THRESHOLD`: (optional) Set similarity threshold (default: 80).
- `MEASURE_SIMILARITY_AI_TEMPERATURE`: (optional) Set ChatGPT temperature for measuring similarity (default: 0).
- `IMPORTANT_WORDS_AI_TEMPERATURE`: (optional) Set ChatGPT temperature for finding important words (default: 0).

`APP_ID` and `PRIVATE_KEY` are [here](https://t.me/c/1588400061/1627) for internal developers to use.
If you are an external developer, `APP_ID`and `PRIVATE_KEY` are automatically generated when you install the app on your repository.
Expand Down Expand Up @@ -57,13 +66,11 @@ To test the bot, you can:
`time-labels` are labels for marking the time limit of the bounty:

- `name` is a human-readable name
- `weight` is a number that will be used to calculate the bounty price
- `value` is number of seconds that corresponds to the time limit of the bounty

`priority-labels` are labels for marking the priority of the bounty:

- `name` is a human-readable name
- `weight` is a number that will be used to calculate the bounty price

`command-settings` are setting to enable or disable a command

Expand Down Expand Up @@ -232,3 +239,27 @@ We can't use a `jsonc` file due to limitations with Netlify. Here is a snippet o
}
}
```

## Supabase Cron Job (`logs-cleaner`)

##### Dashboard > Project > Database > Extensions

> Search `PG_CRON` and Enable it.

##### Dashboard > Project > SQL Editor

```sql
-- Runs everyday at 03:00 AM to cleanup logs that are older than a week
-- Use the cron time format to modify the trigger time if necessary
select
cron.schedule (
'logs-cleaner', -- Job name
'0 3 * * *', -- Everyday at 03:00 AM
$$DELETE FROM logs WHERE timestamp < now() - INTERVAL '1 week'$$
);


-- Cancel the cron job
select cron.unschedule('logs-cleaner');
```
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"decimal.js": "^10.4.3",
"copyfiles": "^2.4.1",
"ethers": "^5.7.2",
"exponential-backoff": "^3.1.1",
"husky": "^8.0.2",
"jimp": "^0.22.4",
"js-yaml": "^4.1.0",
Expand Down
133 changes: 99 additions & 34 deletions src/adapters/supabase/helpers/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,45 @@ export const getMaxIssueNumber = async (): Promise<number> => {
/**
* @dev Gets the last weekly update timestamp
*/
export const getLastWeeklyTime = async (): Promise<number> => {
export const getLastWeeklyTime = async (): Promise<Date | undefined> => {
const { supabase } = getAdapters();

const { data } = await supabase.from("weekly").select("last_time").limit(1).single();
if (data) {
return Number(data.last_time);
return new Date(data.last_time);
} else {
return 0;
return undefined;
}
};

/**
* @dev Updates the last weekly update timestamp
*/
export const updateLastWeeklyTime = async (time: number): Promise<void> => {
export const updateLastWeeklyTime = async (time: Date): Promise<void> => {
const logger = getLogger();
const { supabase } = getAdapters();
const { data, error } = await supabase.from("weekly").update({ last_time: time });
logger.info(`Updating last time is done, data: ${data}, error: ${error}`);

const { data, error } = await supabase.from("weekly").select("last_time");
if (error) {
logger.error(`Checking last time failed, error: ${JSON.stringify(error)}`);
throw new Error(`Checking last time failed, error: ${JSON.stringify(error)}`);
}

if (data && data.length > 0) {
const { data, error } = await supabase.from("weekly").update({ last_time: time.toUTCString() }).neq("last_time", time.toUTCString());
if (error) {
logger.error(`Updating last time failed, error: ${JSON.stringify(error)}`);
throw new Error(`Updating last time failed, error: ${JSON.stringify(error)}`);
}
logger.info(`Updating last time is done, data: ${data}`);
} else {
const { data, error } = await supabase.from("weekly").insert({ last_time: time.toUTCString() });
if (error) {
logger.error(`Creating last time failed, error: ${JSON.stringify(error)}`);
throw new Error(`Creating last time failed, error: ${JSON.stringify(error)}`);
}
logger.info(`Creating last time is done, data: ${data}`);
}
return;
};

Expand Down Expand Up @@ -92,7 +112,7 @@ const getDbDataFromUserProfile = (userProfile: UserProfile, additions?: UserProf
return {
user_login: userProfile.login,
user_type: userProfile.type,
user_name: userProfile.name,
user_name: userProfile.name ?? userProfile.login,
company: userProfile.company,
blog: userProfile.blog,
user_location: userProfile.location,
Expand All @@ -114,18 +134,30 @@ const getDbDataFromUserProfile = (userProfile: UserProfile, additions?: UserProf
export const upsertIssue = async (issue: Issue, additions: IssueAdditions): Promise<void> => {
const logger = getLogger();
const { supabase } = getAdapters();
const { data, error } = await supabase.from("issues").select("id").eq("issue_number", issue.number).single();
const { data, error } = await supabase.from("issues").select("id").eq("issue_number", issue.number);
if (error) {
logger.error(`Checking issue failed, error: ${JSON.stringify(error)}`);
throw new Error(`Checking issue failed, error: ${JSON.stringify(error)}`);
}

if (data) {
const key = data.id as number;
await supabase
if (data && data.length > 0) {
const key = data[0].id as number;
const { data: _data, error: _error } = await supabase
.from("issues")
.upsert({ id: key, ...getDbDataFromIssue(issue, additions) })
.select();
logger.info(`Upserting an issue done, data: ${data}, error: ${error}`);
} else if (error) {
if (_error) {
logger.error(`Upserting an issue failed, error: ${JSON.stringify(_error)}`);
throw new Error(`Upserting an issue failed, error: ${JSON.stringify(_error)}`);
}
logger.info(`Upserting an issue done, { data: ${_data}, error: ${_error}`);
} else {
const { data: _data, error: _error } = await supabase.from("issues").insert(getDbDataFromIssue(issue, additions));
logger.info(`Creating a new issue done, { data: ${_data}, error: ${_error}`);
if (_error) {
logger.error(`Creating a new issue record failed, error: ${JSON.stringify(_error)}`);
throw new Error(`Creating a new issue record failed, error: ${JSON.stringify(_error)}`);
}
logger.info(`Creating a new issue record done, { data: ${_data}, error: ${_error}`);
}
};

Expand All @@ -136,18 +168,26 @@ export const upsertIssue = async (issue: Issue, additions: IssueAdditions): Prom
export const upsertUser = async (user: UserProfile): Promise<void> => {
const logger = getLogger();
const { supabase } = getAdapters();
const { data, error } = await supabase.from("users").select("id").eq("user_login", user.login).single();
const { data, error } = await supabase.from("users").select("user_login").eq("user_login", user.login);
if (error) {
logger.error(`Checking user failed, error: ${JSON.stringify(error)}`);
throw new Error(`Checking user failed, error: ${JSON.stringify(error)}`);
}

if (data) {
const key = data.id as number;
await supabase
.from("users")
.upsert({ id: key, ...getDbDataFromUserProfile(user) })
.select();
logger.info(`Upserting an user done", { data: ${data}, error: ${error} }`);
} else if (error) {
if (data && data.length > 0) {
const { data: _data, error: _error } = await supabase.from("users").upsert(getDbDataFromUserProfile(user)).select();
if (_error) {
logger.error(`Upserting a user failed, error: ${JSON.stringify(_error)}`);
throw new Error(`Upserting a user failed, error: ${JSON.stringify(_error)}`);
}
logger.info(`Upserting a user done, { data: ${JSON.stringify(_data)} }`);
} else {
const { data: _data, error: _error } = await supabase.from("users").insert(getDbDataFromUserProfile(user));
logger.info(`Creating a new user done", { data: ${_data}, error: ${_error} }`);
if (_error) {
logger.error(`Creating a new user record failed, error: ${JSON.stringify(_error)}`);
throw new Error(`Creating a new user record failed, error: ${JSON.stringify(_error)}`);
}
logger.info(`Creating a new user record done, { data: ${JSON.stringify(_data)} }`);
}
};

Expand Down Expand Up @@ -201,15 +241,24 @@ export const upsertWalletMultiplier = async (username: string, multiplier: strin
const logger = getLogger();
const { supabase } = getAdapters();

const { data, error } = await supabase.from("multiplier").select("user_id").eq("user_id", `${username}_${org_id}`).single();
if (data) {
await supabase.from("multiplier").upsert({
const { data, error } = await supabase.from("multiplier").select("user_id").eq("user_id", `${username}_${org_id}`);
if (error) {
logger.error(`Checking wallet multiplier failed, error: ${JSON.stringify(error)}`);
throw new Error(`Checking wallet multiplier failed, error: ${JSON.stringify(error)}`);
}

if (data && data.length > 0) {
const { data: _data, error: _error } = await supabase.from("multiplier").upsert({
user_id: `${username}_${org_id}`,
value: multiplier,
reason,
updated_at: new Date().toUTCString(),
});
logger.info(`Upserting a wallet address done, { data: ${data}, error: ${error} }`);
if (_error) {
logger.error(`Upserting a wallet multiplier failed, error: ${JSON.stringify(_error)}`);
throw new Error(`Upserting a wallet multiplier failed, error: ${JSON.stringify(_error)}`);
}
logger.info(`Upserting a wallet multiplier done, { data: ${JSON.stringify(_data)} }`);
} else {
const { data: _data, error: _error } = await supabase.from("multiplier").insert({
user_id: `${username}_${org_id}`,
Expand All @@ -218,7 +267,11 @@ export const upsertWalletMultiplier = async (username: string, multiplier: strin
created_at: new Date().toUTCString(),
updated_at: new Date().toUTCString(),
});
logger.info(`Creating a new multiplier_table record done, { data: ${_data}, error: ${_error} }`);
if (_error) {
logger.error(`Creating a new multiplier record failed, error: ${JSON.stringify(_error)}`);
throw new Error(`Creating a new multiplier record failed, error: ${JSON.stringify(_error)}`);
}
logger.info(`Creating a new multiplier record done, { data: ${JSON.stringify(_data)} }`);
}
};

Expand All @@ -233,7 +286,11 @@ export const upsertAccessControl = async (username: string, repository: string,
const logger = getLogger();
const { supabase } = getAdapters();

const { data, error } = await supabase.from("access").select("user_name").eq("user_name", username).eq("repository", repository).single();
const { data, error } = await supabase.from("access").select("user_name").eq("user_name", username).eq("repository", repository);
if (error) {
logger.error(`Checking access control failed, error: ${JSON.stringify(error)}`);
throw new Error(`Checking access control failed, error: ${JSON.stringify(error)}`);
}

const properties = {
user_name: username,
Expand All @@ -242,9 +299,13 @@ export const upsertAccessControl = async (username: string, repository: string,
[access]: bool,
};

if (data) {
await supabase.from("access").upsert(properties);
logger.info(`Upserting an access done, { data: ${data}, error: ${error} }`);
if (data && data.length > 0) {
const { data: _data, error: _error } = await supabase.from("access").upsert(properties);
if (_error) {
logger.error(`Upserting a access control failed, error: ${JSON.stringify(_error)}`);
throw new Error(`Upserting a access control failed, error: ${JSON.stringify(_error)}`);
}
logger.info(`Upserting a access control done, { data: ${JSON.stringify(_data)} }`);
} else {
const { data: _data, error: _error } = await supabase.from("access").insert({
created_at: new Date().toUTCString(),
Expand All @@ -254,7 +315,11 @@ export const upsertAccessControl = async (username: string, repository: string,
priority_access: false,
...properties,
});
logger.info(`Creating a new access record done, { data: ${_data}, error: ${_error} }`);
if (_error) {
logger.error(`Creating a new access control record failed, error: ${JSON.stringify(_error)}`);
throw new Error(`Creating a new access control record failed, error: ${JSON.stringify(_error)}`);
}
logger.info(`Creating a new access control record done, { data: ${JSON.stringify(_data)} }`);
}
};

Expand Down
Loading

0 comments on commit 03a78ac

Please sign in to comment.