@@ -139,6 +139,33 @@ function formatPollData(poll) {
139139 return pollMarkdown ;
140140}
141141
142+ function formatReactions ( reactionGroups ) {
143+ if ( ! reactionGroups || reactionGroups . length === 0 ) {
144+ return '' ;
145+ }
146+
147+ const reactionMap = {
148+ 'THUMBS_UP' : '👍' ,
149+ 'THUMBS_DOWN' : '👎' ,
150+ 'LAUGH' : '😄' ,
151+ 'HOORAY' : '🎉' ,
152+ 'CONFUSED' : '😕' ,
153+ 'HEART' : '❤️' ,
154+ 'ROCKET' : '🚀' ,
155+ 'EYES' : '👀'
156+ } ;
157+
158+ const formattedReactions = reactionGroups
159+ . filter ( group => group . users . totalCount > 0 )
160+ . map ( group => {
161+ const emoji = reactionMap [ group . content ] || group . content ;
162+ return `${ emoji } ${ group . users . totalCount } ` ;
163+ } )
164+ . join ( ' | ' ) ;
165+
166+ return formattedReactions ? `\n\n**Reactions:** ${ formattedReactions } ` : '' ;
167+ }
168+
142169// GraphQL Queries and Mutations
143170const CHECK_DISCUSSIONS_ENABLED_QUERY = `
144171 query($owner: String!, $repo: String!) {
@@ -229,6 +256,19 @@ const FETCH_DISCUSSIONS_QUERY = `
229256 }
230257 }
231258 }
259+ reactionGroups {
260+ content
261+ users {
262+ totalCount
263+ }
264+ }
265+ }
266+ }
267+ pinnedDiscussions(first: 100) {
268+ nodes {
269+ discussion {
270+ id
271+ }
232272 }
233273 }
234274 }
@@ -248,6 +288,12 @@ const FETCH_DISCUSSION_COMMENTS_QUERY = `
248288 }
249289 createdAt
250290 upvoteCount
291+ reactionGroups {
292+ content
293+ users {
294+ totalCount
295+ }
296+ }
251297 replies(first: 50) {
252298 nodes {
253299 id
@@ -257,6 +303,12 @@ const FETCH_DISCUSSION_COMMENTS_QUERY = `
257303 }
258304 createdAt
259305 upvoteCount
306+ reactionGroups {
307+ content
308+ users {
309+ totalCount
310+ }
311+ }
260312 }
261313 }
262314 }
@@ -362,6 +414,18 @@ const CLOSE_DISCUSSION_MUTATION = `
362414 }
363415` ;
364416
417+ const LOCK_DISCUSSION_MUTATION = `
418+ mutation($discussionId: ID!) {
419+ lockLockable(input: {
420+ lockableId: $discussionId
421+ }) {
422+ lockedRecord {
423+ locked
424+ }
425+ }
426+ }
427+ ` ;
428+
365429const MARK_DISCUSSION_COMMENT_AS_ANSWER_MUTATION = `
366430 mutation($commentId: ID!) {
367431 markDiscussionCommentAsAnswer(input: {
@@ -552,17 +616,28 @@ async function addLabelsToDiscussion(octokit, discussionId, labelIds) {
552616 }
553617}
554618
555- async function createDiscussion ( octokit , repositoryId , categoryId , title , body , sourceUrl , sourceAuthor , sourceCreated , poll = null ) {
619+ async function createDiscussion ( octokit , repositoryId , categoryId , title , body , sourceUrl , sourceAuthor , sourceCreated , poll = null , locked = false , isPinned = false , reactionGroups = [ ] ) {
556620 let enhancedBody = body ;
557621
622+ // Add pinned indicator if discussion was pinned
623+ if ( isPinned ) {
624+ enhancedBody = `📌 _This discussion was pinned in the source repository_\n\n${ enhancedBody } ` ;
625+ }
626+
627+ // Add reactions if present
628+ const reactionsMarkdown = formatReactions ( reactionGroups ) ;
629+ if ( reactionsMarkdown ) {
630+ enhancedBody += reactionsMarkdown ;
631+ }
632+
558633 // Add poll data if present
559634 if ( poll ) {
560635 const pollMarkdown = formatPollData ( poll ) ;
561636 enhancedBody += pollMarkdown ;
562637 }
563638
564639 // Add metadata
565- enhancedBody += `\n\n---\n<details>\n<summary><i>Original discussion metadata</i></summary>\n\n_Original discussion by @${ sourceAuthor } on ${ sourceCreated } _\n_Source: ${ sourceUrl } _\n</details>` ;
640+ enhancedBody += `\n\n---\n<details>\n<summary><i>Original discussion metadata</i></summary>\n\n_Original discussion by @${ sourceAuthor } on ${ sourceCreated } _\n_Source: ${ sourceUrl } _\n${ locked ? '\n_🔒 This discussion was locked in the source repository_' : '' } \n </details>` ;
566641
567642 log ( `Creating discussion: '${ title } '` ) ;
568643
@@ -576,13 +651,35 @@ async function createDiscussion(octokit, repositoryId, categoryId, title, body,
576651 body : enhancedBody
577652 } ) ;
578653
579- return response . createDiscussion . discussion ;
654+ const newDiscussion = response . createDiscussion . discussion ;
655+
656+ // Lock the discussion if it was locked in the source
657+ if ( locked ) {
658+ await lockDiscussion ( octokit , newDiscussion . id ) ;
659+ }
660+
661+ return newDiscussion ;
580662 } catch ( err ) {
581663 error ( `Failed to create discussion: ${ err . message } ` ) ;
582664 throw err ;
583665 }
584666}
585667
668+ async function lockDiscussion ( octokit , discussionId ) {
669+ log ( `Locking discussion ${ discussionId } ...` ) ;
670+
671+ await rateLimitSleep ( 2 ) ;
672+
673+ try {
674+ await octokit . graphql ( LOCK_DISCUSSION_MUTATION , {
675+ discussionId
676+ } ) ;
677+ log ( `Discussion locked successfully` ) ;
678+ } catch ( err ) {
679+ error ( `Failed to lock discussion: ${ err . message } ` ) ;
680+ }
681+ }
682+
586683async function fetchDiscussionComments ( octokit , discussionId ) {
587684 log ( `Fetching comments for discussion ${ discussionId } ...` ) ;
588685
@@ -600,8 +697,16 @@ async function fetchDiscussionComments(octokit, discussionId) {
600697 }
601698}
602699
603- async function addDiscussionComment ( octokit , discussionId , body , originalAuthor , originalCreated ) {
604- const enhancedBody = `${ body } \n\n---\n<details>\n<summary><i>Original comment metadata</i></summary>\n\n_Original comment by @${ originalAuthor } on ${ originalCreated } _\n</details>` ;
700+ async function addDiscussionComment ( octokit , discussionId , body , originalAuthor , originalCreated , reactionGroups = [ ] ) {
701+ let enhancedBody = body ;
702+
703+ // Add reactions if present
704+ const reactionsMarkdown = formatReactions ( reactionGroups ) ;
705+ if ( reactionsMarkdown ) {
706+ enhancedBody += reactionsMarkdown ;
707+ }
708+
709+ enhancedBody += `\n\n---\n<details>\n<summary><i>Original comment metadata</i></summary>\n\n_Original comment by @${ originalAuthor } on ${ originalCreated } _\n</details>` ;
605710
606711 log ( "Adding comment to discussion" ) ;
607712
@@ -622,8 +727,16 @@ async function addDiscussionComment(octokit, discussionId, body, originalAuthor,
622727 }
623728}
624729
625- async function addDiscussionCommentReply ( octokit , discussionId , replyToId , body , originalAuthor , originalCreated ) {
626- const enhancedBody = `${ body } \n\n---\n_Original reply by @${ originalAuthor } on ${ originalCreated } _` ;
730+ async function addDiscussionCommentReply ( octokit , discussionId , replyToId , body , originalAuthor , originalCreated , reactionGroups = [ ] ) {
731+ let enhancedBody = body ;
732+
733+ // Add reactions if present
734+ const reactionsMarkdown = formatReactions ( reactionGroups ) ;
735+ if ( reactionsMarkdown ) {
736+ enhancedBody += reactionsMarkdown ;
737+ }
738+
739+ enhancedBody += `\n\n---\n_Original reply by @${ originalAuthor } on ${ originalCreated } _` ;
627740
628741 log ( `Adding reply to comment ${ replyToId } ` ) ;
629742
@@ -707,7 +820,8 @@ async function copyDiscussionComments(octokit, discussionId, comments, answerCom
707820 discussionId ,
708821 comment . body ,
709822 author ,
710- createdAt
823+ createdAt ,
824+ comment . reactionGroups || [ ]
711825 ) ;
712826
713827 if ( newCommentId ) {
@@ -735,7 +849,8 @@ async function copyDiscussionComments(octokit, discussionId, comments, answerCom
735849 newCommentId ,
736850 reply . body ,
737851 replyAuthor ,
738- replyCreated
852+ replyCreated ,
853+ reply . reactionGroups || [ ]
739854 ) ;
740855 }
741856 }
@@ -800,16 +915,29 @@ async function processDiscussionsPage(sourceOctokit, targetOctokit, owner, repo,
800915 discussion . url ,
801916 discussion . author ?. login || "unknown" ,
802917 discussion . createdAt ,
803- discussion . poll || null
918+ discussion . poll || null ,
919+ discussion . locked || false ,
920+ discussion . isPinned || false ,
921+ discussion . reactionGroups || [ ]
804922 ) ;
805923
806924 createdDiscussions ++ ;
807925 log ( `✓ Created discussion #${ discussion . number } : '${ discussion . title } '` ) ;
808926
809- // Log poll info if present
927+ // Log additional metadata info
810928 if ( discussion . poll && discussion . poll . options ?. nodes ?. length > 0 ) {
811929 log ( ` ℹ️ Poll included with ${ discussion . poll . options . nodes . length } options (${ discussion . poll . totalVoteCount } total votes)` ) ;
812930 }
931+ if ( discussion . locked ) {
932+ log ( ` 🔒 Discussion was locked in source and has been locked in target` ) ;
933+ }
934+ if ( discussion . isPinned ) {
935+ log ( ` 📌 Discussion was pinned in source (indicator added to body)` ) ;
936+ }
937+ const totalReactions = discussion . reactionGroups ?. reduce ( ( sum , group ) => sum + ( group . users . totalCount || 0 ) , 0 ) || 0 ;
938+ if ( totalReactions > 0 ) {
939+ log ( ` ❤️ ${ totalReactions } reaction${ totalReactions !== 1 ? 's' : '' } copied` ) ;
940+ }
813941
814942 // Process labels
815943 if ( discussion . labels . nodes . length > 0 ) {
0 commit comments