티스토리 뷰

로또번호 생성기는 간단한 앱이다.

로또번호 생성기에 연결하기라고 말하면 앱이 실행되고 번호를 알려주고 끝나는 형태이다.

간단하게 만들수 있기 때문에 nodejs기초를 이해만 하고 있으면 만들 수 있다. 

또 dialogflow에 대한 기초와 로직연결, webhook 연결 구조를 알기 좋은 소재이다.


깃허브 주소는 다음과 같다. -> https://github.com/lunaStratos/lottoNumberGenerator/blob/master/index.js



이번 버전은 내부에 있는 cloud function을 썼다 

구글 클라우드의 cloud function과 다를바 없다. 






이 앱은 로직으로 바로 접속해서 로직이 계산을 하고

끝나는 앱이다. 그래서 웹후크를 연결하는거 외엔 할게 없다.  




// Title

// 로또번호 생성기

//

// display name and invocation name (동일하게 해야 함)

//

// 로또번호 생성기

//

// Short Description

// 한국의 나눔 로또의 6개 번호를 생성해 줍니다. 

//

// Full Description

// 매일 찾아오는 8시의 기쁨! 로또번호를 만들어야 하는데 애매하다면?

// 로또번호 생성기에 연결하기 를 말하세요. 바로 만들어 드립니다. 

//

// Company

// Stratos Heavy Industries

//

// sample invocations

//  로또번호 생성기에 연결하기 (invocation name +에 연결하기)

// 

// 

// Policy

// 아무것도 기록하지 않습니다. 즐기세요.

//

// Test method

//  로또번호 생성기에 연결하기만 말하세요. ask.tell로 끝납니다. 아무런 에러도 없어요. 


'use strict';


process.env.DEBUG = 'actions-on-google:*';

const ApiAiAction = require('actions-on-google').ApiAiAssistant; // apiai


// cloud function name : lottogenerator

// cloud region asia-northeast1-a

// 아직 cloud function은 us 지역만 존재

// https://stackoverflow.com/questions/46902502/use-region-other-than-us-central1-for-google-cloud-functions


