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
Discord botにScrumの Discord botにScrumの手伝いをしてもらう手...
Search
Takashi Makino
February 26, 2021
Programming
430
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Discord botにScrumの Discord botにScrumの手伝いをしてもらう手伝いをしてもらう
使った技術
- discord.py
- gspread
- Backlog API
Takashi Makino
February 26, 2021
More Decks by Takashi Makino
See All by Takashi Makino
あなたの知らないスクラムの世界
makky0620
0
110
Flutterでもテスト駆動したい
makky0620
0
380
A_アルゴリズム高速化を目指して
makky0620
0
1.5k
Other Decks in Programming
See All in Programming
霧の中の代数的エフェクト
funnyycat
1
420
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
330
【やさしく解説 設計編 #1】「ドメイン駆動」と「実装駆動」ってなに? 〜設計の考え方を、たとえ話で学ぼう〜
panda728
PRO
1
120
AI時代、エンジニアはどう育つのか -未経験エンジニアの成長を間近で見て考えたこと-
thasu0123
0
140
Terraform標準の組織で AWS CDKをどう使うか
mu7889yoon
1
350
SLOをサービス品質の共通言語にするために 取り組んできたこと
wakana0222
0
540
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
350
琵琶湖の水は止められてもNet--HTTPのリトライは止められない / You might be able to stop the water flow of Lake Biwa but you can't stop Net::HTTP retries
luccafort
PRO
0
430
Prismを使った型安全な暗号化_関数型まつり2026
_fhhmm
0
150
PHP初心者セッション2026 〜生成AIでは見えない裏側を知る:今だからLAMPを通して仕組みを学ぶ〜
kashioka
0
640
Apache Hive: そしてCloud Native Lakehouseへ
okumin
1
160
Claude Opus 4.6以後の受託開発エンジニアの変化(Claude Code開発ノウハウ大公開スペシャルbyクラスメソッド)
iidatakuma
1
840
Featured
See All Featured
The World Runs on Bad Software
bkeepers
PRO
72
12k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.7k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
SEO for Brand Visibility & Recognition
aleyda
0
4.6k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
270
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Accessibility Awareness
sabderemane
1
160
Automating Front-end Workflow
addyosmani
1370
210k
Making the Leap to Tech Lead
cromwellryan
135
10k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
880
Thoughts on Productivity
jonyablonski
76
5.3k
The Cult of Friendly URLs
andyhume
79
7k
Transcript
Discord botにScrumの 手伝いをしてもらう Makino Tommy Takashi @TechBash
ストーリーポイントを Backlogに反映 ベロシティの計算と記録 ベロシティの可視化 やったこと
discord.py discord gspread Backlog API 使ったものたち(概要)
使ったものたち(パッケージなど) • discord.py:discordを操作するやつ • gspread:スプレッドシートを操作するやつ • requests:httpリクエストを送るやつ • pandas:表や時系列データを操作しやすいやつ •
matplotlib:グラフとか作るやつ • oauth2client:Google APIの認証周りをやってくれるやつ • PyYAML:yamlを操作するやつ [補足] • heroku:デプロイする場所として使ったやつ • poetry:pythonプロジェクトを管理するやつ
なぜやろうと思ったのか 背景 • 私のプロジェクトはスクラム(スクラムマスターいないけど…)をしている • プロダクトバックログはSpread SheetでスプリントバックログはBacklogで管理 • ベロシティの計測周りが手作業だった •
最近はちゃんとチェックしなくなっていた →自動でやってくれたらいいなぁ+みんな見てくれるかなぁ
Discord.py Cogが便利 よくある書き方 with event import discord token = ‘token’
client = discord.Client() @client.event async def on_ready(): print(‘botがログインしました ’) @client.event async def on_message(msg): if (msg.content == ‘!ping’): await msg.channel.send(‘pong!!’) client.run(TOKEN) pros - 手っ取り早くかける cons - 新たなコマンドを増やしたいときは on_message()内の条件分岐を 増やしていく →どんどん増えて煩雑になる
Discord.py Cogが便利 よくある書き方 with command from discord.ext import commands token
= ‘token’ bot = commands.Bot(command_prefix=’!’) “”” ctx: Context 呼び出しについてのコンテキストのメタデータが含まれている e.g. チャンネル, 送信者など “”” @client.event async def on_ready(): print(‘botがログインしました ’) @client.command async def ping(ctx): await ctx.send(‘pong!!’) bot.run(TOKEN) pros - 条件でなく関数名でコマンドが表現で きる cons - コマンドを意味のまとまりに分けること ができない e.g.: - 挨拶系:ping, hello - 時間系:timer, reminder
Discord.py Cogが便利 よくある書き方 with Cog from discord.ext import commands from
greeting import Greeting from timer import Timer token = ‘token’ client = commands.Bot(command_prefix=’!’) @client.event async def on_ready(): print(‘botがログインしました ’) client.add_cog(Greeting(client)) client.add_cog(Timer(client)) client.run(TOKEN) # greeting.py from discord.ext import commands class Greeting(commands.Cog): def __init__(self, bot): self.bot = bot @commands.commands async def ping(self, ctx): await ctx.send(‘pong’) @commands.commands async def hello(self, ctx): await ctx.send(‘world’) # timer.py from discord.ext import commands class Timer(commands.Cog): def __init__(self, bot): self.bot = bot @commands.commands async def timer(self, ctx): # TODO @commands.commands async def reminder(self, ctx): # TODO コマンドを意味のまとまりに分けることができる!
そんなこんなでのファイル構成 root |- main.py |- cog | |- scrum_master_cog.py |-
service | |- scrum_master_service.py | |- backlog_service.py | |- discord_service.py | |- sheet_service.py |- repository |- backlog_repository.py |- sheet_repository.py ここでCogを定義する scrum_master_cogで呼ぶメソッドたち undoneの課題一覧の取得、milestone情報の取得など discordに返すための値を作成など spreadsheetの更新など
gspread (Sheets API)とpandasの相性が良い pandasの便利なところ import pandas as pd import maplotlib.pyplot
as plt # 読み込み df = pd.read_csv(‘velocity.py’) # 絞り込み df = df[df.total >= 30] # -> totalが30以上の行が抽出できる # 図を作成 df.plot(x=’sprint’, y=’total’) # -> 横軸sprint, 縦軸totalの折れ線グラフができる # 統計値を計算 df.describe() “”” 要素数, 最頻値, 平均, 標準偏差, 最小値, 最大値, 中央値などが計算され る “”” sprint start end jack cocoa total 140 2020-07-02 2020-07-08 5 8 13 141 2020-07-09 2020-07-15 14 40 54 142 2020-07-16 2020-07-29 7 8 15 143 2020-07-30 2020-08-05 5 8 13 144 2020-08-06 2020-08-12 5 7 12 145 2020-08-13 2020-08-19 0 35 35 146 2020-08-20 2020-08-26 18 0 18 147 2020-08-27 2020-09-02 2 21 23 148 2020-09-03 2020-09-09 26 26 52 149 2020-09-10 2020-09-16 6 24 30 150 2020-09-17 2020-09-30 16 13 29 velocity.csv
sprint start end jack cocoa total 140 2020-07-02 2020-07-08 5
8 13 141 2020-07-09 2020-07-15 14 40 54 142 2020-07-16 2020-07-29 7 8 15 143 2020-07-30 2020-08-05 5 8 13 144 2020-08-06 2020-08-12 5 7 12 145 2020-08-13 2020-08-19 0 35 35 146 2020-08-20 2020-08-26 18 0 18 147 2020-08-27 2020-09-02 2 21 23 148 2020-09-03 2020-09-09 26 26 52 149 2020-09-10 2020-09-16 6 24 30 150 2020-09-17 2020-09-30 16 13 29 gspread (Sheets API)とpandasの相性が良い spreadsheetをpandasのDataFrameとして扱える velocity spreadsheet import gspread import pandas as pd # 認証部分は省略 # 読み込み sheet = gspread_client.open(‘velocity spreadsheet’).sheet1 df = pd.DataFrame(sheet.get_all_values()) csvを扱う時と同じ処理ができる ※numpyとして読み込むことも可能
Backlog APIのいけてないところ - 課題一覧取得 - マイルストーンの条件が当てはまらない場合は、全ての結果が返ってくる - マイルストーン一覧の取得 - マイルストーン単体で調べる
API がない - 一覧取得の際に名前でフィルターできない 今度もうちょっとまとめます
余談:設定値をyamlで管理しておいた discord: token: discord token scrum-master: channel-ids: [どこかのトピックのid, どこかのトピックのid] backlog:
api-key: BacklogのAPIキー base-url: BacklogのBase URL sheet: credentials: ./code/configs/credential.json product-backlog: バックログ用のスプレッドシートの名前 velocity: ベロシティを保存するようのスプレッドシートの名前