diff --git a/github/definitions/IGithubActivity.ts b/github/definitions/IGithubActivity.ts new file mode 100644 index 0000000..d578a3e --- /dev/null +++ b/github/definitions/IGithubActivity.ts @@ -0,0 +1,23 @@ +import { IGitHubIssue } from "./githubIssue" +import { IGithubComment } from "./IGithubComment"; +import { IGitHubPullRequest } from "./IGithubPullRequest"; + +export interface IGithubActivity { + type: "IssuesEvent" | "PullRequestEvent" | "IssueCommentEvent"; + actor: { + display_login: string; + avatar_url: string; + url: string; + }; + repo: { + name: string; + url: string; + }; + payload: { + action: string; + comment?: IGithubComment + issue?: IGitHubIssue + pull_request?: IGitHubPullRequest + }; + created_at: string; +} diff --git a/github/definitions/IGithubComment.ts b/github/definitions/IGithubComment.ts new file mode 100644 index 0000000..36c3e4c --- /dev/null +++ b/github/definitions/IGithubComment.ts @@ -0,0 +1,5 @@ +export interface IGithubComment { + body: string; + url: string; + lastUpdatedAt: string; +} diff --git a/github/definitions/IGithubPullRequest.ts b/github/definitions/IGithubPullRequest.ts new file mode 100644 index 0000000..f72e25e --- /dev/null +++ b/github/definitions/IGithubPullRequest.ts @@ -0,0 +1,14 @@ +export interface IGitHubPullRequest{ + id: string|number, + title?: string, + html_url?: string, + number?: string|number + labels?: Array, + user_login?:string, + user_avatar?:string, + last_updated_at?: string, + comments?:string|number, + state?: string, + assignees?: Array,//user ids seperated by " " + body?: string, +} diff --git a/github/enum/Subcommands.ts b/github/enum/Subcommands.ts index 8ba32e2..8f3ee28 100644 --- a/github/enum/Subcommands.ts +++ b/github/enum/Subcommands.ts @@ -8,5 +8,6 @@ export enum SubcommandEnum { SEARCH = 'search', NEW_ISSUE = 'issue', ISSUES = 'issues', - PROFILE = 'me' + PROFILE = 'me', + ACTIVITY = 'activity', } diff --git a/github/helpers/ParseGithubActivity.ts b/github/helpers/ParseGithubActivity.ts new file mode 100644 index 0000000..9bb2e5d --- /dev/null +++ b/github/helpers/ParseGithubActivity.ts @@ -0,0 +1,75 @@ +import { IGithubActivity } from "../definitions/IGithubActivity"; + +export function parseUserActivity(event: any): IGithubActivity { + let payload: any = {}; + if (event.type === "IssuesEvent") { + payload = { + action: event.payload.action, + issue: { + issue_id: event.payload.issue.id, + title: event.payload.issue.title, + html_url: event.payload.issue.html_url, + number: event.payload.issue.number, + labels: event.payload.issue.labels.map((label: any) => label.name), + user_login: event.payload.issue.user.login, + user_avatar: event.payload.issue.user.avatar_url, + last_updated_at: event.payload.issue.updated_at, + comments: event.payload.issue.comments, + state: event.payload.issue.state, + assignees: event.payload.issue.assignees.map( + (assignee: any) => assignee.login + ), + repo_url: event.repo.url, + body: event.payload.issue.body, + }, + }; + } else if (event.type === "PullRequestEvent") { + payload = { + action: event.payload.action, + pull_request: { + id: event.payload.pull_request.id, + title: event.payload.pull_request.title, + html_url: event.payload.pull_request.html_url, + number: event.payload.pull_request.number, + labels: event.payload.pull_request.labels.map( + (label: any) => label.name + ), + user_login: event.payload.pull_request.user.login, + user_avatar: event.payload.pull_request.user.avatar_url, + last_updated_at: event.payload.pull_request.updated_at, + comments: event.payload.pull_request.comments, + state: event.payload.pull_request.state, + assignees: event.payload.pull_request.assignees.map( + (assignee: any) => assignee.login + ), + body: event.payload.pull_request.body, + }, + }; + } else if (event.type === "IssueCommentEvent") { + payload = { + action: event.payload.action, + comment: { + body: event.payload.comment.body, + url: event.payload.comment.html_url, + lastUpdatedAt: event.payload.comment.updated_at, + }, + }; + } + + const userActivity: IGithubActivity = { + type: event.type, + actor: { + display_login: event.actor.display_login, + avatar_url: event.actor.avatar_url, + url: event.actor.url, + }, + repo: { + name: event.repo.name, + url: event.repo.url, + }, + payload: payload, + created_at: event.created_at, + }; + + return userActivity; +} diff --git a/github/helpers/githubSDK.ts b/github/helpers/githubSDK.ts index 8aab870..31c29ee 100644 --- a/github/helpers/githubSDK.ts +++ b/github/helpers/githubSDK.ts @@ -1,6 +1,8 @@ import { IHttp } from "@rocket.chat/apps-engine/definition/accessors"; import { IGitHubIssue } from "../definitions/githubIssue"; +import { IGithubActivity } from "../definitions/IGithubActivity"; import { ModalsEnum } from "../enum/Modals"; +import { parseUserActivity } from "./ParseGithubActivity"; const BaseHost = "https://github.com/"; const BaseApiHost = "https://api.github.com/"; @@ -726,3 +728,31 @@ export async function updateGithubIssues( } return repsonseJSON; } + +export async function getUserActivity ( + http: IHttp, + username: String, + access_token : String, + page: number, + till_last : "WEEK" | "MONTH", + per_page?: number, +) : Promise { + per_page = per_page ?? 15; + + const oneWeekAgo = new Date(new Date().getTime() - 7 * 24 * 60 * 60 * 1000); + + // A request need to be made to get the raw data from GitHub Events + const rawFetched = await getRequest(http, access_token, `https://api.github.com/users/${username}/events?per_page=${per_page}?page=${page}`) as any + + // the data needs to be processed to get the last week or month's data + const lastWeekEvents = rawFetched.filter((event: any) => + ['PullRequestEvent', 'IssueCommentEvent', 'IssuesEvent'].includes(event.type) && + new Date(event.created_at) >= oneWeekAgo + ); + + const userActivity: IGithubActivity[] = lastWeekEvents.map((event: any) : IGithubActivity => { + return parseUserActivity(event) + }) + + return userActivity +} diff --git a/github/lib/commandUtility.ts b/github/lib/commandUtility.ts index d2fb1c3..ff195e4 100644 --- a/github/lib/commandUtility.ts +++ b/github/lib/commandUtility.ts @@ -23,6 +23,9 @@ import { import { handleSearch } from "../handlers/SearchHandler"; import { handleNewIssue } from "../handlers/HandleNewIssue"; import { handleUserProfileRequest } from "../handlers/UserProfileHandler"; +import { BlockElementType } from "@rocket.chat/apps-engine/definition/uikit"; +import { getUserActivity } from "../helpers/githubSDK"; +import { getAccessTokenForUser } from "../persistance/auth"; export class CommandUtility implements ExecutorProps { sender: IUser; @@ -138,6 +141,26 @@ export class CommandUtility implements ExecutorProps { ); break; } + case SubcommandEnum.ACTIVITY: { + let access_token = await getAccessTokenForUser( + this.read, + this.context.getSender(), + this.app.oauth2Config + ); + + if (access_token != undefined && access_token.token != undefined) { + const triggerID = this.context.getTriggerId() as string; + const block = await this.getDummyBlock(access_token.token) + const user = this.context.getSender(); + await this.modify.getUiController().openContextualBarView( + block, + { triggerId: triggerID }, + user + ); + } + + break; + } default: { await helperMessage({ room: this.room, @@ -257,4 +280,33 @@ export class CommandUtility implements ExecutorProps { } } } + + public async getDummyBlock(accessToken: string) { + const blocks = this.modify.getCreator().getBlockBuilder(); + + const date = new Date().toISOString(); + + const data = await getUserActivity(this.http, "henit-chobisa", accessToken, 1, "WEEK", 5); + + data.forEach((activity) => { + blocks.addSectionBlock({ + text: blocks.newMarkdownTextObject(activity.repo.name), // [4] + accessory: { // [5] + type: BlockElementType.BUTTON, + actionId: 'repositoryList', + text: blocks.newPlainTextObject('Refresh'), + value: date, + }, + }); + }) + + return { // [6] + id: 'contextualbarId', + title: blocks.newPlainTextObject('Contextual Bar'), + submit: blocks.newButtonElement({ + text: blocks.newPlainTextObject('Submit'), + }), + blocks: blocks.getBlocks(), + }; + } }