exports.dialogflowFirebaseFulfillment = (request, response) => {


    //switch : policy가 없으면 deny되기 때문에 policy페이지 만들어야 함. 

    // 구글 문서로도 만들수는 있다. 

    console.log('Request body: ' + JSON.stringify(request.body));

    let jsonLang = request.body.lang


이런식으로 GET과 POST페이지를 만들 수 있다. dialogflow앱은 policy페이지를 필요로 하는데 물론 구글 도큐먼트이든 html페이지이든 만들면 된다. 본인은 통상 webhook가 둘다 할 수 있게 만든다. 

    

    switch (request.method) {

        case 'GET': // policy를 위한 페이지임

            response.writeHead(200, {

                "Content-Type": "text/html; charset=utf-8"

            });


            var title = '로또번호 생성기 Private Policy';

            var body = '<p>로또번호 생성기 Private Policy</p>\n \

  <p>아무것도 저장하지 않습니다.</p>\n \

  <p>그냥 즐기세요</p>\n \

  <p> - Stratos Heavy Industy</p>';


            var code = [

        '<!DOCTYPE html>',

        '<html>',

        '<head>',

        '<meta charset="utf-8" />',

        '<title>' + title + '</title>',

        '</head>',

        '<body>',

        body,

        '</body>',

        '</html>'

      ].join('\n');


            response.write(code, "utf8");

            response.end();

            break;


        default: // post

            const app = new ApiAiAction({

                request,

                response

            });

            // 여기서부터 시작




            function shuffle(array) {

                var i = 0,

                    j = 0,

                    temp = null


                for (i = array.length - 1; i > 0; i -= 1) {

                    j = Math.floor(Math.random() * (i + 1))

                    temp = array[i]

                    array[i] = array[j]

                    array[j] = temp

                }

                return array;

            }




            // 처음 구동 메소드, tell로 바로 종료

            function welcome_func(app) {


                let textDisplay = ''; // 공통 텍스트

                let textSSML = '';  // 공통텍스트 


ja와 ko를 분리한 것은 나중에 japan앱으로도 만들 예정이라서 그렇다. 맞다. 이 앱은 일본에서도 쓸수 있는앱이다

물론 일본에서는 로또7(그 20부편으로 유명한 광고) 로또 6를 번호를 생성할 수 있는 용도로 만들었다. 

아직은 ja판을 제출하지 않았지만 제출할 예정이다. 그리고 실제로 ko와 ja시뮬레이터를 돌릴때 잘 돌아간다.

결론적으로 request의 lang을 쓰면 안에 있는 언어가 튀어나오고 이걸 비교로 만드는 것이 가능하다. 

dialogflow특성상 각 언어마다 서버를 달리 할수 없는 걸로 아는데, 그래서 이런 처리가 필요하다.

              

  if (jsonLang == "ko") {


메인기능이다. 이 앱은 기동후 바로 종료를 하는 형태라 메소드가 하나에서 끝난다. 

로직은 Array로 저장된 숫자를 shuffle을 한 후 그중 0부터 5번의 Array만까지의 수만 뽑는다.

그리고 나서 사용자 경험을 위해서 이를 정렬해서 보여주는 식이다.

JAVA에서는 간단하게 정렬이 되는데 JS에서는 그런 메소드가 없어서 남의 코드를 가져다 썼다(..)

  

                    var myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40

             , 41, 42, 43, 44, 45];


                    // 6개만 가져올 것 

                    var getArrays = [1, 2, 3, 4, 5, 6];

                    var resultArray = shuffle(myArray);


                    for (var i = 0; i < 6; i++) {

                        getArrays[i] = resultArray[i];

                    }


                    getArrays.sort(function (a, b) {

                        return a - b

                    }); // 사용자 경험을 위한 정렬 


                    // 텍스트 출력 (SSML 위해서 별도 분리)

                    textDisplay = "로또번호가 생성되었습니다. " +

                        getArrays[0] +

                        " " +

                        getArrays[1] +

                        " " +

                        getArrays[2] +

                        " " +

                        getArrays[3] +

                        " " +

                        getArrays[4] +

                        " " +

                        getArrays[5] +

                        " 입니다. 그럼 행운이 있길 빌께요. 바이바이~";


원래는 그냥 텍스트를 써서 둘다 app.tell에 넣어줘도 되지만 그럴경우 숫자를 읽는게 이상해서 SSML처리를 했다. SSML링크를 보면 알겠지만 숫자에 대해서 어떻게 읽을 것인가에 대한 처리에서 부터 음악을 넣을수도 있고 음악과 텍스트를 동시에 재생도 가능하다. 동시 재생에 대한 처리는 파이널 러시안룰렛의 welcome_func에서 적용을 했으니 그 코드를 참조하면 된다. 아니면 구글 레퍼런스를 참조하던가. 

                  


                    // SSML 출력 (SSML 위해서 별도 분리)

                    textSSML = "<speak>로또번호가 생성되었습니다. " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[0] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[1] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[2] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[3] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[4] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[5] +

                        "</say-as></speak> " +

                        " 입니다. 그럼 행운이 있길 빌께요. 바이바이~</speak>";


                } else if (jsonLang == "ja") {


                    // Lotto7: 1~37 번호 저장

                    var myArray7 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37];

                    // Lotto7: 1~43 번호 저장

                    var myArray6 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43];


                    // Lotto7 : 7개만 가져올 것 

                    // Lotto6 : 6개만 가져올 것 

                    var getArrays7 = [1, 2, 3, 4, 5, 6, 7];

                    var getArrays6 = [1, 2, 3, 4, 5, 6];

                    var resultArray6 = shuffle(myArray6);

                    var resultArray7 = shuffle(myArray7);


                    // lotto7

                    for (var i = 0; i < 7; i++) {

                        getArrays7[i] = resultArray7[i];

                    }


                    //lotto6

                    for (var j = 0; j < 6; j++) {

                        getArrays6[j] = resultArray6[j];

                    }


                    getArrays7.sort(function (a, b) {

                        return a - b

                    }); // 사용자 경험을 위한 정렬 

                    getArrays6.sort(function (a, b) {

                        return a - b

                    }); // 사용자 경험을 위한 정렬 


                    // 텍스트 출력 (SSML 위해서 별도 분리)

                    textDisplay = "ロト7番号が生成されました。" +

                        getArrays7[0] +

                        " " +

                        getArrays7[1] +

                        " " +

                        getArrays7[2] +

                        " " +

                        getArrays7[3] +

                        " " +

                        getArrays7[4] +

                        " " +

                        getArrays7[5] +

                        " " +

                        getArrays7[6] +

                        " です。ロト6の番号は " +

                        getArrays6[0] +

                        " " +

                        getArrays6[1] +

                        " " +

                        getArrays6[2] +

                        " " +

                        getArrays6[3] +

                        " " +

                        getArrays6[4] +

                        " " +

                        getArrays6[5] +

                        " です。" +

                        "それじゃ、また使ってください。バイバイ~";


                    // SSML 출력 (SSML 위해서 별도 분리)

                    textSSML = "<speak>ロト7番号が生成されました。 " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays7[0] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays7[1] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays7[2] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays7[3] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays7[4] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays7[5] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays7[6] +

                        "</say-as></speak> " +

                        " です。ロト6の番号は " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays6[0] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays6[1] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays6[2] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays6[3] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays6[4] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays6[5] +

                        "</say-as></speak> " +


                        " です。それじゃ、また使ってください。バイバイ~</speak>";


                } // lang end



