티스토리 뷰

반응형

앱 심사 상태를 슬랙에 실시간으로 공유하는 방법을 찾고싶었는데 기존에 있는 오픈소스들도 있긴하지만

더 간편하게 만들수있지 않을까 싶은 생각이 들어 한번 만들어보았다.

 

일단 생각의 시초는 

애플은 앱의 상태가 변경되면 개발자 계정으로 등록된 이메일 주소로 상태값을 이메일을 쏴준다.

-> 그럼 이메일을 가져와서 슬랙에다가 쏴주면 되겠네?

-> 이메일을 슬랙에 쏘는 방법을 찾아보자

-> 아 슬랙이 무료 계정이라서 이메일 앱을 쓸수가 없네?

-> 수신 웹후크는 무료니까 그럼 다른 방법을 찾아보자

-> App script로 자동화 하는 사람들 많던데 그럼 App Script로 메일 읽어와서 슬랙에 수신 웹후크로 쏘면 되겠네!

 

그래서 생각한걸 한번 구현해봐야겠다 싶어서 만들어보았다.

 

일단 Slack에서 수신 웹후크를 추가해준다.

요기서 앱 추가 클릭
검색창에 IN만 입력해도 하단에 수신 웹후크가 뜨는데 추가 해준다.

 

 

 

그럼 사이트로 이동되는데 Slack에 추가를 클릭

 

채널을 선택하고 수신 웹후크 통합 앱 추가를 클릭하면 웹후크 URL이 생성된다. 

 

이 URL을 복사해서 어디 메모장에 복사해두고 이 창은 닫도록하자.

 

https://script.google.com/home/start 요 사이트로 들어가서

새 프로젝트를 생성해준다.

 

이런 창이 뜨는데 코드를 입력할수있다.

 

이제 코드를 작성해보자

function sendEmailToSlack() {  
  var specificSender = 'no_reply@email.apple.com'; 

// 특정 발신자로부터 읽지 않은 메일 검색
  var threads = GmailApp.search('from:' + specificSender + ' is:unread (subject:"The status of your (iOS) app" OR subject:"Your submission was accepted." OR subject:"We noticed an issue with your submission.")');

  if (threads.length > 0) {
      // 마지막 메일 가져오기
      var lastMessage = threads[threads.length - 1].getMessages()[0];
      var emailSubject = lastMessage.getSubject();
      var emailBody = lastMessage.getBody();

      var statusMessage = getStatusMessage(emailSubject);
      
      Logger.log(emailSubject);

      // Slack으로 보낼 메시지 구성
      if (statusMessage) {
          var receivedTime = new Date(); 
          var formattedReceivedTime = receivedTime.toLocaleString('ko-KR', { timeZone: 'Asia/Seoul' });

          var appVersion = extractInfo(emailBody, /App Version Number:\s*([^<]+)/);
          var appName = extractInfo(emailBody, /App Name:\s*([^<]+)/);
          var color = "#36a64f";
          if (emailSubject.includes('Your submission was accepted.')) {
            color = '#ADD8E6';  
          }
          if (emailSubject.includes("We noticed an issue with your submission.")) {
            color = "#FF6347";
            const textBody = emailBody.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
            // 버전 정보 추출
            const versionMatch = textBody.match(/([\d.]+)\s*for\s*iOS/i);
            if (versionMatch) {
                appVersion = versionMatch[1]; // 버전 정보 (예: 1.0.4)
            } else {
                appVersion = '정보 없음'; // 버전 정보가 없을 경우
            }
          } 

          var message = createSlackMessage(appName, appVersion, formattedReceivedTime, statusMessage, color);
          
          sendToSlack(message);
      }

      markMessagesAsRead(threads);
  } else {
      Logger.log('해당 발신자의 읽지 않은 메일이 없습니다.');
  }
}

