diff --git a/integrations/github/package.json b/integrations/github/package.json index e500406..af86172 100644 --- a/integrations/github/package.json +++ b/integrations/github/package.json @@ -1,6 +1,6 @@ { "name": "@core/github", - "version": "0.1.0", + "version": "0.1.1", "description": "github extension for CORE", "main": "./bin/index.js", "module": "./bin/index.mjs", diff --git a/integrations/github/pnpm-lock.yaml b/integrations/github/pnpm-lock.yaml index 17f1db0..cda6f35 100644 --- a/integrations/github/pnpm-lock.yaml +++ b/integrations/github/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@redplanethq/sdk': - specifier: 0.1.1 - version: 0.1.1 + specifier: 0.1.2 + version: 0.1.2 axios: specifier: ^1.7.9 version: 1.11.0 @@ -466,8 +466,8 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@redplanethq/sdk@0.1.1': - resolution: {integrity: sha512-tfR1c9p7vNeCL5jsF9QlEZcRFLsihaHe/ZQWVKZYXzAZ6GugoIFBaayGfVvjNjyEnN3nlrl3usKBX+hhaKzg0g==} + '@redplanethq/sdk@0.1.2': + resolution: {integrity: sha512-Si+ae2OV0UNy7yvLECjJ1Y/6HHhRO0yU9svIFvBzMlaR/57SDP+KJZLyfWx/PJX+hOuWipyoYTLA9aYULt6z2w==} engines: {node: '>=18.0.0'} '@rollup/rollup-android-arm-eabi@4.46.2': @@ -2455,7 +2455,7 @@ snapshots: '@pkgr/core@0.2.9': {} - '@redplanethq/sdk@0.1.1': + '@redplanethq/sdk@0.1.2': dependencies: commander: 14.0.0 diff --git a/integrations/github/src/schedule.ts b/integrations/github/src/schedule.ts index 65199aa..43b0cda 100644 --- a/integrations/github/src/schedule.ts +++ b/integrations/github/src/schedule.ts @@ -46,7 +46,7 @@ async function fetchUserInfo(accessToken: string) { /** * Processes GitHub notifications into activity messages */ -async function processNotifications(accessToken: string, lastSyncTime: string): Promise { +async function processNotifications(accessToken: string, lastSyncTime: string, username: string): Promise { const activities = []; const allowedReasons = [ 'assign', @@ -117,35 +117,36 @@ async function processNotifications(accessToken: string, lastSyncTime: string): switch (notification.reason) { case 'assign': - title = `${isIssue ? 'Issue' : 'PR'} assigned to you: #${githubData.number} - ${githubData.title}`; + title = `${isIssue ? 'Issue' : 'PR'} #${githubData.number} assigned to ${username} in ${repository.full_name}: ${githubData.title}`; break; case 'author': if (isComment) { - title = `New comment on your ${isIssue ? 'issue' : 'PR'} by ${githubData.user?.login}: ${githubData.body}`; + title = `${githubData.user?.login} commented on ${username}'s ${isIssue ? 'issue' : 'PR'} #${githubData.number} in ${repository.full_name}: ${githubData.body}`; } else { - title = `You created this ${isIssue ? 'issue' : 'PR'}: #${githubData.number} - ${githubData.title}`; + title = `${username} created ${isIssue ? 'issue' : 'PR'} #${githubData.number} in ${repository.full_name}: ${githubData.title}`; } break; case 'comment': - title = `New comment by ${githubData.user?.login} in ${repository.full_name}: ${githubData.body}`; + title = `${githubData.user?.login} commented on ${isIssue ? 'issue' : 'PR'} #${githubData.number} in ${repository.full_name}: ${githubData.body}`; break; case 'manual': - title = `You subscribed to: #${githubData.number} - ${githubData.title}`; + title = `${username} subscribed to ${isIssue ? 'issue' : 'PR'} #${githubData.number} in ${repository.full_name}: ${githubData.title}`; break; case 'mention': - title = `@mentioned by ${githubData.user?.login} in ${repository.full_name}: ${githubData.body}`; + title = `${githubData.user?.login} mentioned ${username} in ${repository.full_name} ${isIssue ? 'issue' : 'PR'} #${githubData.number}: ${githubData.body}`; break; case 'review_requested': - title = `PR review requested in ${repository.full_name}: #${githubData.number} - ${githubData.title}`; + title = `${username} requested to review PR #${githubData.number} in ${repository.full_name}: ${githubData.title}`; break; case 'state_change': { let stateInfo = ''; + let actor = githubData.user?.login || 'someone'; if (githubData.state) { stateInfo = `to ${githubData.state}`; } else if (githubData.merged) { @@ -153,28 +154,28 @@ async function processNotifications(accessToken: string, lastSyncTime: string): } else if (githubData.closed_at) { stateInfo = 'to closed'; } - title = `State changed ${stateInfo} in ${repository.full_name}: #${githubData.number} - ${githubData.title}`; + title = `${actor} changed ${isIssue ? 'issue' : 'PR'} #${githubData.number} state ${stateInfo} in ${repository.full_name}: ${githubData.title}`; break; } case 'subscribed': if (isComment) { - title = `New comment on watched ${isIssue ? 'issue' : 'PR'} in ${repository.full_name} by ${githubData.user?.login}: ${githubData.body}`; + title = `${githubData.user?.login} commented on watched ${isIssue ? 'issue' : 'PR'} #${githubData.number} in ${repository.full_name}: ${githubData.body}`; } else if (isPullRequest) { - title = `New PR created in watched repo ${repository.full_name}: #${githubData.number} - ${githubData.title}`; + title = `New PR #${githubData.number} created in watched repo ${repository.full_name}: ${githubData.title}`; } else if (isIssue) { - title = `New issue created in watched repo ${repository.full_name}: #${githubData.number} - ${githubData.title}`; + title = `New issue #${githubData.number} created in watched repo ${repository.full_name}: ${githubData.title}`; } else { - title = `Update in watched repo ${repository.full_name}: #${githubData.number} - ${githubData.title}`; + title = `Update on watched ${isIssue ? 'issue' : 'PR'} #${githubData.number} in ${repository.full_name}: ${githubData.title}`; } break; case 'team_mention': - title = `Your team was mentioned in ${repository.full_name}`; + title = `${username}'s team mentioned in ${repository.full_name} ${isIssue ? 'issue' : 'PR'} #${githubData.number}: ${githubData.title}`; break; default: - title = `GitHub notification: ${repository.full_name}`; + title = `GitHub notification for ${username} in ${repository.full_name}`; break; } @@ -236,19 +237,19 @@ async function processUserEvents( switch (event.type) { case 'pr': - title = `You created PR #${event.number}: ${event.title}`; + title = `${username} created PR #${event.number}: ${event.title}`; break; case 'issue': - title = `You created issue #${event.number}: ${event.title}`; + title = `${username} created issue #${event.number}: ${event.title}`; break; case 'pr_comment': - title = `You commented on PR #${event.number}: ${event.title}`; + title = `${username} commented on PR #${event.number}: ${event.title}`; break; case 'issue_comment': - title = `You commented on issue #${event.number}: ${event.title}`; + title = `${username} commented on issue #${event.number}: ${event.title}`; break; case 'self_assigned_issue': - title = `You assigned yourself to issue #${event.number}: ${event.title}`; + title = `${username} assigned themselves to issue #${event.number}: ${event.title}`; break; default: title = `GitHub activity: ${event.title || 'Unknown'}`; @@ -319,6 +320,7 @@ export async function handleSchedule(config: any, state: any) { const notificationActivities = await processNotifications( integrationConfiguration.access_token, lastSyncTime, + settings.username || 'user', ); messages.push(...notificationActivities); } catch (error) { diff --git a/integrations/github/src/utils.ts b/integrations/github/src/utils.ts index e71bd2f..4de37cd 100644 --- a/integrations/github/src/utils.ts +++ b/integrations/github/src/utils.ts @@ -33,22 +33,22 @@ export async function getUserEvents( ] = await Promise.all([ // Search for PRs created by user getGithubData( - `https://api.github.com/search/issues?q=author:${username}+type:pr+created:>${formattedDate}&sort=created&order=desc&page=${page}&per_page=10`, + `https://api.github.com/search/issues?q=author:${username}+type:pr+created:>=${formattedDate}&sort=created&order=desc&page=${page}&per_page=10`, accessToken, ), // Search for issues created by user getGithubData( - `https://api.github.com/search/issues?q=author:${username}+type:issue+created:>${formattedDate}&sort=created&order=desc&page=${page}&per_page=10`, + `https://api.github.com/search/issues?q=author:${username}+type:issue+created:>=${formattedDate}&sort=created&order=desc&page=${page}&per_page=10`, accessToken, ), // Search for issues/PRs the user commented on getGithubData( - `https://api.github.com/search/issues?q=commenter:${username}+updated:>${formattedDate}&sort=updated&order=desc&page=${page}&per_page=10`, + `https://api.github.com/search/issues?q=commenter:${username}+updated:>=${formattedDate}&sort=updated&order=desc&page=${page}&per_page=10`, accessToken, ), // Search for issues assigned to the user and authored by the user (self-assigned) getGithubData( - `https://api.github.com/search/issues?q=assignee:${username}+author:${username}+type:issue+updated:>${formattedDate}&sort=updated&order=desc&page=${page}&per_page=10`, + `https://api.github.com/search/issues?q=assignee:${username}+author:${username}+type:issue+updated:>=${formattedDate}&sort=updated&order=desc&page=${page}&per_page=10`, accessToken, ), ]); @@ -58,17 +58,26 @@ export async function getUserEvents( console.log('Comments found:', commentsResponse?.items?.length || 0); console.log('Self-assigned issues found:', assignedIssuesResponse?.items?.length || 0); + // Filter function to exclude items older than the exact since timestamp + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const filterBySince = (item: any) => { + if (!since) return true; + const itemDate = new Date(item.created_at || item.updated_at); + const sinceDate = new Date(since); + return itemDate >= sinceDate; + }; + // Return simplified results - combine PRs, issues, commented items, and self-assigned issues const results = [ // eslint-disable-next-line @typescript-eslint/no-explicit-any - ...(prsResponse?.items || []).map((item: any) => ({ ...item, type: 'pr' })), + ...(prsResponse?.items || []).filter(filterBySince).map((item: any) => ({ ...item, type: 'pr' })), ...(issuesResponse?.items || []) // eslint-disable-next-line @typescript-eslint/no-explicit-any - .filter((item: any) => !item.pull_request) + .filter((item: any) => !item.pull_request && filterBySince(item)) // eslint-disable-next-line @typescript-eslint/no-explicit-any .map((item: any) => ({ ...item, type: 'issue' })), // eslint-disable-next-line @typescript-eslint/no-explicit-any - ...(commentsResponse?.items || []).map((item: any) => ({ + ...(commentsResponse?.items || []).filter(filterBySince).map((item: any) => ({ ...item, type: item.pull_request ? 'pr_comment' : 'issue_comment', })), @@ -76,9 +85,9 @@ export async function getUserEvents( ...(assignedIssuesResponse?.items || []) // eslint-disable-next-line @typescript-eslint/no-explicit-any .filter((item: any) => { - // Only include if not already in issuesResponse (by id) + // Only include if not already in issuesResponse (by id) and passes since filter // eslint-disable-next-line @typescript-eslint/no-explicit-any - return !(issuesResponse?.items || []).some((issue: any) => issue.id === item.id); + return !(issuesResponse?.items || []).some((issue: any) => issue.id === item.id) && filterBySince(item); }) // eslint-disable-next-line @typescript-eslint/no-explicit-any .map((item: any) => ({