From 58116a07d50a985a4008c97818acfd91ce824a9c Mon Sep 17 00:00:00 2001 From: Chinmay Sa <68277286+ScreenTechnicals@users.noreply.github.com> Date: Wed, 25 Dec 2024 22:41:21 +0530 Subject: [PATCH] feat: add commands --- bun.lockb | Bin 418640 -> 418680 bytes src/handlers/app.handler.ts | 34 +++++++++- src/handlers/chat-commands.handler.ts | 86 ++++++++++++++++++++++++++ src/handlers/index.ts | 1 + 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 src/handlers/chat-commands.handler.ts diff --git a/bun.lockb b/bun.lockb index c5df9fd5e6e2b8fa9064a8e2f3db65016ffe1982..224c994186cc20329da6efca062e58e5a68fcd74 100755 GIT binary patch delta 4877 zcmXw*37n609>IiC_nqr$hFM$ ztn^4$dZDcJ!n@L=SBpj3hV_d_+a>iY90ZXd2of=ke&L+r(UNKXjhTYG@*P3&v{{tv zVrB!(61Yw>8yH?ziov)FfqsXTvulXMi*lW8mSLt9R5u$MrY4bMxLtRE>)18I>`t!l zH5+NBmHx?WRG6t0qwUgy>)AENtT@;8&BmJPCDP2E3y&+sI9z(?l2|*v4I|UxrO+MB zCYY6mrJGF*lS`0dl3itS)wCNhL`!*RHC#irF>KDXPIr zn9Vn<4$IZ%F&2cqlp=JBnxOr5Eiy}i9Wq<&6t!SyV9LBC+@=)E>{3nCbNF(nP)+=T z*2s38YT{S3m0_e5DRS((4_As^tIX=c>Y!DntIbl;-)Zw0Yr;-SvDU8pL09cs2a{B( zeP*`aaVoXlFctcSFk2}$+SLHG$F5CI(GXVIDYiJS5iHqkYj{&Bw%OGL*IjmPH+vBF zwQ7j5!%W3}KA!}^&aioDQoL$cQ}8vr;%3db{>JPzv*uj4Fxwr@QHniwwFLjguDviV zs1?@Q>~+T}rj6Mf;boct$*d>3zQZq@^@24t zyAmdqBgH3n{R>xhyFNAR4U3vxh4DY=gC&?<3wtTW=Wy*sUu>ab7+*4L(fzPz%)Vll z?2k1*^@uOJ=`Yh}L=De_zQv77sFi?)ee}+j8#~LEk^tWLu>JeCD$NeG9CPl0mTcZ~l zg;hYPV~d+Ti%x^WFAtOaxF0u~F#aj^v0 zlDUinpGPk>D{B^mErPXTE@w6#{RB+ST;41boeono-)%Mlt>Zk4lD< zxEhZ=g53inPmqPFy!8pFVm2AA^43U(Dd7}s42`JILRH62MGuE*R5N=4{Rm8-is~`L zX)L-%5C%B*8rf~oj=GdGWN z{#xNuOvNYIf>~@CrcUU?+|q10TAiTLidhL)VCn?LwRT)Kx+wZ7<~EL7iB2?o*epl& zr$1Nq*=YyVgI8gNVNWybjl@=CrC|EDbTC_kz5}Lj%cEv%(Z8{(!OZDq>(J+6Lzz3m zwCGo`6C~F2gU&!5&w6a6p2m30H*Y|9f@LyyGuw#Pu}s9en{7htSj2jmZANPcvarWt zdhixZN2j8FBFgjiysg+0R-meV(l>8IFVm_RJGx)n^LABWP z%=V%?Do*=97^qeM2W#w`hdA(cSQD7qFT?B&^fb0j?KjlyP4slLVP?6o2F^F!>@8Rg znA&dyET-*$8{3q?55`Cb?n9@Uje==``>`yv&Uv)s4xm-6YQHgN2hr*Tjj_zS_YkJf zvASxU;|}Zn@8n`7@Oi@{XeC_3{Qs}xJ7%ix@s4{JeSyrX?o6}y&>!$ds&0J|^>RnC zlV%gm-iLjd&)9!eqXLg%A30EODRvw?Z8jOEH#vb#fvH=j!c+?%V5$*~>Av?QIwzk5 z!3?txx$cXpGhP(a`Jck{K()q92Y!Uk;GEPMv&>GTyTQ~2v(3(+SHjc#9hzN2cZR9D7n)s0cQIRJ zb_LcHM#0B|mkmDwDxoTVvDv5SnQXNxeu>#tbVK5DnU|XV7yS^$x{rC8*=OjBoR{ik zx!EDU*SS#Z2xdF*bF@AfI>VJ_U!b)>9ZinemuA}XRc2qIGl|n!ZT2-f z3#MaOWA+U?O}{F&jx6Rr$kjyS4Pa_-r)Em||)vsyGIAwHv4bYnu~XuSS?(SwnA(bQ<~NTf@= z|DU663WYoCMN=Xx!ZY=v=aSUr>grRN8u@g%yMA;_(goyI>% EKM}MD`Tzg` delta 4842 zcmXw*37C%M8pq#{Z=6PTnX$`~$u^d*lCeY+A}KV+Y07X4SC&pl6S5q924mm1m#ky# zSyE|83L#WNwj7S7q*D$jsYW@c^ZWBZ&o#H_|Nid#y}##sp8I}$1$)aK+FNe=(~%w7 zX*p?;oU}qYX@xhZMK2bMq=fYoqHPj;7Y>3*5Crj!as~jW);x; z%_f^wgdH%O67E!rskn3^_hKK|HQnKrVNsnTV}|2&Lh)v^!o(7!m~B@TT*d5~>l9UC z#mz#qYOtLu7{Z3> zM{DFcPBrl#v*lr=Bq>(d^#HD9yH=V#2&;`&m98?Yi@vVSW2_F-m12!u^*|TxS__j@ zsa-N#=Qx$xR+tKXeVD5h8|-Qb+Gf{Ar)UJLs_-) zU{_Q_jLl{$?$ftO5WE*QFGY$ib~OcmXV+Gaf*4uY-f00DR$W<{G?qUo3-Y-t=Vof#k9kUV|&87rAe{Zt~Q`dOyd(X zz22FY(%5IF*IS$I53`lxfL&?0GTFM)%%7UIM|bjeerA>qdlsh7{yaRa6bJ44GpH8X z)!<*4J%dhy-NSsyECYSh?RYp$Dnp7RxU_Z8Ve4>JWJ%{v0CaK#ujN2p_qn+--M!kRIcFdKs2trr+2&4!})n3Xd78!QjjoVm2wF!XY>GPhYQ7!J$@ zKE_cOa}U=~)}tbyZZ!|K2~F*kJF9Q1=`jU6`^mQuu<-NY~i zR&&Bf%;v$eeA}d&&4;DIbQ3*l_6B+kx(jntvjyn3=&sDo%obXAV{RVhuyw|ZFja1M z<`xcIj8^4}wKQ9TPC)lye%x#+T3w{kidp$`F?EsRT03qT`VMqY<|iGOr(%mYY-6|_ zrk}dHirT?A?qCI081^#r(`GBtC1JX6(#%$&?}X{TX>Ya~{RgXhg*n}94f-@J_8OuC zP^(^x9nq&To`I1kcoTcw>^Z-@4weoZ#oW~68jb1SA*85m%vzHyW4c6AIx7i1 z(d`}B7p7Hzh&49r=eUnxO<-!jSIu^yCvqfezbvzz=t*X;neBo#biV$u82;d6tU6Hb zH^70r(d%h3je%x+(5Ysx!?eJ?SPok4H`sBXpjE7DzaeJ((CQA2q0D-Bzb;$d?pbyri!0nb_}iEQo&CY)A=9A zvej{pS9^WD;jjIiee;(=~bgO z@`qK8R*j2fEbX$B!{q$h$%g<~W4J*YLWZZr}lz$^5`p2H4l`Gu7#?Dp9 bFH|9}NF+X?;%%^HTw=wz{KSeydbRo==<5Lb diff --git a/src/handlers/app.handler.ts b/src/handlers/app.handler.ts index 3b179df..c05db84 100644 --- a/src/handlers/app.handler.ts +++ b/src/handlers/app.handler.ts @@ -2,7 +2,14 @@ import { Context, Probot } from 'probot'; import { envs } from '~common/consts'; import { Config } from '~common/types'; import { UserErrorListener } from '~events'; -import { ChatHandler, DiagramHandler, ReviewHandler, SummaryHandler, WalkthroughHandler } from '~handlers'; +import { + ChatCommandHandler, + ChatHandler, + DiagramHandler, + ReviewHandler, + SummaryHandler, + WalkthroughHandler +} from '~handlers'; import { systemLogger } from '~loggers'; import { AiService, AppService, CacheService, ConfigService, ErrorService, QueueService } from '~services'; import { ContributorHandler } from './contributor.handler'; @@ -37,6 +44,7 @@ export class AppHandler { pushHandler: PushHandler; diagramHandler: DiagramHandler; installationHandler: installationHandler; + chatCommandHandler: ChatCommandHandler; }; constructor() { @@ -78,6 +86,11 @@ export class AppHandler { this.services.queueService, this.services.cacheService ), + chatCommandHandler: new ChatCommandHandler( + this.services.appService, + this.services.queueService, + this.services.cacheService + ), contributorHandler: new ContributorHandler(this.services.cacheService, this.services.queueService), pushHandler: new PushHandler(this.services.cacheService, this.services.configService), installationHandler: new installationHandler(this.services.cacheService) @@ -134,6 +147,17 @@ export class AppHandler { }); } + private async handleCommandEvents(context: Context<'pull_request_review_comment' | 'pull_request'>): Promise { + await this.safeEventHandler(context, async (apiKey, config) => { + await this.handlers.contributorHandler.safeCacheContributors(context, apiKey); + const chatX = await this.handlers.chatCommandHandler.handle(context, apiKey, config); + + if (chatX.reviewTriggered) { + await this.handlers.reviewHandler.handle(context, apiKey, config); + } + }); + } + private async handleMemberEvents(context: Context<'member'>): Promise { await this.safeEventHandler(context, (apiKey) => this.handlers.contributorHandler.handle(context, apiKey)); } @@ -167,6 +191,14 @@ export class AppHandler { this.handleCommentEvents.bind(this) ); + app.on( + [ + 'pull_request_review_comment.created', + 'pull_request' + ], + this.handleCommandEvents.bind(this) + ); + app.on( [ 'member.added', diff --git a/src/handlers/chat-commands.handler.ts b/src/handlers/chat-commands.handler.ts new file mode 100644 index 0000000..f5a9b0d --- /dev/null +++ b/src/handlers/chat-commands.handler.ts @@ -0,0 +1,86 @@ +import { WebhookEventName } from '@octokit/webhooks-types'; +import { Context } from 'probot'; +import { Config } from '~common/types'; +import { SystemError } from '~errors'; +import { isInlineComment } from '~helpers'; +import { AppService, CacheService, GitHubService, QueueService } from '~services'; +import { ChatSkipConditions } from '~utils'; + +type CommentEvent = + | 'issue_comment' + | 'discussion_comment' + | 'pull_request_review_comment' + | 'discussion' + | 'issues' + | 'pull_request'; + +interface Handler { + handle( + context: Context, + apiKey: string, + config: Config + ): Promise<{ + reviewTriggered: boolean; + }>; +} + +export class ChatCommandHandler implements Handler { + constructor( + private readonly appService: AppService, + private readonly queueService: QueueService, + private readonly cacheService: CacheService + ) {} + + async handle( + context: Context, + apiKey: string, + config: Config + ): Promise<{ + reviewTriggered: boolean; + }> { + const shouldSkip = await new ChatSkipConditions( + context, + config, + this.appService, + this.cacheService, + this.queueService, + apiKey + ).shouldSkip(); + + if (shouldSkip) { + return { + reviewTriggered: false + }; + } + const contextBody = await this.getContextBody(context); + + if (contextBody?.includes('dr-github-pro review')) { + return { reviewTriggered: true }; + } + + return { + reviewTriggered: false + }; + } + + private async getContextBody(context: Context): Promise { + return this.queueService.schedule(async () => { + if (isInlineComment(context.payload) && context.payload.comment.in_reply_to_id) { + const reviewComment = await GitHubService.getReviewComment(context, context.payload.comment.in_reply_to_id); + + return reviewComment.data.body; + } + + if ('comment' in context.payload) { + return context.payload.comment.body; + } else if ('discussion' in context.payload) { + return context.payload.discussion.body; + } else { + if ('issue' in context.payload) { + return context.payload.issue.body; + } + throw new SystemError('Unhandled payload type'); + } + }); + } +} diff --git a/src/handlers/index.ts b/src/handlers/index.ts index e61bebd..6ca1549 100644 --- a/src/handlers/index.ts +++ b/src/handlers/index.ts @@ -1,4 +1,5 @@ export * from './app.handler'; +export * from './chat-commands.handler'; export * from './chat.handler'; export * from './contributor.handler'; export * from './diagram.handler';