2023-05-15 23:22:19 +03:00
from utils.translate import get_text
2023-05-03 19:53:01 +03:00
from time import time
import typing
import discord
import schedule
2023-05-09 21:05:24 +03:00
from os import remove
2023-05-03 19:53:01 +03:00
from bot import db
from loguru import logger
from random import randint as rint
from discord import app_commands
from discord.ext import commands , tasks
from discord.app_commands import Choice
from datetime import datetime
2023-05-10 01:51:45 +03:00
from matplotlib import ticker
2023-05-03 19:53:01 +03:00
from matplotlib import pyplot as plt
2023-05-15 17:29:09 +03:00
from utils.emojis import chocolate
2023-05-03 19:53:01 +03:00
class Economic ( commands . Cog , name = "Экономика" ):
def __init__ ( self , bot ):
self . bot = bot
plt . style . use ([ 'default' , "dark.mplstyle" ])
def time_translation ( self , secs ):
def two_digit ( number ):
if len ( str ( number )) == 1 :
return '0' + str ( number )
return number
time = f " { secs } s "
if 60 <= secs < 60 * 60 :
time = f " { secs // 60 } : { two_digit ( secs % 60 ) } "
elif 60 * 60 <= secs < 24 * 60 * 60 :
time = f " { secs // 60 // 60 } : { two_digit ( secs // 60 % 60 ) } : { two_digit ( secs % 60 ) } "
elif 24 * 60 * 60 <= secs :
time = f " { secs // 60 // 60 // 24 } d { two_digit ( secs // 60 // 60 % 24 ) } : { two_digit ( secs // 60 % 60 ) } : { two_digit ( secs % 60 ) } "
return time
def exp_translation ( self , exp ):
if exp < 1000 :
return exp
if exp < 1000000 :
exp /= 1000
if exp . is_integer ():
return str ( int ( exp )) + 'k'
return " %.1f k" % exp
@commands.Cog.listener ()
async def on_message ( self , message ):
if not message . author . bot and message . guild is not None and not message . content . startswith ( tuple ( await self . bot . command_prefix ( self . bot , message ))):
2023-05-16 16:34:50 +03:00
data = await db . members . find_one ({ "id" : message . author . id })
2023-05-18 22:54:43 +03:00
flood_channels = await db . guild_settings . find_one ({ "id" : message . guild . id , 'type' : 'general' })
2023-05-03 19:53:01 +03:00
if flood_channels is None :
flood_channels = []
else :
flood_channels = flood_channels [ 'flood_channels' ]
if time () - 3 >= data [ "last_mess_time" ] and message . channel . id not in flood_channels :
delta_exp = len ( message . content ) + len ( message . attachments ) * 100
2023-05-16 16:34:50 +03:00
await db . history . update_one (
2023-05-03 19:53:01 +03:00
{ 'type' : 'server' , 'id' : message . guild . id },
{ '$inc' : { f 'current. { datetime . now () . hour } ' : delta_exp }}
)
if message . author . voice is not None :
2023-05-11 17:57:08 +03:00
delta_exp //= 10
2023-05-03 19:53:01 +03:00
delta_money = rint ( 1 , 5 )
# Глобальные опыт/уроень
2023-05-16 16:34:50 +03:00
await db . members . update_one ({ "id" : message . author . id },
2023-05-11 17:57:08 +03:00
{ "$inc" : { "exp" : delta_exp }}) # Изменяем exp
2023-05-16 16:34:50 +03:00
data = await db . members . find_one ({ "id" : message . author . id })
2023-05-03 19:53:01 +03:00
if data is not None :
level = data [ "level" ]
if level ** 2 * 50 + 5 <= data [ "exp" ]:
2023-05-16 16:34:50 +03:00
await db . members . update_one ({ "id" : message . author . id },
2023-05-11 17:57:08 +03:00
{ "$inc" : { "level" : 1 }}) # Изменяем level
2023-05-03 19:53:01 +03:00
if data [ "level" ] + 1 >= data [ "max_level" ]:
2023-05-16 16:34:50 +03:00
await db . members . update_one ({ "id" : message . author . id },
2023-05-11 17:57:08 +03:00
{ "$inc" : { "money" : ( level + 1 ) * delta_money }}) # Изменяем money
2023-05-03 19:53:01 +03:00
# Локальные опыт/уровень
prefix = f "guild_stat. { message . guild . id } "
2023-05-16 16:34:50 +03:00
if ( await db . members . find_one ({ "id" : message . author . id , f 'guild_stat. { message . guild . id } ' : { '$exists' : 0 }})):
await db . members . update_many ({ "id" : message . author . id },
2023-05-11 17:57:08 +03:00
{ "$set" : {
f " { prefix } .exp" : 0 ,
f " { prefix } .level" : 0 ,
f " { prefix } .secs_in_voice" : 0 ,
f " { prefix } .history" : {
"hour" : {},
"day" : {},
"siv_h" : {},
"siv_d" : {}
}
}}) # Создаем в guild_stat поле для сервера
2023-05-03 19:53:01 +03:00
2023-05-16 16:34:50 +03:00
data = ( await db . members . find_one ({ "id" : message . author . id }))[ "guild_stat" ][ str ( message . guild . id )]
await db . members . update_one ({ "id" : message . author . id },
2023-05-11 17:57:08 +03:00
{ "$inc" : { f " { prefix } .exp" : delta_exp }})
2023-05-16 16:34:50 +03:00
data = ( await db . members . find_one ({ "id" : message . author . id }))[ "guild_stat" ][ str ( message . guild . id )]
2023-05-03 19:53:01 +03:00
level = data [ "level" ]
if level ** 2 * 50 + 5 <= data [ "exp" ]:
2023-05-16 16:34:50 +03:00
await db . members . update_one ({ "id" : message . author . id },
2023-05-11 17:57:08 +03:00
{ "$inc" : { f " { prefix } .level" : 1 }})
2023-05-16 16:34:50 +03:00
data = await db . guild_settings . find_one ({ "id" : message . guild . id })
2023-05-11 12:21:24 +03:00
if data is not None and data [ 'levelup' ] == "send" :
await message . reply (
embed = discord . Embed (
title = "LEVEL UP" ,
description = f " { message . author . mention } достиг { level + 1 } уровня!"
),
delete_after = 10 ,
mention_author = False
)
2023-05-03 19:53:01 +03:00
2023-05-16 16:34:50 +03:00
await db . members . update_one ({ "id" : message . author . id }, { "$set" : { "last_mess_time" : time ()}})
2023-05-03 19:53:01 +03:00
@commands.Cog.listener ()
async def on_voice_state_update ( self , member , before , after ):
if not member . bot :
# При входе
if before . channel is None :
humans = list ( filter ( lambda x : not x . bot , after . channel . members ))
#logger.info(f"{member.name}#{member.discriminator} зашел. В канале теперь {len(humans)} человек")
if len ( humans ) == 1 : pass
elif len ( humans ) == 2 :
self . bot . voice_counter [ str ( humans [ 0 ] . id )] = datetime . now ()
self . bot . voice_counter [ str ( humans [ 1 ] . id )] = datetime . now ()
else :
self . bot . voice_counter [ str ( member . id )] = datetime . now ()
else :
humans = list ( filter ( lambda x : not x . bot , before . channel . members ))
if len ( humans ) == 1 :
2023-05-16 16:34:50 +03:00
await self . voice_register ( humans [ 0 ], before )
2023-05-03 19:53:01 +03:00
if len ( humans ) != 0 :
2023-05-16 16:34:50 +03:00
await self . voice_register ( member , before )
2023-05-03 19:53:01 +03:00
# При выходе
if after . channel is None :
try : del self . bot . voice_counter [ str ( member . id )]
2023-05-11 17:57:08 +03:00
except : pass
2023-05-03 19:53:01 +03:00
2023-05-16 16:34:50 +03:00
async def voice_register ( self , member , voice_state ):
2023-05-11 17:57:08 +03:00
if member . id in self . bot . voice_counter . keys ():
secs = ( datetime . now () - self . bot . voice_counter [ member . id ]) . seconds
else :
2023-05-03 19:53:01 +03:00
secs = 0
# TODO: Убрать нахуй эти ифы
if voice_state . self_deaf :
k = 0
elif voice_state . self_mute :
k = .5
else :
k = 1
if voice_state . self_deaf and ( voice_state . self_stream or voice_state . self_video ):
k = 0.1
elif voice_state . self_stream or voice_state . self_video :
k *= 2
exp = int ( secs // 5 * k )
money = exp * rint ( 1 , 5 )
2023-05-16 16:34:50 +03:00
await db . members . update_one ({ "id" : member . id }, {
2023-05-11 17:57:08 +03:00
"$inc" : {
f "guild_stat. { member . guild . id } .secs_in_voice" : secs ,
f "guild_stat. { member . guild . id } .exp" : exp ,
"exp" : exp ,
"money" : money
2023-05-03 19:53:01 +03:00
}})
2023-05-16 16:34:50 +03:00
await db . history . update_one (
2023-05-03 19:53:01 +03:00
{ 'type' : 'server' , 'id' : member . guild . id },
{ "$inc" : { f 'current. { datetime . now () . hour } ' : exp }}
)
2023-05-11 17:57:08 +03:00
self . bot . voice_counter [ member . id ] = datetime . now ()
2023-05-03 19:53:01 +03:00
logger . info (
f " { member . name } # { member . discriminator } \n "
f " \t Секунд: + { secs } \n "
f " \t Опыт: + { exp } \n "
f " \t Денег: + { money } "
)
@commands.Cog.listener ()
async def on_member_join ( self , member ):
2023-05-16 16:34:50 +03:00
member_data = await db . members . find_one ({ "id" : member . id })
2023-05-03 19:53:01 +03:00
if member_data is None :
logger . warning ( "Пользователь не найден" )
return
if str ( member . guild . id ) in member_data [ "guild_stat" ] . keys ():
logger . debug ( member_data [ "guild_stat" ][ str ( member . guild . id )][ "exp" ], end = " \t " )
2023-05-16 16:34:50 +03:00
await db . members . update_one (
2023-05-03 19:53:01 +03:00
{ "id" : member . id },
2023-05-11 17:57:08 +03:00
{ "$inc" : { "exp" : member_data [ "guild_stat" ][ str ( member . guild . id )][ "exp" ]}}
2023-05-03 19:53:01 +03:00
)
@commands.Cog.listener ()
async def on_member_remove ( self , member ):
2023-05-16 16:34:50 +03:00
member_data = await db . members . find_one ({ "id" : member . id })
2023-05-03 19:53:01 +03:00
if member_data is None :
logger . warning ( "Пользователь не найден" )
return
if str ( member . guild . id ) in member_data [ "guild_stat" ] . keys ():
logger . debug ( member_data [ "guild_stat" ][ str ( member . guild . id )][ "exp" ], end = " \t " )
2023-05-16 16:34:50 +03:00
await db . members . update_one (
2023-05-03 19:53:01 +03:00
{ "id" : member . id },
2023-05-11 17:57:08 +03:00
{ "$dec" : { "exp" : member_data [ "guild_stat" ][ str ( member . guild . id )][ "exp" ]}
2023-05-03 19:53:01 +03:00
})
@commands.Cog.listener ()
async def on_guild_join ( self , guild ):
2023-05-16 16:34:50 +03:00
async for m in db . members . find ({ f "guild_stat. { guild . id } " : { "$exists" : True }}):
2023-05-03 19:53:01 +03:00
logger . debug ( m [ "guild_stat" ][ str ( guild . id )][ "exp" ], end = " \t " )
2023-05-16 16:34:50 +03:00
await db . members . update_one (
2023-05-03 19:53:01 +03:00
{ "id" : m [ 'id' ]},
2023-05-11 17:57:08 +03:00
{ "$inc" : { "exp" : m [ "guild_stat" ][ str ( guild . id )][ "exp" ]}
2023-05-03 19:53:01 +03:00
})
logger . debug ( m [ "guild_stat" ][ str ( guild . id )][ "exp" ])
@commands.Cog.listener ()
async def on_guild_remove ( self , guild ):
2023-05-16 16:34:50 +03:00
async for m in db . members . find ({ f "guild_stat. { guild . id } " : { "$exists" : True }}):
2023-05-03 19:53:01 +03:00
logger . debug ( m [ "guild_stat" ][ str ( guild . id )][ "exp" ], end = " \t " )
2023-05-16 16:34:50 +03:00
await db . members . update_one (
2023-05-03 19:53:01 +03:00
{ "id" : m [ 'id' ]},
2023-05-11 17:57:08 +03:00
{ "$dec" : { "exp" : m [ "guild_stat" ][ str ( guild . id )][ "exp" ]}
2023-05-03 19:53:01 +03:00
})
logger . debug ( m [ "guild_stat" ][ str ( guild . id )][ "exp" ])
2023-05-18 22:54:43 +03:00
stat_gr = app_commands . Group ( name = "statistic" , description = "Some statistic" )
@stat_gr.command ( description = "View balance and level" )
2023-05-09 21:05:24 +03:00
async def rank ( self , inter : discord . Interaction , user : discord . Member = None ):
2023-05-03 19:53:01 +03:00
if user is None : user = inter . user
if self . bot . get_user ( user . id ) . bot :
2023-05-16 16:55:25 +03:00
await inter . response . send_message ( await get_text ( inter , "Bot hasn't experience" , "rank" ))
2023-05-03 19:53:01 +03:00
return
2023-05-16 16:34:50 +03:00
user_data = await db . members . find_one ({ "id" : user . id })
2023-05-09 17:26:12 +03:00
if user_data is None or str ( inter . guild . id ) not in user_data [ 'guild_stat' ] . keys ():
2023-05-03 19:53:01 +03:00
await inter . response . send_message ( "Об этом пользователе информации пока нет" )
return
if str ( user . id ) in self . bot . voice_counter . keys ():
prefix = f "guild_stat. { inter . guild . id } "
if str ( inter . guild . id ) not in user_data [ "guild_stat" ] . keys ():
2023-05-16 16:34:50 +03:00
await db . members . update_many (
2023-05-03 19:53:01 +03:00
{ "id" : user . id },
{ "$set" : {
f " { prefix } .exp" : 0 ,
f " { prefix } .level" : 0 ,
f " { prefix } .secs_in_voice" : 0 ,
f " { prefix } .history" : {
"hour" : {},
"day" : {}
}
}}
) # Создаем в guild_stat поле для сервера
2023-05-16 16:34:50 +03:00
await self . voice_register ( user , user . voice )
2023-05-03 19:53:01 +03:00
2023-05-16 16:34:50 +03:00
user_data = await db . members . find_one ({ "id" : user . id })
2023-05-03 19:53:01 +03:00
if user_data is None : return
if inter . guild is not None :
color = inter . guild . me . color
if color == discord . Color . default ():
color = discord . Color ( 0xaaffaa )
else :
color = discord . Color ( 0xaaffaa )
history = user_data [ 'history' ]
if len ( history [ 'hour' ]) >= 1 :
per_hour = user_data [ 'exp' ] - history [ 'hour' ][ list ( history [ 'hour' ] . keys ())[ - 1 ]]
else : per_hour = "???"
if len ( history [ 'hour' ]) >= 2 :
last_hour = history [ 'hour' ][ list ( history [ 'hour' ] . keys ())[ - 1 ]] - history [ 'hour' ][ list ( history [ 'hour' ] . keys ())[ - 2 ]]
else : last_hour = "???"
if len ( history [ 'day' ]) >= 1 :
per_day = user_data [ 'exp' ] - history [ 'day' ][ list ( history [ 'day' ] . keys ())[ - 1 ]]
else : per_day = "???"
if len ( history [ 'day' ]) >= 2 :
last_day = history [ 'day' ][ list ( history [ 'day' ] . keys ())[ - 1 ]] - history [ 'day' ][ list ( history [ 'day' ] . keys ())[ - 2 ]]
else : last_day = "???"
2023-05-16 16:55:25 +03:00
description = f " { await get_text ( inter , 'Money' , 'rank' ) } : { user_data [ 'money' ] }{ chocolate } \n\n " \
f "__ { await get_text ( inter , 'Global stats' , 'rank' ) } :__ \n " \
f " { await get_text ( inter , 'Level' , 'rank' ) } : { user_data [ 'level' ] } \n " \
f " { await get_text ( inter , 'Exp' , 'rank' ) } : { user_data [ 'exp' ] } / { user_data [ 'level' ] ** 2 * 50 + 5 } " \
2023-05-03 19:53:01 +03:00
f " ( { ( user_data [ 'level' ] ** 2 * 50 + 5 ) - user_data [ 'exp' ] } ) \n " \
2023-05-16 16:55:25 +03:00
f " { await get_text ( inter , 'Per hour' , 'rank' ) } : { per_hour } , { await get_text ( inter , 'per the past hour' , 'rank' ) } : { last_hour } \n " \
f " { await get_text ( inter , 'Per day' , 'rank' ) } : { per_day } , { await get_text ( inter , 'per the past day' , 'rank' ) } : { last_day } \n "
2023-05-03 19:53:01 +03:00
secs = user_data [ 'guild_stat' ][ str ( inter . guild . id )][ 'secs_in_voice' ]
if "guild_stat" in list ( user_data . keys ()):
if inter . guild is not None and str ( inter . guild . id ) in list ( user_data [ 'guild_stat' ] . keys ()):
2023-05-15 23:22:19 +03:00
description += f " \n __ { await get_text ( inter , 'rank' , 'On this guild' ) } :__ \n " \
2023-05-16 16:55:25 +03:00
f " { await get_text ( inter , 'Level' , 'rank' ) } : { user_data [ 'guild_stat' ][ str ( inter . guild . id )][ 'level' ] } \n " \
f " { await get_text ( inter , 'Exp' , 'rank' ) } : { user_data [ 'guild_stat' ][ str ( inter . guild . id )][ 'exp' ] } / " \
2023-05-03 19:53:01 +03:00
f " { user_data [ 'guild_stat' ][ str ( inter . guild . id )][ 'level' ] ** 2 * 50 + 5 } " \
f " ( { ( user_data [ 'guild_stat' ][ str ( inter . guild . id )][ 'level' ] ** 2 * 50 + 5 ) - user_data [ 'guild_stat' ][ str ( inter . guild . id )][ 'exp' ] } ) \n " \
2023-05-16 16:55:25 +03:00
f " { await get_text ( inter , 'Time in voice channels' , 'rank' ) } : { self . time_translation ( secs ) } "
2023-05-03 19:53:01 +03:00
2023-05-16 16:55:25 +03:00
e = discord . Embed ( title = f " { await get_text ( inter , 'Info about' , 'rank' ) } { self . bot . get_user ( user . id ) . name } " ,
2023-05-03 19:53:01 +03:00
description = description ,
color = color )
await inter . response . send_message ( embed = e )
2023-05-18 22:54:43 +03:00
@stat_gr.command ( description = "Top members of the guild" )
2023-05-03 19:53:01 +03:00
@app_commands.describe ( category = 'Category' )
@app_commands.choices ( category = [
Choice ( name = 'Balance' , value = "Баланс" ),
Choice ( name = 'Experience' , value = "Опыт" ),
Choice ( name = 'Time in voice channel' , value = "Время в войсе" )
])
# @logger.catch
2023-05-09 21:05:24 +03:00
async def top ( self , inter : discord . Interaction , category : Choice [ str ] = None ):
2023-05-09 17:26:12 +03:00
if category is None :
2023-05-03 19:53:01 +03:00
category = "Опыт"
else :
category = category . value
categories = {
'Уровень' : f "guild_stat. { inter . guild . id } .level" ,
'Баланс' : "money" ,
'Опыт' : f "guild_stat. { inter . guild . id } .exp" ,
'Время в войсе' : f "guild_stat. { inter . guild . id } .secs_in_voice"
}
if inter . guild is not None :
color = inter . guild . me . color
if color == discord . Color . default ():
color = discord . Color ( 0xaaffaa )
else :
color = discord . Color ( 0xaaffaa )
e = discord . Embed ( title = "Топ" , description = category , color = color )
2023-05-16 16:34:50 +03:00
data_ = await db . members . find ({ f "guild_stat. { inter . guild . id } " : { "$exists" : True }}) . sort ( categories [ category ], - 1 ) . to_list ( 10 )
2023-05-03 19:53:01 +03:00
2023-05-16 12:32:13 +03:00
if not data_ :
2023-05-16 16:55:25 +03:00
await inter . response . send_message ( await get_text ( inter , "Not enough data. Try later" , "rank" ))
2023-05-03 19:53:01 +03:00
return
2023-05-09 00:06:10 +03:00
l = min ( len ( data_ ), 10 )
2023-05-03 19:53:01 +03:00
MAX_COLONS = 25
if category == "Опыт" :
max_val = data_ [ 0 ][ "guild_stat" ][ str ( inter . guild . id )][ "exp" ]
elif category == "Время в войсе" :
max_val = data_ [ 0 ][ 'guild_stat' ][ str ( inter . guild . id )][ 'secs_in_voice' ]
elif category == "Баланс" :
max_val = data_ [ 0 ][ 'money' ]
2023-05-16 12:32:13 +03:00
max_val = max ( max_val , 1 )
2023-05-03 19:53:01 +03:00
for place in range ( l ):
m = data_ [ place ]
if 'level' not in m [ 'guild_stat' ][ str ( inter . guild . id )] . keys ():
2023-05-16 16:34:50 +03:00
await db . members . update_one (
2023-05-03 19:53:01 +03:00
{ 'id' : m [ 'id' ]},
{ '$set' : { f 'guild_stat. { inter . guild . id } .level' : 0 }}
)
m [ 'guild_stat' ][ str ( inter . guild . id )][ 'level' ] = 0
data = { "Уровень" : [ "Ур:" , m [ 'guild_stat' ][ str ( inter . guild . id )][ 'level' ]],
"Опыт" : [ "Опыт:" , self . exp_translation ( m [ 'guild_stat' ][ str ( inter . guild . id )][ "exp" ]), m [ 'guild_stat' ][ str ( inter . guild . id )][ "exp" ]],
"Время в войсе" : [ ":sound:" , self . time_translation ( m [ 'guild_stat' ][ str ( inter . guild . id )][ 'secs_in_voice' ]), m [ 'guild_stat' ][ str ( inter . guild . id )][ 'secs_in_voice' ]],
"Баланс" : [ ":moneybag:" , m [ "money" ], m [ "money" ]]
}
u = self . bot . get_user ( m [ 'id' ])
if u is None :
name = str ( place + 1 ) + '. ' + m [ "name" ]
else :
name = str ( place + 1 ) + '. ' + u . name + '#' + str ( u . discriminator )
e . add_field ( name = name ,
inline = False ,
value = f " { data [ category ][ 0 ] } { data [ category ][ 1 ] } | " +
" | " . join ([ f " { data [ k ][ 0 ] } { data [ k ][ 1 ] } " for k in data . keys () if k != category ]) +
" \n " + str ( int ( data [ category ][ 2 ] / max_val * 100 )) + '% ' +
"█" * int ( data [ category ][ 2 ] / max_val * MAX_COLONS ) +
2023-05-09 00:06:10 +03:00
"▌" * int (( data [ category ][ 2 ] / max_val * MAX_COLONS ) % 2 ))
2023-05-03 19:53:01 +03:00
await inter . response . send_message ( embed = e )
2023-05-18 22:54:43 +03:00
@stat_gr.command ( description = "Comparison of exp with other members" )
2023-05-03 19:53:01 +03:00
@app_commands.choices ( period = [
Choice ( name = 'Per the entire period' , value =- 1 ),
Choice ( name = 'Per month' , value = 24 * 30 ),
2023-05-10 01:51:45 +03:00
Choice ( name = 'Per week' , value = 24 * 7 ),
2023-05-03 19:53:01 +03:00
Choice ( name = 'Per day' , value = 24 )
])
2023-05-09 21:05:24 +03:00
async def dif_graph ( self , inter : discord . Interaction , user1 : discord . Member , user2 : discord . Member = None , period : Choice [ int ] = - 1 ):
2023-05-03 19:53:01 +03:00
if period != - 1 : period = period . value
ts = datetime . now () . timestamp ()
# if user1 is None: user1 = user2
user1 = user1 . id
if user2 is None :
user2 = inter . user . id
else :
user2 = user2 . id
if self . bot . get_user ( user1 ) . bot or self . bot . get_user ( user2 ) . bot :
await inter . response . send_message ( "У ботов нет опыта. Они всемогущи" )
return
db_ = db . members
2023-05-16 16:34:50 +03:00
info1 = await db_ . find_one ({ "id" : user1 })[ 'guild_stat' ][ str ( inter . guild . id )][ 'history' ][ 'hour' ]
info2 = await db_ . find_one ({ "id" : user2 })[ 'guild_stat' ][ str ( inter . guild . id )][ 'history' ][ 'hour' ]
info1 [ str ( int ( ts ))] = await db_ . find_one ({ "id" : user1 })[ 'guild_stat' ][ str ( inter . guild . id )][ 'exp' ]
info2 [ str ( int ( ts ))] = await db_ . find_one ({ "id" : user2 })[ 'guild_stat' ][ str ( inter . guild . id )][ 'exp' ]
2023-05-03 19:53:01 +03:00
if period == - 1 :
data1 = list ( info1 . values ())
data2 = list ( info2 . values ())
else :
data1 = [ info1 [ key ] for key in info1 . keys () if int ( key ) >= ts - period * 60 * 60 ]
data2 = [ info2 [ key ] for key in info2 . keys () if int ( key ) >= ts - period * 60 * 60 ]
fig , ax = plt . subplots ( figsize = ( 8 , 5 ))
ax . plot ( list ( map ( int , info1 . keys ()))[ - len ( data1 ):], data1 , marker = '.' , label = self . bot . get_user ( user1 ) . name )
ax . plot ( list ( map ( int , info2 . keys ()))[ - len ( data2 ):], data2 , marker = '.' , label = self . bot . get_user ( user2 ) . name )
# ax.plot([i for info1.keys()], data2, label="Разница")
ax . grid ( True )
ax . set_ylabel ( 'Опыт' )
ax . set_xlabel ( 'Время (ч)' )
ax . legend ( loc = 'upper left' )
2023-05-10 01:51:45 +03:00
ax . xaxis . set_major_formatter ( ticker . FuncFormatter ( lambda x , pos : datetime . fromtimestamp ( x ) . strftime ( ' %d .%m' )))
if period == 24 :
ax . xaxis . set_major_locator ( ticker . IndexLocator ( base = 60 * 60 * 5 , offset = 0 ))
ax . xaxis . set_major_formatter ( ticker . FuncFormatter ( lambda x , pos : datetime . fromtimestamp ( x ) . strftime ( '%Hh' )))
elif period == 24 * 7 :
ax . xaxis . set_major_locator ( ticker . IndexLocator ( base = 60 * 60 * 24 , offset = 0 ))
ax . xaxis . set_major_formatter ( ticker . FuncFormatter ( lambda x , pos : datetime . fromtimestamp ( x ) . strftime ( ' %d .%m' )))
else :
ax . xaxis . set_major_locator ( ticker . IndexLocator ( base = 60 * 60 * 24 * 7 , offset = 0 ))
ax . xaxis . set_minor_locator ( ticker . IndexLocator ( base = 60 * 60 * 24 , offset = 0 ))
ax . xaxis . set_minor_formatter ( ticker . FuncFormatter ( lambda x , pos : datetime . fromtimestamp ( x ) . strftime ( ' %d ' )))
2023-05-03 19:53:01 +03:00
ax . legend () . get_frame () . set_boxstyle ( 'Round' , pad = 0.2 , rounding_size = 1 )
ax . legend () . get_frame () . set_linewidth ( 0.0 )
ax . xaxis . set_ticks_position ( 'none' )
ax . yaxis . set_ticks_position ( 'none' )
ax . spines [ 'bottom' ] . set_visible ( False )
ax . spines [ 'top' ] . set_visible ( False )
ax . spines [ 'left' ] . set_color ( '#303030' )
ax . spines [ 'right' ] . set_color ( '#303030' )
2023-05-09 20:25:44 +03:00
fig . savefig ( f 'tmp/ { inter . id } .png' )
with open ( f 'tmp/ { inter . id } .png' , 'rb' ) as f :
2023-05-10 01:51:45 +03:00
await inter . response . send_message ( file = discord . File ( f ))
2023-05-09 21:05:24 +03:00
remove ( f 'tmp/ { inter . id } .png' )
2023-05-03 19:53:01 +03:00
2023-05-18 22:54:43 +03:00
@stat_gr.command ()
2023-05-09 17:26:12 +03:00
@app_commands.choices ( period = [
Choice ( name = 'Per the entire period' , value =- 1 ),
Choice ( name = 'Per month' , value = 24 * 30 ),
Choice ( name = 'Per week' , value = 24 * 7 ),
Choice ( name = 'Per day' , value = 24 )
])
2023-05-09 21:05:24 +03:00
async def top_graph ( self , inter : discord . Interaction , period : Choice [ int ] =- 1 ):
2023-05-09 17:26:12 +03:00
if period != - 1 : period = period . value
ts = datetime . now () . timestamp ()
db_mem = db . members
2023-05-16 16:34:50 +03:00
data = await db_mem . find ({ f "guild_stat. { inter . guild . id } " : { "$exists" : True }}) . sort ( f "guild_stat. { inter . guild . id } .exp" , - 1 ) . to_list ( 10 )
2023-05-09 17:26:12 +03:00
if not data :
await inter . response . send_message ( "Недостаточно данных. Попробуйте завтра" )
return
fig , ax = plt . subplots ( figsize = ( 8 , 5 ))
ax . grid ( True )
ax . set_ylabel ( 'Опыт' , color = ( 1. , 1. , 1. ))
ax . set_xlabel ( 'Время' , color = ( 1. , 1. , 1. ))
# ax.set_facecolor((.12, .12, .12))
marker = '.' if - 1 < period <= 24 else ''
for user in data :
info = user [ 'guild_stat' ][ str ( inter . guild . id )][ 'history' ][ 'hour' ]
if period == - 1 :
vals = list ( info . values ())
else :
vals = [ info [ key ] for key in info . keys () if int ( key ) >= ts - period * 60 ** 2 ]
ax . plot ( list ( map ( int , info . keys ()))[ - len ( vals ):], vals , marker = marker , label = self . bot . get_user ( user [ 'id' ]) . name )
2023-05-10 01:51:45 +03:00
ax . xaxis . set_major_formatter ( ticker . FuncFormatter ( lambda x , pos : datetime . fromtimestamp ( x ) . strftime ( ' %d .%m' )))
if period == 24 :
ax . xaxis . set_major_locator ( ticker . IndexLocator ( base = 60 * 60 * 5 , offset = 0 ))
ax . xaxis . set_major_formatter ( ticker . FuncFormatter ( lambda x , pos : datetime . fromtimestamp ( x ) . strftime ( '%Hh' )))
elif period == 24 * 7 :
ax . xaxis . set_major_locator ( ticker . IndexLocator ( base = 60 * 60 * 24 , offset = 0 ))
ax . xaxis . set_major_formatter ( ticker . FuncFormatter ( lambda x , pos : datetime . fromtimestamp ( x ) . strftime ( ' %d .%m' )))
else :
ax . xaxis . set_major_locator ( ticker . IndexLocator ( base = 60 * 60 * 24 * 7 , offset = 0 ))
ax . xaxis . set_minor_locator ( ticker . IndexLocator ( base = 60 * 60 * 24 , offset = 0 ))
ax . xaxis . set_minor_formatter ( ticker . FuncFormatter ( lambda x , pos : datetime . fromtimestamp ( x ) . strftime ( ' %d ' )))
2023-05-09 17:26:12 +03:00
2023-05-10 01:51:45 +03:00
# fig.autofmt_xdate()
2023-05-09 17:26:12 +03:00
ax . legend () . get_frame () . set_boxstyle ( 'Round' , pad = .2 , rounding_size = 1 )
ax . legend () . get_frame () . set_linewidth ( .0 )
ax . xaxis . set_ticks_position ( 'none' )
ax . yaxis . set_ticks_position ( 'none' )
ax . spines [ 'bottom' ] . set_visible ( False )
ax . spines [ 'top' ] . set_visible ( False )
ax . spines [ 'left' ] . set_visible ( '#303030' )
ax . spines [ 'right' ] . set_visible ( '#303030' )
fig . savefig ( f 'tmp/ { inter . id } .png' )
with open ( f 'tmp/ { inter . id } .png' , 'rb' ) as f :
await inter . response . send_message ( file = discord . File ( f ))
2023-05-09 21:05:24 +03:00
remove ( f 'tmp/ { inter . id } .png' )
2023-05-09 17:26:12 +03:00
2023-05-03 19:53:01 +03:00
# @logger.catch
async def setup ( bot ):
await bot . add_cog ( Economic ( bot ))