Chatchart changes

Top 20 instead of 15, match v2 style changes, channel targeted can now be specified, messages fetched can now be specified.
This commit is contained in:
aikaterna
2018-05-13 09:19:16 -07:00
parent d06271fe04
commit 519d46dfaa

View File

@@ -20,64 +20,80 @@ class Chatchart:
def __init__(self, bot):
self.bot = bot
def create_chart(self, top, others):
def create_chart(self, top, others, channel):
plt.clf()
sizes = [x[1] for x in top]
labels = ["{} {:g}%".format(x[0], x[1]) for x in top]
if len(top) >= 15:
if len(top) >= 20:
sizes = sizes + [others]
labels = labels + ["Others {:g}%".format(others)]
title = plt.title('User activity in the last 5000 messages')
if len(channel.name) >= 19:
channel_name = '{}...'.format(channel.name[:19])
else:
channel_name = channel.name
title = plt.title("Stats in #{}".format(channel_name), color="white")
title.set_va("top")
title.set_ha("left")
title.set_ha("center")
plt.gca().axis("equal")
colors = ['r', 'darkorange', 'gold', 'y', 'olivedrab', 'green', 'darkcyan', 'mediumblue', 'darkblue', 'blueviolet', 'indigo', 'orchid', 'mediumvioletred', 'crimson', 'chocolate', 'gray']
colors = ['r', 'darkorange', 'gold', 'y', 'olivedrab', 'green', 'darkcyan', 'mediumblue', 'darkblue', 'blueviolet', 'indigo', 'orchid', 'mediumvioletred', 'crimson', 'chocolate', 'yellow', 'limegreen','forestgreen','dodgerblue','slateblue','gray']
pie = plt.pie(sizes, colors=colors, startangle=0)
plt.legend(pie[0], labels, bbox_to_anchor=(0.7, 0.45), loc="center", fontsize=10,
bbox_transform=plt.gcf().transFigure)
plt.legend(pie[0], labels, bbox_to_anchor=(0.7, 0.5), loc="center", fontsize=10,
bbox_transform=plt.gcf().transFigure, facecolor='#ffffff')
plt.subplots_adjust(left=0.0, bottom=0.1, right=0.45)
image_object = BytesIO()
plt.savefig(image_object, format='PNG')
plt.savefig(image_object, format='PNG', facecolor='#36393E')
image_object.seek(0)
return image_object
@commands.command(pass_context=True)
@commands.command()
@commands.cooldown(1, 10, commands.BucketType.channel)
async def chatchart(self, ctx):
async def chatchart(self, ctx, channel: discord.TextChannel=None, messages=5000):
"""
Generates a pie chart, representing the last 5000 messages in this channel.
Generates a pie chart, representing the last 5000 messages in the specified channel.
"""
channel = ctx.message.channel
e = discord.Embed(description="Loading...", colour=ctx.guild.me.top_role.colour)
e = discord.Embed(description="Loading...", colour=0x00ccff)
e.set_thumbnail(url="https://i.imgur.com/vSp4xRk.gif")
em = await ctx.send(embed=e)
channel_history = []
async for msg in channel.history(limit=5000):
channel_history.append(msg)
if channel is None:
channel = ctx.message.channel
history = []
if not channel.permissions_for(ctx.message.author).read_messages == True:
await self.bot.delete_message(em)
return await ctx.send("You're not allowed to access that channel.")
try:
async for msg in channel.history(limit=messages):
history.append(msg)
except discord.errors.Forbidden:
await self.bot.delete_message(em)
return await ctx.send("No permissions to read that channel.")
msg_data = {'total count': 0, 'users': {}}
for msg in channel_history:
for msg in history:
if len(msg.author.name) >= 20:
short_name = '{}...'.format(msg.author.name[:20])
else:
short_name = msg.author.name
whole_name = '{}#{}'.format(short_name, msg.author.discriminator)
if msg.author.bot:
pass
elif msg.author.name in msg_data['users']:
msg_data['users'][msg.author.name]['msgcount'] += 1
elif whole_name in msg_data['users']:
msg_data['users'][whole_name]['msgcount'] += 1
msg_data['total count'] += 1
else:
msg_data['users'][msg.author.name] = {}
msg_data['users'][msg.author.name]['msgcount'] = 1
msg_data['users'][whole_name] = {}
msg_data['users'][whole_name]['msgcount'] = 1
msg_data['total count'] += 1
for usr in msg_data['users']:
pd = float(msg_data['users'][usr]['msgcount']) / float(msg_data['total count'])
msg_data['users'][usr]['percent'] = round(pd * 100, 1)
top_ten = heapq.nlargest(15, [(x, msg_data['users'][x][y])
top_ten = heapq.nlargest(20, [(x, msg_data['users'][x][y])
for x in msg_data['users']
for y in msg_data['users'][x]
if y == 'percent'], key=lambda x: x[1])
others = 100 - sum(x[1] for x in top_ten)
img = self.create_chart(top_ten, others)
img = self.create_chart(top_ten, others, channel)
await em.delete()
await channel.send(file=discord.File(img, 'chart.png'))
await ctx.message.channel.send(file=discord.File(img, 'chart.png'))