1- import { WebhookClient , type MessageCreateOptions } from "discord.js"
1+ import { type MessageCreateOptions , WebhookClient } from "discord.js"
2+ import { EXCLUDED_BOTS } from "lib/constants"
23import { getRepos } from "lib/data-retrieval/getRepos"
34import { octokit } from "lib/sdks"
4- import { EXCLUDED_BOTS } from "lib/constants"
55
66const discordWebhook = new WebhookClient ( {
77 url : process . env . ISSUES_DISCORD_WEBHOOK_URL || "" ,
@@ -11,6 +11,13 @@ interface Issue {
1111 number : number
1212 title : string
1313 html_url : string
14+ body ?: string | null
15+ labels : Array <
16+ | string
17+ | {
18+ name ?: string
19+ }
20+ >
1421 user : {
1522 login : string
1623 }
@@ -21,6 +28,53 @@ function getUTCDateTime(): string {
2128 return new Date ( ) . toISOString ( )
2229}
2330
31+ function getLabelNames ( issue : Issue ) : string [ ] {
32+ return issue . labels
33+ . map ( ( label ) => ( typeof label === "string" ? label : label . name ) )
34+ . filter ( ( label ) : label is string => Boolean ( label ) )
35+ }
36+
37+ function findBountyAmount ( text : string ) : string | null {
38+ const bountyMatch = text . match (
39+ / (?: \/ b o u n t y | b o u n t y ) \s * \$ \s * ( [ \d , ] + (?: \. \d { 1 , 2 } ) ? ) / i,
40+ )
41+ if ( bountyMatch ) return `$${ bountyMatch [ 1 ] } `
42+
43+ const dollarMatch = text . match ( / \$ \s * ( [ \d , ] + (?: \. \d { 1 , 2 } ) ? ) / )
44+ if ( dollarMatch ) return `$${ dollarMatch [ 1 ] } `
45+
46+ return null
47+ }
48+
49+ async function getIssueBounty (
50+ repo : string ,
51+ issue : Issue ,
52+ ) : Promise < string | null > {
53+ const labelBounty = getLabelNames ( issue )
54+ . filter ( ( label ) => ! label . toLowerCase ( ) . includes ( "rewarded" ) )
55+ . map ( findBountyAmount )
56+ . find ( ( amount ) => amount )
57+
58+ if ( labelBounty ) return labelBounty
59+
60+ const bodyBounty = findBountyAmount ( issue . body ?? "" )
61+ if ( bodyBounty ) return bodyBounty
62+
63+ const [ owner , repoName ] = repo . split ( "/" )
64+ const { data : comments } = await octokit . issues . listComments ( {
65+ owner,
66+ repo : repoName ,
67+ issue_number : issue . number ,
68+ per_page : 20 ,
69+ } )
70+
71+ return (
72+ comments
73+ . map ( ( comment ) => findBountyAmount ( comment . body ?? "" ) )
74+ . find ( ( amount ) => amount ) ?? null
75+ )
76+ }
77+
2478async function getRecentIssues ( repo : string ) : Promise < Issue [ ] > {
2579 const [ owner , repoName ] = repo . split ( "/" )
2680 const sixtyMinutesAgo = new Date ( Date . now ( ) - 60 * 60 * 1000 ) . toISOString ( )
@@ -61,14 +115,15 @@ async function notifyDiscord(issues: Issue[], repo: string) {
61115 `[${ getUTCDateTime ( ) } ] Sending notification for ${ issues . length } issues from ${ repo } to Discord` ,
62116 )
63117
64- const messageContent =
65- `New issues in ${ repo } :\n` +
66- issues
67- . map (
68- ( issue ) =>
69- `• #${ issue . number } ${ issue . title } by ${ issue . user . login } - <${ issue . html_url } >` ,
70- )
71- . join ( "\n" )
118+ const issueLines = await Promise . all (
119+ issues . map ( async ( issue ) => {
120+ const bounty = await getIssueBounty ( repo , issue )
121+ const bountyText = bounty ? ` [bounty: ${ bounty } ]` : ""
122+ return `• #${ issue . number } ${ issue . title } ${ bountyText } by ${ issue . user . login } - <${ issue . html_url } >`
123+ } ) ,
124+ )
125+
126+ const messageContent = `New issues in ${ repo } :\n${ issueLines . join ( "\n" ) } `
72127
73128 const messageOptions : MessageCreateOptions = {
74129 content : messageContent ,
0 commit comments