app.tell로 바로 끝낸다. 이 앱은 다른 기능은 넣지 않고 단순히 알려주고 종료하는 형태로 끝냈다. 만약 종료하지 않는다면 app.ask로 하면 된다. 

              

                // tell 바로 종료시키기

                app.tell(app.buildRichResponse()

                    .addSimpleResponse({

                        speech: textSSML,

                        displayText: textDisplay

                    })

                );



                let actionMap = new Map(); // intent map save list


                actionMap.set('input.welcome', welcome_func); // first : welcome intent tell end

                app.handleRequest(actionMap); //   intent search



                break;

            }


    }

}





           

   // 처음 구동 메소드, tell로 바로 종료

                function welcome_func(app) {

                    console.log(app.lang);

                    // 1~45 번호 저장

                    var myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40

             , 41, 42, 43, 44, 45];


                    // 6개만 가져올 것 

                    var getArrays = [1, 2, 3, 4, 5, 6];

                    var resultArray = shuffle(myArray);


                    for (var i = 0; i < 6; i++) {

                        getArrays[i] = resultArray[i];

                    }


                    getArrays.sort(function (a, b) {

                        return a - b

                    }); // 사용자 경험을 위한 정렬 


                    // 텍스트 출력 (SSML 위해서 별도 분리)

                    let textDisplay = "로또번호가 생성되었습니다. " +

                        getArrays[0] +

                        " " +

                        getArrays[1] +

                        " " +

                        getArrays[2] +

                        " " +

                        getArrays[3] +

                        " " +

                        getArrays[4] +

                        " " +

                        getArrays[5] +

                        " 입니다. 그럼 행운이 있길 빌께요. 바이바이~";


  // SSML 출력 (SSML 위해서 별도 분리)

                    let textSSML = "<speak>로또번호가 생성되었습니다. " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[0] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[1] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[2] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[3] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[4] +

                        "</say-as></speak> " +

                        '<speak> <say-as interpret-as="cardinal">' + getArrays[5] +

                        "</say-as></speak> " +

                        " 입니다. 그럼 행운이 있길 빌께요. 바이바이~</speak>";


      // tell러 바로 종료시키기

                    app.tell(app.buildRichResponse()

                        .addSimpleResponse({

                            speech: textSSML,

                            displayText: textDisplay

                        })

                    );

                }

                let actionMap = new Map(); // intent map save list


                actionMap.set('input.welcome', welcome_func); // first : welcome intent tell end

                app.handleRequest(actionMap); //   intent search


                break;

            }


    }

}


딱 봐도 초보자가 쓴 코드임을 알수 있다. 그럴수밖에 프로그래밍 개발한지 1년도 안된 사람이 만드는데 코드가 깔끔할 일이 있을리가

간단하지만 한국어, 일본어 지원이 가능한 형태의 코드이다.

이를 복사해서 본인이 원하는 Webhook를 만들면 될것이다.




앱이 다국어로 만든다면 다음과 같이 언어를 지정해서 작성이 가능하다.



한국어와 일본어 페이지는 다음과 같이 만들었다.

보면 알겠지만 인보케이션 이름은 특정한 규칙이 있다

다음 레퍼런스를 참조하면 된다. 

https://developers.google.com/actions/localization/languages-locales


각언어 부분에 인보케이션의 구조가 있다.




이미지와 개인정보 정책 그리고 회사이름


테스트 방법은 안적어도 된다.

그냥 적었다.

카테고리는 생산성으로 했다.




이럴때는 소리 아이콘 왼쪽왼쪽에 있는 Change version을 확인해보자 

Draft로 되어있는지 확인


이렇게 해서 깔끔하게 앱이 등록이 되었다. 









공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함