Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Go + Google Cloud Functions を使ったSlackのThreadにも対...
Search
ktykogm
July 25, 2019
Programming
0
450
Go + Google Cloud Functions を使ったSlackのThreadにも対応したbotを簡単に作る方法
Slack Dev Meetup Tokyo #1 LT 資料です。
ktykogm
July 25, 2019
Tweet
Share
More Decks by ktykogm
See All by ktykogm
街じゅうを"駅前化"する電動マイクロモビリティのシェアサービス「LUUP」のIoTとSRE
0gm
2
11k
サービスと組織の拡大を支えるEmbedded SREs
0gm
7
3.6k
SRE的team開発Tipsとベストプラクティスっぽい何か
0gm
9
5.4k
Other Decks in Programming
See All in Programming
TypeScriptでDXを上げろ! Hono編
yusukebe
3
650
技術同人誌をMCP Serverにしてみた
74th
1
680
Railsアプリケーションと パフォーマンスチューニング ー 秒間5万リクエストの モバイルオーダーシステムを支える事例 ー Rubyセミナー 大阪
falcon8823
5
1.4k
ソフトウェア品質を数字で捉える技術。事業成長を支えるシステム品質の マネジメント
takuya542
2
14k
なんとなくわかった気になるブロックテーマ入門/contents.nagoya 2025 6.28
chiilog
1
280
なぜ「共通化」を考え、失敗を繰り返すのか
rinchoku
1
670
AIエージェントはこう育てる - GitHub Copilot Agentとチームの共進化サイクル
koboriakira
0
620
ふつうの技術スタックでアート作品を作ってみる
akira888
1
1.1k
AI時代の『改訂新版 良いコード/悪いコードで学ぶ設計入門』 / ai-good-code-bad-code
minodriven
22
9k
The Evolution of Enterprise Java with Jakarta EE 11 and Beyond
ivargrimstad
0
180
Composerが「依存解決」のためにどんな工夫をしているか #phpcon
o0h
PRO
1
330
Modern Angular with Signals and Signal Store:New Rules for Your Architecture @enterJS Advanced Angular Day 2025
manfredsteyer
PRO
0
240
Featured
See All Featured
Speed Design
sergeychernyshev
32
1k
Build The Right Thing And Hit Your Dates
maggiecrowley
37
2.8k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
60k
Facilitating Awesome Meetings
lara
54
6.5k
Building Applications with DynamoDB
mza
95
6.5k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
29
9.6k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.7k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
Producing Creativity
orderedlist
PRO
346
40k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
7
330
Designing Experiences People Love
moore
142
24k
Code Review Best Practice
trishagee
69
19k
Transcript
(P (PPHMF$MPVE'VODUJPOTΛͬ ͨ4MBDLͷUISFBEʹରԠͨ͠CPUΛ؆ ୯ʹ࡞Δํ๏ λΠτϧ͕͗ͨ͢LUZLPHN 4MBDL%FW.FFUVQ5PLZP-5ࢿྉ
XIPBNJ w !LUZLPHN LPHVNB w ϝϧΧϦ43& w ࠷ۙ(PΛۀͰͨ·ʹॻ͍͍ͯΔϨϕϧ w
ʮ4MBDL (PͳΒͦͷ͘Β͍؆୯ʹԼ४උͰ͖ΔΑʯͱ͍͏͜ͱΛ ͑ʹདྷ·ͨ͠ w 43&-PVOHFͱ͍͏ίϛϡχςΟͷӡӦ׆ಈΛ͍ͯ͠·͢ɻ
ຊ͍͑ͨ͜ͱ w 4MBDL (P $MPVE'VODUJPOTͷ૬ੑ w (PΛͬͨ4MBDLͷ5ISFBEରԠํ๏ w (Pք۾ͰΑ͘ΒΕͨOMPQFTTMBDL͕DPPPPPPPPM w
ͦΕΒ#PU ͦΕҎ֎ ࡞ɺαʔόͱӡ༻අΛ༻ҙͤͣʹؾָʹ࢝Ί ΒΕΔ
$MPVE'VODUJPOTͱ w ΠϕϯτυϦϒϯͳαʔόϨείϯϐϡʔτϓϥοτ ϑΥʔϜ w (BUFXBZແͯ͘ಈ͘ w &YUFOTJCMF4FSWJDF1SPYZ &41 Λͬͯ(BUFXBZ
FOEQPJOUߏͪΖΜͰ͖·͢ɻ w ͦͷ··ؔΛઃஔͰ͖Δ HPCVJMEෆཁ w ࣗಈతʹεέʔϧͭɺ)" w ଞͷ($1αʔϏεʹଓ֦ͯ͠ு͕Մೳ w ແྉ͕ଘࡏ͢Δ w ݄ؒͰɺສݺͼग़͠ ສඵ (#ԼΓτϥ ϑΟοΫ ݄ʹ(PSVUJNF͕CFUBSFMFBTF IUUQTDMPVEHPPHMFDPNGVODUJPOT
$MPVE'VODUJPOT ଞͷ($1αʔϏεʹଓ֦ͯ͠ு͕Մೳ w $MPVE1VC4VC w $MPVE4UPSBHF w )551 w 4UBDLESJWFS-PHHJOH
w 'JSFCBTF w $MPVE42- $POOFDU71$ FUD
ࣄલ४උ w 4MBDLͷ༻ҙ w (PPHMF$MPVE1MBUGPSN ($1 ͷΞΧϯτΛ࡞ w HDMPVEίϚϯυ͕͑ΔΑ͏ʹ(PPHMF$MPVE4%,Λ*OTUBMM w
IUUQTDMPVEHPPHMFDPNTELJOTUBMM w HDMPVEݱࡏ1ZUIPO͕ඞཁͳͷͰɺQZFOWͰXPSLJOH EJSFDUPSZʹQZFOWMPDBMYͰཧ͢Δͱྑ͍Ͱ͢
ࠓճͷߏͱڥʹ͍ͭͯ w ࠓճ-5ͳͷͰλΠτϧʹ͋Δ4MBDL5ISFBEʹରԠͨ͠#PUΛ࡞͢Δ ํ๏ͱͦͷઆ໌͚ͩʹ༰Λ΄΅ߜΓ·͢ w 4MBDLࣗମ4MBTI$PNNBOE#PUͷNFOUJPOʹΑΔԠͳͲ༷ʑ ͳํͰରԠͰ͖·͢ w 4MBDLͷ35."1*Λ༻ w
(PͷOMPQFTTMBDLNPEVMFΛ༻
࠷খ$PEF package gcf_slack_sample import ( "net/http" "os" "strings" "github.com/nlopes/slack" )
var ( threadTs slack.RTMsgOption ) type SlackParams struct { accessToken string botUserID string rtm *slack.RTM } func PostMessage(w http.ResponseWriter, r *http.Request) { // Ҿ০ΓɻCloud Functionͷhttp trigger Ͱඞཁ params := SlackParams{ accessToken: os.Getenv("ACCESS_TOKEN"), botUserID: "", } api := slack.New(params.accessToken) params.rtm = api.NewRTM() go params.rtm.ManageConnection() go func() { for msg := range params.rtm.IncomingEvents { switch ev := msg.Data.(type) { case *slack.ConnectedEvent: params.botUserID = ev.Info.User.ID case *slack.MessageEvent: if !strings.Contains(ev.Msg.Text, params.botUserID) { continue } threadTs = slack.RTMsgOptionTS(ev.ThreadTimestamp) params.rtm.SendMessage(params.rtm.NewOutgoingMessage("Sample TEST", ev.Channel, threadTs)) } } }() ࣮͜Ε͚ͩͰɺຊ ͷʮ4MBDLͷ5ISFBEʹ ରԠͨ͠#PUPO $MPVE'VODUJPOTΛ(P Ͱ࡞Δʯ͜ͱՄೳ WBSTZBNMߦ͚ͩ$SFEFOUJBMཧ Ͱผ్͋Γ·͢ɻޙ΄Ͳઆ໌ HPNPEVMFTͷTFUVQͷઆ໌ল͖ ·͢
தͷઆ໌
FOEQPJOUؔ w (PPHMF$MPVE'VODUJPOTͷ༷ ͰɺNBJOؔҎ֎͕ඞཁʹͳΓ· ͢ɻ w ྫͰɺ1PTU.FTTBHF w Ͳ͔͜Β։࢝͞ΕΔ͔Θ͔Γ͍͢Α
͏ʹNBJOHPGVODUJPOHPͱ͍͏ pMF໊ʹͯ͠ҎԼͷΑ͏ʹ։࢝͢Δؔ Λ࡞Γ·͢ package gcf_slack_sample // <= ࣮ԿͰok // ..<snip> func PostMessage(w http.ResponseWriter, r *http.Request) { // Ҿ০ΓɻCloud Functionͷhttp trigger Ͱඞཁ params := SlackParams{ accessToken: os.Getenv("ACCESS_TOKEN"), botUserID: "", }
4MBDLͷ5ISFBEରԠ w TMBDL35.TH0QUJPO w ͜Εޙʹઆ໌͢Δ35.TH0QUJPO54 FW5ISFBE5JNFTUBNQ ʹؔ͠ ·͢ɻ var (
threadTs slack.RTMsgOption )
4MBDLͷ5ISFBEରԠ ҎԼ͕4MBDLͷ5ISFBEͰͦͷ࣌ʹऔಘ͞ΕΔ5ISFBE5JNF4UBNQΛ࣋ͪ· ͢ ͜ͷ5ISFBE5JNF4UBNQΛར༻͢Δ͜ͱͰ#PU͕4MBDLͷ5ISFBEʹରԠ͢ ΔΑ͏ʹͳΓ·͢ threadTs = slack.RTMsgOptionTS(ev.ThreadTimestamp)
4MBDLͷ5ISFBEରԠ 35.TH0QUJPO54 FW5ISFBE5JNFTUBNQ ͱԿͳͷ͔ go func() { for msg :=
range s.rtm.IncomingEvents { switch ev := msg.Data.(type) { ͜ͷFWɺͦͷલͷ35.ͷ*ODPNJOH&WFOUT͔Β&WFOUUZQF͝ͱʹTXJUDI͠ɺͦͷ&WFOUEBUBΛFWʹೖΕ͍ͯ·͢ case *slack.MessageEvent: // .. <snip> threadTs = slack.RTMsgOptionTS(ev.ThreadTimestamp) .FTTBHF&WFOUΛड͚औͬͨλΠϛϯάͰɺͦͷૹ৴ݩͷTMBDLͷUISFBEʹରԠ͢ΔͨΊʹ ͦͷ࣌ͷ5ISFBE5JNF4UBNQΛ༻͠·͢ ͢ͳΘͪɺ͜ͷ.FTTBHF&WFOU͕࢝·ͬͨ࣌ͷ5ISFBE5JNFTUBNQ͕ೖΓ·͢ɻ
OMPQFTTMBDLଆͷྲྀΕ ϖʔδͷ্ؔɺOMPQFTTMBDLଆͷઆ໌ׂѪ͠·͕͢ྲྀΕ͚ͩॻ͘ͱҎԼͰ͢ɻ 35.TH0QUJPO54 Ͱɺ.FTTBHF&WFOUΛड͚औͬͨͱ͖ͷ5ISFBE5NFTUBNQΛૹΔ 0VUHPJOH.FTTBBHF\5ISFBE5JNFTUBNQUISFBE5JNFTUBNQ^ʹઃఆ͞ΕΔ 35.TH0QUJPOܕͰฦ͢ 1BDLBHFWBSJBCMFͰࢦఆͨ͠มUISFBE5Tɺͦͷ35.TH0QUJPOܕͱͳΔ IUUQTHJUIVCDPNOMPQFTTMBDLCMPCFBFDEFFCDEEGD
NFTTBHFTHP--
ड͚औͬͨ5ISFBE5JNF4UBNQΛ͏ s.rtm.NewOutgoingMessage() ͜ͷؔɺTMBDL35.ͰҎԼͷΑ͏ʹఆٛ͞Ε͍ͯ·͢ɻ func (rtm *RTM) NewOutgoingMessage(text string, channelID string,
options ...RTMsgOption) *OutgoingMessage { // ..<snip> return &msg 4MBDLͰ#PU͕͢.FTTBHFΛೖΕΔؔ
ड͚औͬͨ5ISFBE5JNF4UBNQΛ͏ ҎԼͰUISFBE5JNF4UBNQΛ0QUJPOͰࢦఆ͢Εྑ͍Θ͚Ͱ͢ɻ s.rtm.NewOutgoingMessage(message, ev.Channel, threadTs)
ड͚औͬͨ5ISFBE5JNF4UBNQΛ͏ s.rtm.SendMessage(s.rtm.NewOutgoingMessage(message, ev.Channel, threadTs)) ࣮ࡍʹ.FTTBHFΛૹΔͨΊʹҎԼͷΑ͏ʹ͠·͢ɻ
͜ΕΛ$MPVE'VODUJPOTʹͤ ͯ4MBDLCPUͱͯ͠ొ͢Δ
4MBDLͰઃఆ 4MBDL"QQͷ࡞ɺొ͔Βɻ wิ w֤छͷઆ໌ʹ͍ͭͯҎԼ͕Θ͔Γ͍͢Ͱ͢ wIUUQTRJJUBDPNOBNVUBLBJUFNT BDBG IUUQTBQJTMBDLDPNBQQTɹΛ։͖·͢
4MBDLͰઃఆ $SFBUF/FX"QQTΛ։ ͍ͯ࡞Λ։࢝͠·͢ ͜͜ͰUFTUCPUͱ͍͏໊ લͰొ͠·͢ %FWFMPQNFOU4MBDL 8PSLTQBDFΛબ͠·͢
4MBDLͰઃఆ #PU6TFSTΛΫϦοΫ͠ ͯɺ"EEB#PUVTFSΛΫ ϦοΫ %JTQMBZOBNFͱ%FGBVMU VTFSOBNFͰɺͲͷΑ͏ ͳจࣈͰϋΠϑϯແ͠ ʹม͞ΕΔ
ϋΠϑϯ͕ඞཁͩͬͨΒՃ͍ͯͩ͘͠͞ VTFSOBNFจࣈ·Ͱͷ੍ݶ͕͋Γ· ͢ɻ
4MBDLͰઃఆ 4DPQFTʹ DIBUXSJUFCPUΛՃ͢Δ 4BWF$IBOHFTͰอଘ ಉ͡ϖʔδͷҰ൪্ʹ͋Δ
A*OTUBMMBQQUPXPSLTQBDFAΛ ΫϦοΫͯ͠"VUIPSJ[FE͢Δɻ 0BVUI1FSNJTTJPOTઃఆ
4MBDLͰઃఆ #PU6TFS0"VUI"DDFTT5PLFOΛऔ ಘͯ͠ɺWBSTZBNMʹॻ͘ 0BVUI1FSNJTTJPOTઃఆ ACCESS_TOKEN: xoxb-XXXXXXXXXXXXXXXXXXXX WBSTZBNM HJUJHOPSFʹೖΕ͓͖ͯ·͢
(PPHMF$MPVE'VODUJPOTʹEFQMPZ HDMPVEGVODUJPOTEFQMPZUFTUCPUa FOUSZQPJOU1PTU.FTTBHFa SVOUJNFHPa FOWWBSTpMFWBSTZBNMa USJHHFSIUUQ
(PPHMF$MPVE'VODUJPOTʹEFQMPZ ͠Βͭ͘ͱEFQMPZ͕ྃ͠·͢ɻ IUUQT5SJHHFS VSMIUUQTSFHJPOQSPKFDUDMPVEGVODUJPOTOFUUFTUCPU TUBUVT"$5*7& ͷΑ͏ͳIUUQT5SJHHFS͕ൃߦ͞Ε·͢ͷͰɺ͜ΕΛΫϦοΫ͠·͢ɻ
͜Ε͚ͩͰྃͰ͢ TMBDLͷDIBOOFMʹ#PUΛ*OWJUF͠·͢ɻ
#PUΛݺͼग़͢
#PUΛݺͼग़͢ 5ISFBEʹ#PUͷ .FOUJPOΛඈ͢ͱͦͷ 5ISFBEʹରԠ͍ͯ͠· ͢ɻ ·ͨɺ5ISFBEҎ֎ʹ ͦͷDIBOOFMʹਖ਼֬ʹ #PU͕ԠΛฦ͍ͤͯ· ͢ɻ
ิ w ͪΖΜࠓճ-5Ͱઆ໌༻Ͱۃʹͨ͘͠$PEFͰ͢ w ࣮ࡍʹ͏ͱ͖ظӡ༻Λߟ͑ͯॺ໊ͳΜ͔͚ͭΔͱྑ͍ͱࢥ͍·͢ w 4JHOJOHTFDSFU
·ͱΊ w 4MBDLCPUͷԼ४උΛ(PͰ؆୯ʹग़དྷΔ w 5ISFBEରԠɺ TMBDL35.TH0QUJPO54 FW5ISFBE5JNFTUBNQ Λऔಘͯ͠͏ ͚ͩ w
4MBDLCPU (P $MPVE'VODUJPOTͷ૬ੑѱ͘ͳ͍ w ࡞Γ͍͢ ֦ுੑ͕͋Δ The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/)
࠷ޙʹ IUUQTHJUIVCDPNLPHVNBHDGMFBTUTMBDLTBNQMFGPS-5
͝੩ௌ͋Γ͕ͱ͏͍͟͝·͠ ͨɻ