-
Notifications
You must be signed in to change notification settings - Fork 1
/
teambot.py
150 lines (113 loc) · 3.96 KB
/
teambot.py
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# -*- coding: utf-8 -*-
import os
import random
import sys
from logging import INFO, Formatter, StreamHandler, getLogger
from logging.handlers import SYSLOG_UDP_PORT, SysLogHandler
import discord
from discord.ext import commands
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix='*',
description="shika bot",
intents=intents)
# Logger
simpleFormatter = Formatter("[%(levelname)s] %(message)s")
consoleHandler = StreamHandler(sys.stdout)
consoleHandler.setFormatter(simpleFormatter)
syslogHandler = SysLogHandler(address=('localhost', SYSLOG_UDP_PORT))
syslogHandler.setFormatter(simpleFormatter)
LOGGER = getLogger(__file__)
LOGGER.setLevel(INFO)
LOGGER.addHandler(consoleHandler)
LOGGER.addHandler(syslogHandler)
def team_alloc(members: list, alloc_size: int) -> list:
u"""指定の割り当てサイズに近い人数で均等にチーム分配する
Args:
members: 参加者リスト
alloc_size: 1チーム当たりの人数
Returns:
均等に分配されたチームのリスト
"""
total = len(members)
if total % alloc_size == 0:
# 割り切れる場合
# チーム数=人数 / 割り当てサイズ
teams = total // alloc_size
else:
# 余る場合
# チーム数=人数 / 割り当てサイズ + 1
teams = total // alloc_size + 1
# 各チームの人数リスト
sizes = [(total + i) // teams for i in range(teams)]
# シャッフル
random.shuffle(members)
members_iter = iter(members)
# 割り振り
result = []
for i, s in enumerate(sizes):
team = []
for _ in range(s):
m = next(members_iter)
team.append(m)
result.append(team)
return result
def team_to_string(teams) -> str:
u"""チームのリストを表す2次元リストの文字列表現を取得する
Args:
teams: チームのリストを表す2次元リスト
Returns:
文字列表現
"""
result = ""
for i, t in enumerate(teams):
members = ""
for m in t:
if members:
members += ", "
members += m.nick or m.name
result += u"[Team {0}] {1}\n".format(i + 1, members)
return result
async def proc_alloc_command(ctx: commands.Context, alloc_size: int):
u"""チーム割り振りコマンドを処理し、返答する。
Args:
ctx: commands.Context オブジェクト
alloc_size: 1チームあたりの人数
"""
# 発言者のVCにいるメンバーリスト
members = ctx.author.voice.channel.members
# 簡易テスト用
# members = list(m for m in ctx.message.guild.members if m != bot.user)
# チーム分け
result = team_alloc(members, alloc_size)
# 返答
reply = team_to_string(result)
await ctx.channel.send(reply)
@bot.event
async def on_ready():
LOGGER.info("Logged in as {0.name}#{0.id}".format(bot.user))
@bot.command(pass_context=True)
async def duo(ctx: commands.Context):
u"""1チームあたり2人に近くなるよう均等にチーム分けする
"""
await proc_alloc_command(ctx, 2)
@bot.command(pass_context=True, aliases=["sq"])
async def squad(ctx: commands.Context):
u"""1チームあたり4人に近くなるよう均等にチーム分けする
"""
await proc_alloc_command(ctx, 4)
@bot.command(pass_context=True)
async def team(ctx: commands.Context, alloc_size: int):
u"""指定人数に近くなるよう均等にチーム分けする
"""
await proc_alloc_command(ctx, alloc_size)
@bot.command(pass_context=True)
async def dice(ctx: commands.Context, dimen: int = 6):
u"""1から指定数値までのダイスを振る
"""
num = random.randint(1, dimen)
await ctx.channel.send("{0.mention} {1}".format(ctx.message.author, num))
def main():
bot.run(os.environ.get("BOT_TOKEN"))
if __name__ == '__main__':
main()