├── README.md ├── background.js ├── content-script.js ├── manifest.json ├── options.html └── options.js /README.md: -------------------------------------------------------------------------------- 1 | # Better Comment 2 | 3 | Better Comment는 GitHub에서 코멘트를 작성할 때, 해당 코멘트가 공격적이지 않고, 받는 사람의 기분을 상하지 않는지 분석해주는 크롬 확장 프로그램입니다. OpenAI의 API를 사용하여 코멘트를 분석하고, 개선된 문구를 제안합니다. 4 | 5 | ## 설치 방법 6 | 7 | 1. 이 저장소를 로컬 컴퓨터로 클론합니다. 8 | 9 | ```bash 10 | git clone https://github.com/paperspoon/better-comment.git 11 | ``` 12 | 13 | 2. 크롬 브라우저에서 `chrome://extensions/`로 이동합니다. 14 | 15 | 3. 오른쪽 상단의 "개발자 모드" 토글을 활성화합니다. 16 | 17 | 4. 왼쪽 상단의 "압축 해제된 확장 프로그램을 로드합니다." 버튼을 클릭하고, 클론한 저장소의 디렉토리를 선택합니다. 18 | 19 | ## 사용 방법 20 | 21 | 1. 확장 프로그램이 설치되면, 크롬 확장 프로그램 아이콘 영역에 새로운 아이콘을 확인할 수 있습니다. 22 | 23 | 2. GitHub 페이지에서 코멘트를 작성하는 텍스트 영역에 입력한 후 폼에서 포커스가 떠나면 (onBlur), 코멘트가 분석되어 개선된 문구가 표시됩니다. 24 | 25 | ## 설정 26 | 27 | 1. OpenAI API 키를 사용하려면, 아래 주소에서 API 키를 발급받으세요. 28 | https://platform.openai.com/ 29 | 30 | 2. 확장 프로그램 아이콘을 클릭하여 팝업창에서 API키를 입력한후 Save 버튼을 클릭합니다. 31 | 32 | 3. 필요에 따라 프롬프트를 바꾸거나 기타 옵션을 수정하실 수 있습니다. 33 | 34 | ## TODO 35 | 36 | - [ ] 코드를 포함해서 프롬프트를 작성할 수 있는 옵션 제공 (토큰 소모가 많을듯?) 37 | 38 | ## 기여 39 | 40 | 프로젝트에 기여하려면, 이 저장소를 포크한 후에 변경 사항을 커밋하고 풀 리퀘스트를 생성해주세요. 풀 리퀘스트가 검토된 후 프로젝트에 기여한 내용이 추가될 수 있습니다. 41 | 42 | ## 라이센스 43 | 44 | 이 프로젝트는 [MIT 라이센스](LICENSE)를 따릅니다. 45 | -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { 2 | if (request.type === "analyzeComment" && request.options) { 3 | analyzeComment(request.comment, request.options).then(sendResponse) 4 | } 5 | return true 6 | }) 7 | const analyzeComment = async (comment, options) => { 8 | const {prompt, api_key, temperature, max_tokens, model} = options; 9 | 10 | const response = await fetch(`https://api.openai.com/v1/engines/${model}/completions`, { 11 | method: "POST", 12 | headers: { 13 | "Content-Type": "application/json", 14 | "Authorization": `Bearer ${api_key}`, 15 | }, 16 | body: JSON.stringify({ 17 | prompt: `${prompt}: "${comment}"`, 18 | max_tokens: Number(max_tokens), 19 | n: 1, 20 | stop: null, 21 | temperature: Number(temperature) 22 | }), 23 | }); 24 | const data = await response.json(); 25 | if (data.error) { 26 | return data.error.message; 27 | } 28 | return data.choices[0].text.trim(); 29 | } -------------------------------------------------------------------------------- /content-script.js: -------------------------------------------------------------------------------- 1 | let resultElement = null; 2 | const keysWithDefault = [ 3 | ['api_key', 'your key'], 4 | ['model', 'text-davinci-003'], 5 | ['temperature', '0.7'], 6 | ['max_tokens', '1000'], 7 | ['selector', 'textarea[name="comment[body]"]:focus'], 8 | ['prompt', '이 github 코멘트를 보는 사람의 기분을 좋게 하고 더 도움이 되는 코멘트로 개선해줘'] 9 | ]; 10 | let lastComment = null; 11 | chrome.storage.sync.get("options", ({options}) => { 12 | if (!options) { 13 | options = keysWithDefault.reduce((acc, [key, defaultValue]) => { 14 | acc[key] = defaultValue; 15 | return acc; 16 | }) 17 | chrome.storage.sync.set({options}); 18 | } 19 | const analyzeComment = async (comment) => { 20 | resultElement.innerHTML = ``; 21 | return new Promise((resolve) => { 22 | chrome.runtime.sendMessage( 23 | {type: "analyzeComment", comment, options}, 24 | (improvedComment) => { 25 | resolve(improvedComment); 26 | } 27 | ); 28 | }) 29 | } 30 | 31 | const onInput = async (event) => { 32 | const comment = event.target.value; 33 | if (comment.trim().length === 0 || comment === lastComment) return 34 | lastComment = comment; 35 | const improvedComment = await analyzeComment(comment); 36 | resultElement.innerHTML = `
이렇게 써보는 것은 어떨까요? from better comment
${improvedComment}
`; 37 | observer.observe(document.body, {childList: true, subtree: true}) 38 | }; 39 | 40 | const observeCommentBox = () => { 41 | const commentBox = document.querySelector(options.selector); 42 | if (commentBox) { 43 | resultElement = document.createElement("div"); 44 | commentBox.parentElement.appendChild(resultElement); 45 | commentBox.addEventListener("blur", onInput); 46 | return true; 47 | } 48 | return false; 49 | }; 50 | 51 | const observer = new MutationObserver(() => { 52 | if (!observeCommentBox()) { 53 | setTimeout(observeCommentBox, 1000); 54 | } else { 55 | observer.disconnect(); 56 | } 57 | }); 58 | observer.observe(document.body, {childList: true, subtree: true}) 59 | }); 60 | 61 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Better Comment", 3 | "version": "0.1", 4 | "description": "Analyze and suggest improvements for comments using OpenAI's API", 5 | "manifest_version": 3, 6 | "permissions": [ 7 | "tabs", 8 | "storage" 9 | ], 10 | "host_permissions": [ 11 | "https://*.github.com/*", 12 | "https://*.openai.com/*" 13 | ], 14 | "action": { 15 | "default_popup": "options.html" 16 | }, 17 | "content_scripts": [ 18 | { 19 | "matches": [ 20 | "https://github.com/*" 21 | ], 22 | "js": [ 23 | "content-script.js" 24 | ] 25 | } 26 | ], 27 | "background": { 28 | "service_worker": "background.js" 29 | } 30 | } -------------------------------------------------------------------------------- /options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | 18 |