Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building Alexa custom skill by Serverless Framework

Building Alexa custom skill by Serverless Framework

Serverless Meetup Osaka 2017/08/25 #serverlessosaka

Hidetaka Okamoto
PRO

August 25, 2017
Tweet

More Decks by Hidetaka Okamoto

Other Decks in Programming

Transcript

  1. S e r v e r l e s s M e e t u p O s a k a 2 0 1 7 / 0 8 / 2 5
    B u i l d i n g A l e x a c u s t o m s k i l l
    b y S e r v e r l e s s F r a m e w o r k
    #getshifter

    View Slide

  2. H i d e t a k a
    O k a m o t o
    • Digitalcube Co. Ltd.
    • AMIMOTO / Shifter
    • WordCamp Kyoto 2017
    #getshifter

    View Slide

  3. ࠓ ೔ ͷ ࿩
    • Node.jsͰAmazon AlexaͷεΩϧΛͭ͘Ζ͏
    • Serverless FrameworkΛ࢖ͬͯσϓϩΠ΍؅ཧΛ؆୯ʹ
    • ςετ༻ϥΠϒϥϦΛ࢖͑͹ΑΓߏங͕؆୯ศརʹ
    #getshifter

    View Slide

  4. A m a z o n E c h o & m o re
    h t t p s : / / w w w. a m a z o n . c o m / d p / B 0 1 E 6 A O 6 9 U
    #getshifter

    View Slide

  5. w e b A P I ϕʔε Ͱ Ξ ϓ Ϧ ͕ ࡞ Ε Δ ʢ A S K ʣ
    h t t p s : / / d e v e l o p e r. a m a z o n . c o m / a l e x a - s k i l l s - k i t
    #getshifter

    View Slide

  6. A u d i o
    C a p t u re
    A u d i o
    P l a y b a c k
    C a l l w e b A P I
    Ta l k
    s o m t h i n g
    R e s p o n c e
    S p e e c h t o
    Te x t
    Te x t t o
    S p e e c h

    View Slide

  7. View Slide

  8. L i v e t o d a y !
    • Shifter news skill
    • Read our official blog feed
    • We can easy downloads
    https://www.amazon.com/
    dp/B0753C53WQ/

    View Slide

  9. ࠓ ೔ ͷ ࿩
    • Node.jsͰAmazon AlexaͷεΩϧΛͭ͘Ζ͏
    • Serverless FrameworkΛ࢖ͬͯσϓϩΠ΍؅ཧΛ؆୯ʹ
    • ςετ༻ϥΠϒϥϦΛ࢖͑͹ΑΓߏங͕؆୯ศརʹ
    #getshifter

    View Slide

  10. [ ج ຊ ] A l e x a S k i l l ͸ J S O N Λ ड ͚ औ ͬͯ J S O N Λ ฦ ͢
    {
    " v e r s i o n " : " s t r i n g " ,
    " re s p o n s e " : {
    " o u t p u t S p e e c h " : {
    " t y p e " : " s t r i n g " ,
    " t e x t " : " s t r i n g " ,
    " s s m l " : " s t r i n g "
    } ,
    " c a rd " : {
    " t y p e " : " s t r i n g " ,
    " i m a g e " : {
    " s m a l l I m a g e U r l " : " s t r i n g " ,
    " l a rg e I m a g e U r l " : " s t r i n g "
    }

    #getshifter

    View Slide

  11. A l e x a S k i l l s K i t S D K f o r N o d e . j s
    • ݱࡏެࣜϦϦʔε͞Ε͍ͯΔ།ҰͷSDK
    • npm install -S alexa-sdk
    • αϯϓϧίʔυ΋୔ࢁ
    https://github.com/alexa/
    alexa-skills-kit-sdk-for-nodejs

    View Slide

  12. A l e x a S k i l l s K i t S D K f o r N o d e . j s E x a m p l e s
    • Hello World
    • RSS / ATOM Feed ͷಡΈ্͛
    • ΫΠζήʔϜ
    • γςΟΨΠυ
    • etc…
    https://github.com/alexa/

    View Slide

  13. A l e x a S D K Λ ࢖ ͏
    ' u s e s t r i c t ' ;
    v a r A l e x a = re q u i re ( ' a l e x a - s d k ' ) ;
    m o d u l e . e x p o r t s . h e l l o = ( e v e n t , c o n t e x t , c a l l b a c k ) = > {
    v a r a l e x a = A l e x a . h a n d l e r ( e v e n t , c o n t e x t , c a l l b a c k ) ;
    a l e x a . re g i s t e r H a n d l e r s ( h a n d l e r s ) ;
    a l e x a . e x e c u t e ( ) ;
    } ;
    #getshifter

    View Slide

  14. A l e x a S D K Λ ࢖ ͏
    ' u s e s t r i c t ' ;
    c o n s t A l e x a = re q u i re ( ' a l e x a - s d k ' ) ;
    m o d u l e . e x p o r t s . h e l l o = ( e v e n t , c o n t e x t , c a l l b a c k ) = > {
    c o n s t a l e x a = A l e x a . h a n d l e r ( e v e n t , c o n t e x t , c a l l b a c k ) ;
    a l e x a . re g i s t e r H a n d l e r s ( h a n d l e r s ) ;
    a l e x a . e x e c u t e ( ) ;
    } ;
    S D K ͷ ಡ Έ ࠐ Έ
    ϋ ϯ υ ϥ ͷ η ο τΞ οϓ
    ϋ ϯ υ ϥ ͷ ઃ ఆ
    ࣮ ߦ
    #getshifter

    View Slide

  15. Πϕ ϯ τϋ ϯ υ ϥ ͸ O b j e c t ܗ ࣜ Ͱ
    v a r h a n d l e r s = {
    ' L a u n c h R e q u e s t ' : f u n c t i o n ( ) {
    t h i s . e m i t ( ' : t e l l ' , ' H e l l o ' ) ;
    } ,
    } ,
    ' N a m e I n t e n t ' : f u n c t i o n ( ) {
    c o n s t s l o t s = t h i s . e v e n t . re q u e s t . i n t e n t . s l o t s ;
    c o n s t n a m e Va l u e = s l o t s . N a m e S l o t . v a l u e ;
    t h i s . e m i t ( ' : t e l l ' , ` N i c e t o m e e t y o u , $ { n a m e Va l u e } . E n j o y A l e x a w o r l d ! ` ) ;
    } ,
    } ;
    I N T E N T ໊ Λ Ω ʔ ʹ ͢ Δ
    S L O T ͷ ৘ ใ Λ औ ಘ ͢ Δ
    t h i s . e m i t ʹ Ϩε ϙ ϯε ͳ Ͳ Λ ॻ ͘
    #getshifter

    View Slide

  16. Tr y E x a m p l e s !
    • αϯϓϧεΩϧ͸શͯηοτΞοϓΨΠυ෇͖
    • εΫγϣ΋͋ΔͷͰӳޠۤखͰ΋҆৺
    • ࡞Γ͍ͨεΩϧͷαϯϓϧΛϕʔεʹ
    ɹσʔλΛॻ͖׵͑ͯ
    ɹࣗ෼ͷεΩϧʹ͠Α͏ʂ
    http://bit.ly/2vSAZhB

    View Slide

  17. ࠓ ೔ ͷ ࿩
    • Node.jsͰAmazon AlexaͷεΩϧΛͭ͘Ζ͏
    • Serverless FrameworkΛ࢖ͬͯσϓϩΠ΍؅ཧΛ؆୯ʹ
    • ςετ༻ϥΠϒϥϦΛ࢖͑͹ΑΓߏங͕؆୯ศརʹ
    #getshifter

    View Slide

  18. L a m b d a ͷ σ ϓ ϩ Π ͸ ؆ ୯ ʹ ͠ ͨ ͍
    #getshifter

    View Slide

  19. S e r v e r l e s s F r a m e w o r k
    h t t p s : / / s e r v e r l e s s . c o m
    #getshifter

    View Slide

  20. S e r v e r l e s s F r a m e w o r k
    • Node.js੡ͷServerlessΞϓϦέʔγϣϯͷσϓϩΠɾ؅ཧπʔϧ
    • AWSɾGCPɾAzureɾIBMͷෳ਺ϓϥοτϑΥʔϜରԠ
    • YAMLܗࣜͰϦιʔεΛఆٛ͢ΔͷͰɺߏ੒؅ཧ͕؆୯
    #getshifter

    View Slide

  21. S e r v e r l e s s F r a m e w o r k Λ ಋ ೖ ͢ Δ
    $ n p m i n s t a l l - g s e r v e r l e s s
    $ c d / PAT H / T O / Y O U R / A P P
    $ s l s c re a t e - t a w s - n o d e j s
    $ s l s d e p l o y
    #getshifter

    View Slide

  22. σΟ Ϩ Ϋ τ Ϧ ߏ ଄
    $ t re e - L 1
    .
    ᵓ ᴷ ᴷ h a n d l e r. j s
    ᵓ ᴷ ᴷ n o d e _ m o d u l e s
    ᵓ ᴷ ᴷ p a c k a g e . j s o n
    ᵋ ᴷ ᴷ s e r v e r l e s s . y m l
    #getshifter

    View Slide

  23. s e r v e r l e s s . y m l
    s e r v i c e : n o d e - a l e x a - t d d - e x a m p l e
    f r a m e w o r k Ve r s i o n : " > = 1 . 1 0 . 1 "
    p ro v i d e r :
    n a m e : a w s
    r u n t i m e : n o d e j s 6 . 1 0
    re g i o n : u s - e a s t - 1
    p a c k a g e :
    i n c l u d e :
    - n o d e _ m o d u l e s /
    f u n c t i o n s :
    h e l l o :
    h a n d l e r : h a n d l e r. h e l l o
    e v e n t s :
    - a l e x a S k i l l
    #getshifter

    View Slide

  24. s e r v e r l e s s . y m l - 1
    s e r v i c e : n o d e - a l e x a - t d d - e x a m p l e
    f r a m e w o r k Ve r s i o n : " > = 1 . 1 0 . 1 "
    ϓ ϩ δΣ Ϋ τ ໊
    S E R V E R L E S S ͷ όʔ δ ϣ ϯ
    #getshifter

    View Slide

  25. s e r v e r l e s s . y m l - 2
    p ro v i d e r :
    n a m e : a w s
    r u n t i m e : n o d e j s 6 . 1 0
    re g i o n : u s - e a s t - 1
    ར ༻ ͢ Δ Ϋ ϥ ΢ υ
    ϥϯ λ ΠϜ
    σ ϓ ϩ Π ઌ
    #getshifter

    View Slide

  26. s e r v e r l e s s . y m l - 3
    p a c k a g e :
    i n c l u d e :
    - n o d e _ m o d u l e s /
    ಉ ࠝ ͢ Δ σΟ Ϩ Ϋ τ Ϧ
    #getshifter

    View Slide

  27. s e r v e r l e s s . y m l - 4
    f u n c t i o n s :
    h e l l o :
    h a n d l e r : h a n d l e r. h e l l o
    e v e n t s :
    - a l e x a S k i l l
    L A M B D A ͷ Πϕ ϯ τ Λ A S K ʹ
    ࣮ ߦ ͢ Δ ؔ ਺ ໊
    ϑ Ν ϯ Ϋ γ ϣ ϯ ໊
    #getshifter

    View Slide

  28. S e r v e r l e s s F r a m e w o r k Ͱ σ ϓ ϩ Π ΍ ಈ ࡞ ֬ ೝ ͢ Δ
    # ຊ ൪ ༻ ͷ σ ϓ ϩ Π
    $ s l s d e p l o y — s t a g e p ro d u c t i o n
    # ݸ ਓ Ξ Χ ΢ ϯ τ ʹ σ ϓ ϩ Π
    $ s l s d e p l o y — s t a g e d e v e l o p m e n t — p ro f i l e m y l o c a l
    # ϩ ʔΧ ϧ Ͱ ͷ ಈ ࡞ ֬ ೝ
    $ s l s i n v o k e l o c a l - f h e l l o
    #getshifter

    View Slide

  29. ࠓ ೔ ͷ ࿩
    • Node.jsͰAmazon AlexaͷεΩϧΛͭ͘Ζ͏
    • Serverless FrameworkΛ࢖ͬͯσϓϩΠ΍؅ཧΛ؆୯ʹ
    • ςετ༻ϥΠϒϥϦΛ࢖͑͹ΑΓߏங͕؆୯ศརʹ
    #getshifter

    View Slide

  30. σ ϓ ϩ Π લ ʹ ςε τ ͯ͠ ͓ ͖ ͨ ͍
    #getshifter

    View Slide

  31. A l e x a C o n v e r s a t i o n
    • AlexaͰͷձ࿩ΛςετͰ͖Δπʔϧ
    • mochaͰςετΛ࣮ߦ͢Δ
    • ձ࿩ϕʔεͷςετίʔυ
    https://github.com/ExpediaDotCom/
    alexa-conversation

    View Slide

  32. ૝ ఆ ͯ͠ ͍ Δ ձ ࿩ Λ ςε τ ί ʔ υ ʹ Ͱ ͖ Δ
    c o n v e r s a t i o n ( o p t s )
    . u s e r S a y s ( ' H e l l o I n t e n t ' )
    . p l a i n R e s p o n s e
    . s h o u l d C o n t a i n ( " H e l l o . I ' m e x a m p l e s k i l l s . " )
    . e n d ( ) ;
    #getshifter

    View Slide

  33. ಋ ೖ
    $ n p m i n s t a l l - - D a l e x a - c o n v e r s a t i o n
    $ n p m i n s t a l l - - D m o c h a
    $ m k d i r t e s t s
    $ t o u c h t e s t s / h a n d l e r. t e s t . j s
    #getshifter

    View Slide

  34. ςε τ ͷ ४ උ
    c o n s t c o n v e r s a t i o n = re q u i re ( ' a l e x a - c o n v e r s a t i o n ' ) ;
    c o n s t a p p = re q u i re ( ' . . / h a n d l e r. j s ' ) ;
    c o n s t o p t s = {
    n a m e : ' H e l l o A l e x a Te s t ' ,
    a p p I d : ' y o u r- a p p - i d ' ,
    a p p : a p p ,
    h a n d l e r : a p p . h e l l o
    } ;
    #getshifter

    View Slide

  35. ςε τ ί ʔ υ Λ ॻ ͘
    c o n v e r s a t i o n ( o p t s )
    . u s e r S a y s ( ' H e l l o I n t e n t ' )
    . p l a i n R e s p o n s e
    . s h o u l d C o n t a i n ( " H e l l o . I ' m e x a m p l e s k i l l s f o r y o u r s e r v e r l e s s p ro j e c t s . " )
    . s h o u l d C o n t a i n ( " P l e a s e t e l l m e y o u r n a m e . " )
    . u s e r S a y s ( ' N a m e I n t e n t ' , { N a m e S l o t : ' Ts u y o s h i ' } )
    . p l a i n R e s p o n s e
    . s h o u l d C o n t a i n ( " N i c e t o m e e t y o u , Ts u y o s h i . E n j o y A l e x a w o r l d ! " )
    . e n d ( ) ;
    #getshifter

    View Slide

  36. ςε τ Λ ࣮ ߦ ʢ a l e x a - s d k Λ ಡ Έ ࠐ ΜͰ ͳ ͍ ৔ ߹ ͷ Τ ϥ ʔ ʣ
    $ n o d e _ m o d u l e s / m o c h a / b i n / _ m o c h a t e s t s
    ( n o d e : 3 7 9 8 1 ) U n h a n d l e d P ro m i s e R e j e c t i o n Wa r n i n g : U n h a n d l e d p ro m i s e re j e c t i o n
    ( re j e c t i o n i d : 3 ) : Ty p e E r ro r : c a l l b a c k i s n o t a f u n c t i o n
    ( n o d e : 3 7 9 8 1 ) D e p re c a t i o n Wa r n i n g : U n h a n d l e d p ro m i s e re j e c t i o n s a re d e p re c a t e d .
    I n t h e f u t u re , p ro m i s e re j e c t i o n s t h a t a re n o t h a n d l e d w i l l t e r m i n a t e t h e N o d e . j s
    p ro c e s s w i t h a n o n - z e ro e x i t c o d e .
    E x e c u t i n g c o n v e r s a t i o n : H e l l o A l e x a Te s t
    ( n o d e : 3 7 9 8 1 ) P ro m i s e R e j e c t i o n H a n d l e d Wa r n i n g : P ro m i s e re j e c t i o n w a s h a n d l e d
    a s y n c h ro n o u s l y ( re j e c t i o n i d : 3 )
    E R R O R : Ty p e E r ro r : c a l l b a c k i s n o t a f u n c t i o n
    #getshifter

    View Slide

  37. ί ʔ υ Λ ॻ ͘ − ̍
    ' u s e s t r i c t ' ;
    v a r A l e x a = re q u i re ( ' a l e x a - s d k ' ) ;
    m o d u l e . e x p o r t s . h e l l o = ( e v e n t , c o n t e x t , c a l l b a c k ) = > {
    v a r a l e x a = A l e x a . h a n d l e r ( e v e n t , c o n t e x t , c a l l b a c k ) ;
    a l e x a . re g i s t e r H a n d l e r s ( h a n d l e r s ) ;
    a l e x a . e x e c u t e ( ) ;
    } ;
    #getshifter

    View Slide

  38. ί ʔ υ Λ ॻ ͘ − ̎
    v a r h a n d l e r s = {
    ' L a u n c h R e q u e s t ' : f u n c t i o n ( ) {
    t h i s . e m i t ( ' : t e l l ' , ' H e l l o ' ) ;
    } ,
    ' H e l l o I n t e n t ' : f u n c t i o n ( ) {
    t h i s . e m i t ( ' : t e l l ' , ` H e l l o . I ' m e x a m p l e s k i l l s f o r y o u r s e r v e r l e s s p ro j e c t s .
    P l e a s e t e l l m e y o u r n a m e .
    ` ) ;
    } ,
    ' N a m e I n t e n t ' : f u n c t i o n ( ) {
    c o n s t s l o t s = t h i s . e v e n t . re q u e s t . i n t e n t . s l o t s ;
    c o n s t n a m e Va l u e = s l o t s . N a m e S l o t . v a l u e ;
    t h i s . e m i t ( ' : t e l l ' , ` N i c e t o m e e t y o u , $ { n a m e Va l u e } . E n j o y A l e x a w o r l d ! ` ) ;
    } ,
    } ;
    #getshifter

    View Slide

  39. ςε τ Λ ࣮ ߦ
    $ n o d e _ m o d u l e s / m o c h a / b i n / _ m o c h a t e s t s
    E x e c u t i n g c o n v e r s a t i o n : H e l l o A l e x a Te s t
    ✓ F i n i s h e d e x e c u t i n g c o n v e r s a t i o n
    C o n v e r s a t i o n : H e l l o A l e x a Te s t
    U s e r t r i g g e r s : H e l l o I n t e n t
    ✓ A l e x a ' s p l a i n t e x t re s p o n s e s h o u l d c o n t a i n : H e l l o . I ' m e x a m p l e s k i l l s f o r y o u r
    s e r v e r l e s s p ro j e c t s .
    ✓ A l e x a ' s p l a i n t e x t re s p o n s e s h o u l d c o n t a i n : P l e a s e t e l l m e y o u r n a m e .
    U s e r t r i g g e r s : N a m e I n t e n t S L O T S : { N a m e S l o t : Ts u y o s h i }
    ✓ A l e x a ' s p l a i n t e x t re s p o n s e s h o u l d c o n t a i n : N i c e t o m e e t y o u , Ts u y o s h i . E n j o y
    A l e x a w o r l d !
    4 p a s s i n g ( 1 6 m s )
    #getshifter

    View Slide

  40. · ͱ Ί
    #getshifter

    View Slide

  41. A l e x a S k i l l s ͸ ࢥ ͬͯ ͍ Δ Α Γ ͸ ؆ ୯ ʹ ࡞ Ε · ͢ 


    ɾ ެ ࣜ ͷ ϥ Π ϒ ϥ Ϧ ΋ ͋ Δ
    ɾ σ ϓ ϩ Π ͷ ͨ Ί ͷ ศ ར π ʔϧ ΋ ͋ Δ
    ɾ α ϯ ϓϧί ʔ υ ΋ ୔ ࢁ ͋ Δ
    ɾ ΍ Δ ͠ ͔ ͳ ͍ ʂ
    #getshifter

    View Slide

  42. 9 / 3 Wo rd B e n c h େ ࡕ w i t h ژ ౎ & ௕ ໺
    h t t p s : / / w b o s a k a . c o n n p a s s . c o m / e v e n t / 6 2 0 6 0 /

    View Slide

  43. 9 / 3 Wo rd B e n c h େ ࡕ w i t h ژ ౎ & ௕ ໺
    h t t p s : / / w b o s a k a . c o n n p a s s . c o m / e v e n t / 6 2 0 6 0 /

    View Slide

  44. 9 / 3 ΋ େ ࡕ Ͱ A l e x a ͷ ࿩ ͠ · ͠ ΐ ͏ ʂ
    #getshifter

    View Slide

  45. ΋ ͬ ͱ A l e x a ͷ ࿩ Λ ฉ ͖ ͨ ͍ ํ
    #getshifter

    View Slide

  46. 1 0 0 ճ ͷ ࢀ Ճ Α Γ ΋ ɺ 1 ճ ͷ ొ ஃ
    #getshifter

    View Slide

  47. ΍ Γ · ͠ ΐ ͏
    #getshifter

    View Slide

  48. N e e d A l e x a S k i l l s ?
    • ߏஙࢧԉαʔϏε͸͡Ί·ͨ͠
    • https://www.digitalcube.jp/service/web-service/
    • ૬ஊ͓·͓ͪͯ͠Γ·͢

    View Slide

  49. ࠓ ೔ ͷ ࿩
    • Node.jsͰAmazon AlexaͷεΩϧΛͭ͘Ζ͏
    • Serverless FrameworkΛ࢖ͬͯσϓϩΠ΍؅ཧΛ؆୯ʹ
    • ςετ༻ϥΠϒϥϦΛ࢖͑͹ΑΓߏங͕؆୯ศརʹ
    #getshifter

    View Slide

  50. ࠓ ೔ ͷ ࿩
    • Node.jsͰAmazon AlexaͷεΩϧΛͭ͘Ζ͏
    • Serverless FrameworkΛ࢖ͬͯσϓϩΠ΍؅ཧΛ؆୯ʹ
    • ςετ༻ϥΠϒϥϦΛ࢖͑͹ΑΓߏங͕؆୯ศརʹ
    • ͓·͚
    #getshifter

    View Slide

  51. View Slide

  52. a l e x a - s d k ͸ ݱ ࡏ ະ ର Ԡ ( 2 0 1 7 / 0 8 / 2 5 )
    • issue͸͢Ͱʹཱ͍ͬͯΔ
    • Pull Request͸·ͩͳ͍༷ࢠ
    • JSڧ͍ํ͸Let’s try !
    https://github.com/alexa/
    alexa-skills-kit-sdk-for-nodejs

    View Slide

  53. S h o w ର Ԡ ΋ ΍ Δ ͜ ͱ ͸ Ұ ॹ
    • Alexa Skills ͱͯ͠࡞Δ
    • JSONΛड͚औͬͯJSONΛฦ͢
    • දࣔ༻ͷϑΥʔϚοτΛ௥Ճ͢Δ
    https://developer.amazon.com/public/solutions/
    alexa/alexa-skills-kit/docs/display-interface-
    reference#template-interfaces-json

    View Slide

  54. Ϩε ϙ ϯε J S O N ͷ α ϯ ϓϧ
    {
    " re s p o n s e " : {
    " d i re c t i v e s " : [
    {
    " t y p e " : " D i s p l a y. R e n d e r Te m p l a t e " ,
    " t e m p l a t e " : {
    " t y p e " : " s t r i n g "
    }
    } ,
    {
    " t y p e " : " H i n t " ,
    " h i n t " : {
    " t y p e " : " P l a i n Te x t " ,
    " t e x t " : " s t r i n g "
    }
    }
    ] ,
    #getshifter

    View Slide

  55. ݱ ࣌ ఺ Ͱ ͷ ର Ԡ ϑ Υ ʔ Ϛ ο τ ( 2 0 1 7 / 0 8 / 2 5 )
    • Ϧετʢը૾͋Γɾͳ͠ʣ
    • ςΩετ
    • ςΩετʴը૾
    • શ̒छྨ
    https://developer.amazon.com/public/solutions/alexa/
    alexa-skills-kit/docs/display-interface-reference#template-
    interfaces-json

    View Slide

  56. T h a n k s !
    • Node.jsͰAmazon AlexaͷεΩϧΛͭ͘Ζ͏
    • Serverless FrameworkΛ࢖ͬͯσϓϩΠ΍؅ཧΛ؆୯ʹ
    • ςετ༻ϥΠϒϥϦΛ࢖͑͹ΑΓߏங͕؆୯ศརʹ
    • How to support Amazon Echo Show
    #getshifter

    View Slide