-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add issue comment delete command #243
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| import * as readline from 'node:readline' | ||
| import { Command } from 'commander' | ||
| import { deleteIssueCommentByNodeId } from '../../lib/github' | ||
| import { getRepoInfo } from '../../lib/github-api' | ||
| import { detectSystemLanguage, getCommentMessages } from '../../lib/i18n' | ||
| import { toIssueCommentNodeId, validateCommentIdentifier } from '../../lib/id-converter' | ||
|
|
||
| /** | ||
| * Prompt user for confirmation | ||
| * @param prompt - The prompt message to display | ||
| * @returns Promise that resolves to true if user confirms, false otherwise | ||
| */ | ||
| async function confirm(prompt: string): Promise<boolean> { | ||
| const rl = readline.createInterface({ | ||
| input: process.stdin, | ||
| output: process.stdout, | ||
| }) | ||
|
|
||
| return new Promise((resolve) => { | ||
| rl.question(prompt, (answer) => { | ||
| rl.close() | ||
| resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') | ||
| }) | ||
| }) | ||
| } | ||
|
|
||
| /** | ||
| * Creates a command to delete issue comments | ||
| * @returns Command object configured for deleting issue comments | ||
| */ | ||
| export function createIssueCommentDeleteCommand(): Command { | ||
| const command = new Command('delete') | ||
|
|
||
| command | ||
| .description('Delete an issue comment') | ||
| .argument('<comment-id>', 'Database ID (number) or Node ID (IC_...) of the issue comment') | ||
| .option('-R, --repo <owner/repo>', 'Repository in owner/repo format') | ||
| .option('--issue <number>', 'Issue number (required when using Database ID)') | ||
| .option('-y, --yes', 'Skip confirmation prompt') | ||
| .action(async (commentIdStr: string, options: { repo?: string, issue?: string, yes?: boolean }) => { | ||
| const lang = detectSystemLanguage() | ||
| const msg = getCommentMessages(lang) | ||
|
|
||
| try { | ||
| // Validate comment identifier (Database ID or Node ID) | ||
| const commentIdentifier = validateCommentIdentifier(commentIdStr) | ||
|
|
||
| // Get repository info | ||
| const { owner, repo } = await getRepoInfo(options.repo) | ||
|
|
||
| // Convert comment identifier to Node ID | ||
| let commentNodeId: string | ||
|
|
||
| if (commentIdentifier.startsWith('IC_')) { | ||
| // Already a Node ID, use directly | ||
| commentNodeId = commentIdentifier | ||
| console.log(`✓ Node ID detected, using directly`) | ||
| } | ||
| else { | ||
| // Database ID - need issue number to convert | ||
| if (!options.issue) { | ||
| throw new Error( | ||
| 'Issue number is required when using Database ID. ' | ||
| + 'Use --issue <number> or provide Node ID instead.', | ||
| ) | ||
| } | ||
|
|
||
| const issueNumber = Number.parseInt(options.issue, 10) | ||
| if (Number.isNaN(issueNumber)) { | ||
| throw new TypeError('Invalid issue number') | ||
| } | ||
|
|
||
| console.log(`🔄 Converting Database ID to Node ID...`) | ||
| commentNodeId = await toIssueCommentNodeId( | ||
| commentIdentifier, | ||
| owner, | ||
| repo, | ||
| issueNumber, | ||
| ) | ||
| } | ||
|
|
||
| // Prompt for confirmation unless --yes flag is provided | ||
| if (!options.yes) { | ||
| const confirmed = await confirm(msg.confirmDelete) | ||
| if (!confirmed) { | ||
| console.log(msg.deleteAborted) | ||
| process.exit(0) | ||
| } | ||
| } | ||
|
|
||
| // Delete comment using GraphQL | ||
| console.log(msg.deletingComment(commentIdentifier)) | ||
| await deleteIssueCommentByNodeId(commentNodeId) | ||
|
|
||
| console.log(msg.commentDeleted) | ||
| } | ||
| catch (error) { | ||
| if (error instanceof Error) { | ||
| console.error(`${msg.errorPrefix}: ${error.message}`) | ||
| } | ||
| else { | ||
| console.error(msg.unknownError) | ||
| } | ||
| process.exit(1) | ||
| } | ||
| }) | ||
|
|
||
| return command | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -88,6 +88,11 @@ export interface CommentMessages { | |||||||||||||||||||||||||||
| fetchingComment: (commentId: number) => string | ||||||||||||||||||||||||||||
| updatingComment: (commentId: number) => string | ||||||||||||||||||||||||||||
| commentUpdated: string | ||||||||||||||||||||||||||||
| deletingComment: (commentId: number | string) => string | ||||||||||||||||||||||||||||
| commentDeleted: string | ||||||||||||||||||||||||||||
| confirmDelete: string | ||||||||||||||||||||||||||||
| deleteAborted: string | ||||||||||||||||||||||||||||
| usageDeleteIssue: string | ||||||||||||||||||||||||||||
|
Comment on lines
+91
to
+95
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To support full internationalization in the new
Suggested change
|
||||||||||||||||||||||||||||
| bodyRequired: string | ||||||||||||||||||||||||||||
| bodyEmpty: string | ||||||||||||||||||||||||||||
| usageIssue: string | ||||||||||||||||||||||||||||
|
|
@@ -299,6 +304,11 @@ export const commentMessages: Record<Language, CommentMessages> = { | |||||||||||||||||||||||||||
| fetchingComment: (commentId: number) => `🔍 댓글 ${commentId} 가져오는 중...`, | ||||||||||||||||||||||||||||
| updatingComment: (commentId: number) => `📝 댓글 ${commentId} 업데이트 중...`, | ||||||||||||||||||||||||||||
| commentUpdated: '✅ 댓글이 성공적으로 업데이트되었습니다!', | ||||||||||||||||||||||||||||
| deletingComment: (commentId: number | string) => `🗑️ 댓글 ${commentId} 삭제 중...`, | ||||||||||||||||||||||||||||
| commentDeleted: '✅ 댓글이 성공적으로 삭제되었습니다!', | ||||||||||||||||||||||||||||
| confirmDelete: '정말로 이 댓글을 삭제하시겠습니까? (y/N): ', | ||||||||||||||||||||||||||||
| deleteAborted: '삭제가 취소되었습니다.', | ||||||||||||||||||||||||||||
| usageDeleteIssue: ' 사용법: gh please issue comment delete <comment-id> [--yes]', | ||||||||||||||||||||||||||||
|
Comment on lines
+307
to
+311
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add the Korean translations for the new i18n keys to ensure a consistent experience for Korean-speaking users.
Suggested change
|
||||||||||||||||||||||||||||
| bodyRequired: '❌ 오류: --body 또는 --body-file이 필요합니다', | ||||||||||||||||||||||||||||
| bodyEmpty: '❌ 오류: 댓글 내용이 비어 있습니다', | ||||||||||||||||||||||||||||
| usageIssue: ' 사용법: gh please issue comment edit <comment-id> --body \'내용\'', | ||||||||||||||||||||||||||||
|
|
@@ -317,6 +327,11 @@ export const commentMessages: Record<Language, CommentMessages> = { | |||||||||||||||||||||||||||
| fetchingComment: (commentId: number) => `🔍 Fetching comment ${commentId}...`, | ||||||||||||||||||||||||||||
| updatingComment: (commentId: number) => `📝 Updating comment ${commentId}...`, | ||||||||||||||||||||||||||||
| commentUpdated: '✅ Comment updated successfully!', | ||||||||||||||||||||||||||||
| deletingComment: (commentId: number | string) => `🗑️ Deleting comment ${commentId}...`, | ||||||||||||||||||||||||||||
| commentDeleted: '✅ Comment deleted successfully!', | ||||||||||||||||||||||||||||
| confirmDelete: 'Are you sure you want to delete this comment? (y/N): ', | ||||||||||||||||||||||||||||
| deleteAborted: 'Delete aborted.', | ||||||||||||||||||||||||||||
| usageDeleteIssue: ' Usage: gh please issue comment delete <comment-id> [--yes]', | ||||||||||||||||||||||||||||
|
Comment on lines
+330
to
+334
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add the English translations for the new i18n keys. This completes the internationalization for the new command's logic.
Suggested change
|
||||||||||||||||||||||||||||
| bodyRequired: '❌ Error: --body or --body-file is required', | ||||||||||||||||||||||||||||
| bodyEmpty: '❌ Error: Comment body cannot be empty', | ||||||||||||||||||||||||||||
| usageIssue: ' Usage: gh please issue comment edit <comment-id> --body \'text\'', | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are several hardcoded English strings in the command's logic. To maintain consistency with the project's internationalization (i18n) approach, these should be moved to the
src/lib/i18n.tsfile.Specifically, the following strings are hardcoded:
--issueflag and invalid issue numbers.I have added separate comments on
src/lib/i18n.tswith suggestions to add the necessary keys. Once those are added, please update this file to use the new i18n messages. Remember to also usemsg.invalidIssueNumberfor theTypeError, as it's already available inCommentMessages.