function getStatusMessage(subject) {
    var status = subject.split('now');

    if (subject.includes("Your submission was accepted")) {
        return "배포 준비됨";
    } else if (subject.includes("We noticed an issue with your submission.")) {
        return "앱 심사 거부됨";
    } else {
        if (status.length > 1) {
            var statusMessage = status[1].trim();
            Logger.log(`statusMessage : ${statusMessage}`);
            var statusMessage = status[1].trim().replace(/\"/g, '');
            return mapStatusMessage(statusMessage);
        } else {
            return '상태를 찾을 수 없습니다.';
        }
    }
}

// 상태 메시지를 매핑하는 함수
function mapStatusMessage(statusMessage) {
    const statusMapping = {
        "Waiting for Review": "대기 중",
        "Ready for Distribution": "배포 준비 완료",
        "Pre-Order Ready for Sale" : "사전 주문 판매 준비 완료",
        "Pending Developer Release" : "보류 중인 개발자 릴리스",
        "Metadata Rejected" : "메타 데이터 거부",
        "Rejected": "거절됨",
        "Developer Rejected": "개발자 취소",
        "Ready For Review": "심사 대기중",
        "In Review": "심사 중",
        "Ready for Sale": "출시 대기 중",
        "Prepare for Submission": "제출 준비 중"
    };

    // 로그를 통해 statusMessage 확인
    
    Logger.log(`Received statusMessage: "${statusMessage}"`);
    
    return statusMapping[statusMessage] || "상태를 알 수 없습니다.";
}

// 정보 추출 함수
function extractInfo(body, regex) {
    var match = body.match(regex);
    return match ? match[1].trim() : '정보 없음';
}

// Slack 메시지 생성 함수
function createSlackMessage(appName, appVersion, receivedTime, statusMessage, color) {
    var message =`\n\n*[IOS] 앱 심사 상태가 변경되었습니다.*\n` +
           `App Name: ${appName}\n` +
           `App Version Number: ${appVersion}\n` +
           `Time : ${receivedTime}\n` +
           `Status: *${statusMessage}*`;
    return {
          attachments: [
              {
                  title: "App Store Connect",
                  text: message ,
                  color: color
              }
          ]
      };
}

// Slack으로 메시지 전송 함수
function sendToSlack(attachments) {
    var options = {
      method: 'post',
      contentType: 'application/json',
      payload: JSON.stringify(attachments)
    };
    var slackWebhookUrl = '웹훅 url 넣기';
    
    UrlFetchApp.fetch(slackWebhookUrl, options);
}

// 메시지를 읽음으로 표시하는 함수
function markMessagesAsRead(threads) {
    var messagesToMarkRead = [];
    threads.forEach(thread => {
        messagesToMarkRead = messagesToMarkRead.concat(thread.getMessages());
    });

    if (messagesToMarkRead.length > 0) {
        GmailApp.markMessagesRead(messagesToMarkRead);
        Logger.log("모든 메시지를 읽음으로 표시했습니다.");
    }
}

 

github에도 소스 올려두었다. 

https://github.com/Ko-Dean/appstore-status-appscript/blob/main/index.gs

 

appstore-status-appscript/index.gs at main · Ko-Dean/appstore-status-appscript

Contribute to Ko-Dean/appstore-status-appscript development by creating an account on GitHub.

github.com

 

이렇게 작성한다.  테스트를 하고싶다면 위에 실행버튼을 누르면 테스트할수있다.

근데 뭐 받은 이메일이 있고 안읽음 처리 해두었다면  테스트가 되겠지만 읽은 메일이라면 안읽음 표시로 바꿔서 테스트해보자.

 

 

https://developer.apple.com/help/app-store-connect/reference/app-and-submission-statuses/

 

App and submission statuses - Reference - App Store Connect - Help - Apple Developer

 

developer.apple.com

여기서 애플 앱 제출 상태 종류를 볼수있다. 일단 메일로 받아본 내용들만 코드로 정리했다.

 

 

왼쪽 메뉴에 4번째 트리거라는 메뉴를 클릭해주자

 

 

그럼 이렇게 이런 화면이 나오는데 파란색 + 트리거 추가 버튼을 클릭

 

요런 창이 하나 뜨는데 여기서 우리가 해야할건 저장뿐이다. 

근데 시간 간격을 바꾸고 싶다면 트리거 기반 시간 유형 선택에서 시간 단위 타이머를 클릭하면 

이렇게 다양하게 옵션이 있다.

분 단위 타이머로 하면 

 

이렇게 메일을 조금더 잦은 간격으로 조회할수있다.

 

아무튼 개인의 성향에 맞게 설정하고 저장을 눌러주자

그럼 팝업창이 하나 뜨는데 로그인한 계정을 클릭하고 저장하면 끝.

 

그럼 상태가 바뀔때마다 애플에서 상태 변경에 대한 메일을 보내줄때마다 슬랙에 자동으로 메세지가 남겨진다.

 

메일을 읽은 경우에는 슬랙 발송이 되지 않으므로 참고하자.

반응형