Skip to content

Commit b81a52b

Browse files
authored
Version/1.2.3 (#13)
* added clear command * Update bot.py * remove clear all * customizable settings * adjusted settings, added custom new user level und mult * Update settings.py.example * some refrag * fix: multi user bug * removed token * fixed typo * added boost * Update settings.py.example * Update settings.py.example * added server welcome message * fix: expire xp boost
1 parent c2bc473 commit b81a52b

File tree

4 files changed

+314
-92
lines changed

4 files changed

+314
-92
lines changed

bot.py

Lines changed: 141 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
from ast import literal_eval
1313

1414

15+
class ENUMS:
16+
BOOST_SUCCESS = 0
17+
BOOSTING_YOURSELF_FORBIDDEN = 1
18+
BOOST_NOT_EXPIRED = 2
19+
20+
1521
class DiscordBot:
1622
def __init__(self,
1723
db_conn,
@@ -68,13 +74,23 @@ def _dict_factory(cursor, row):
6874

6975
cur.execute('''
7076
CREATE TABLE IF NOT EXISTS settings (
71-
gid INTEGER NOT NULL,
72-
skey TEXT NOT NULL,
73-
svalue TEXT NOT NULL,
77+
gid INTEGER NOT NULL,
78+
skey TEXT NOT NULL,
79+
svalue TEXT NOT NULL,
7480
PRIMARY KEY (gid, skey)
7581
);
7682
''')
7783

84+
cur.execute('''
85+
CREATE TABLE IF NOT EXISTS boosts (
86+
uid INTEGER NOT NULL,
87+
gid INTEGER NOT NULL,
88+
boostedid INTEGER NOT NULL,
89+
expires INTEGER NOT NULL,
90+
PRIMARY KEY (uid, gid)
91+
);
92+
''')
93+
7894
self.db_conn.commit()
7995

8096
self.bot = commands.Bot(command_prefix=command_prefix,
@@ -201,6 +217,39 @@ async def search_text_channel(ctx, search):
201217
return channel
202218
return None
203219

220+
async def xp_multiplier_adds(self, member_id, guild_id):
221+
xp_adds = 0
222+
cur = self.db_conn.cursor()
223+
cur.execute('SELECT COUNT(*) as count FROM boosts WHERE gid=? AND boostedid=? AND expires>?',
224+
(guild_id, member_id, time.time(),))
225+
xp_adds += cur.fetchone()['count'] * await self.get_setting(guild_id, 'BOOST_ADD_XP_MULTIPLIER')
226+
return xp_adds
227+
228+
async def get_all_boosts(self, member):
229+
cur = self.db_conn.cursor()
230+
cur.execute('SELECT * FROM boosts WHERE gid=?', (member.guild.id,))
231+
return cur.fetchall()
232+
233+
async def get_boost_user(self, member):
234+
cur = self.db_conn.cursor()
235+
cur.execute('SELECT * FROM boosts WHERE uid=? AND gid=?', (member.id, member.guild.id,))
236+
return cur.fetchone()
237+
238+
async def set_boost_user(self, member, user_to_boost):
239+
if member.id == user_to_boost.id:
240+
return ENUMS.BOOSTING_YOURSELF_FORBIDDEN
241+
previous_boost = await self.get_boost_user(member)
242+
current_time = int(time.time())
243+
if previous_boost is None or previous_boost['expires'] < current_time:
244+
cur = self.db_conn.cursor()
245+
cur.execute('INSERT OR REPLACE INTO boosts(uid, gid, boostedid, expires)'
246+
'VALUES(?, ?, ?, ?);',
247+
(member.id, member.guild.id, user_to_boost.id, current_time
248+
+ (await self.get_setting(member.guild.id, 'BOOST_EXPIRES_DAYS')) * 24 * 60 * 60,))
249+
self.db_conn.commit()
250+
return ENUMS.BOOST_SUCCESS
251+
return ENUMS.BOOST_NOT_EXPIRED
252+
204253
async def get_users(self, guild):
205254
cur = self.db_conn.cursor()
206255
cur.execute('SELECT * FROM users WHERE gid=?', (guild.id,))
@@ -310,7 +359,8 @@ async def update_all_voice_users(self, ctime):
310359
else:
311360
xp_earned = self.xp_for((ctime - user['joined'])
312361
* await self.get_setting(guild.id, 'VOICE_XP_PER_MINUTE') / 60,
313-
user['xp_multiplier'])
362+
user['xp_multiplier']
363+
+ await self.xp_multiplier_adds(user['uid'], user['gid']))
314364

315365
user['joined'] = ctime
316366

@@ -343,11 +393,9 @@ async def member_create_profile_image(self, member):
343393
# Retrieve user data
344394
#
345395
data = await self.get_user(member)
346-
name = member.name
347-
if member.nick is not None:
348-
name = member.nick
396+
name = member.display_name
349397

350-
data_xp_multiplier = data['xp_multiplier']
398+
data_xp_multiplier = data['xp_multiplier'] + await self.xp_multiplier_adds(data['uid'], data['gid'])
351399
data_xp = int(self.lvl_get_xp(data['lvl']))
352400
data_max_xp = int(self.max_xp_for(data['lvl']))
353401
data_percentage = data_xp / data_max_xp
@@ -368,10 +416,18 @@ async def member_create_profile_image(self, member):
368416
(await self.get_setting(member.guild.id, 'PROFILE_IMAGE'))(data_obj))
369417
return discord.File(filename="member.png", fp=img_buf)
370418

419+
async def member_create_welcome_image(self, member):
420+
name = member.display_name
421+
data_obj = {'member': member,
422+
'name': name,
423+
'avatar_url': str(member.avatar_url_as(format="png")),
424+
'guild_icon_url': str(member.guild.icon_url_as(format="png"))}
425+
img_buf = await self.image_creator.create(
426+
(await self.get_setting(member.guild.id, 'WELCOME_IMAGE'))(data_obj))
427+
return discord.File(filename="welcome.png", fp=img_buf)
428+
371429
async def member_create_lvl_image(self, member, old_lvl, new_lvl):
372-
name = member.name
373-
if member.nick is not None:
374-
name = member.nick
430+
name = member.display_name
375431

376432
data_obj = {'member': member,
377433
'old_lvl': self.get_lvl(old_lvl),
@@ -384,9 +440,7 @@ async def member_create_lvl_image(self, member, old_lvl, new_lvl):
384440
return discord.File(filename="lvlup.png", fp=img_buf)
385441

386442
async def member_create_rank_up_image(self, member, old_lvl, new_lvl, old_role, new_role):
387-
name = member.name
388-
if member.nick is not None:
389-
name = member.nick
443+
name = member.display_name
390444

391445
data_obj = {'member': member,
392446
'old_lvl': self.get_lvl(old_lvl),
@@ -406,9 +460,7 @@ async def create_ranking_image(self, member, ranked_users):
406460
for user in ranked_users:
407461
member = get(member.guild.members, id=int(user['uid']))
408462
if member is not None and not member.bot:
409-
name = member.name
410-
if member.nick is not None:
411-
name = member.nick
463+
name = member.display_name
412464
data_obj.append({
413465
'member': member,
414466
'rank': user['rank'],
@@ -480,7 +532,7 @@ async def member_left_vc(self, member, t):
480532
data = await self.get_user(member)
481533
if bool(data['blacklist']) is True:
482534
return
483-
xp_multiplier = data['xp_multiplier']
535+
xp_multiplier = data['xp_multiplier'] + await self.xp_multiplier_adds(data['uid'], data['gid'])
484536
if data['joined'] >= 0:
485537
xp_earned = self.xp_for((t - data['joined'])
486538
* await self.get_setting(member.guild.id, 'VOICE_XP_PER_MINUTE') / 60, xp_multiplier)
@@ -494,7 +546,7 @@ async def member_message_xp(self, member):
494546
data = await self.get_user(member)
495547
if bool(data['blacklist']) is True:
496548
return
497-
xp_multiplier = data['xp_multiplier']
549+
xp_multiplier = data['xp_multiplier'] + await self.xp_multiplier_adds(data['uid'], data['gid'])
498550
xp_earned = self.xp_for(await self.get_setting(member.guild.id, 'MESSAGE_XP'), xp_multiplier)
499551
old_level = data['lvl']
500552
data['lvl'] += self.lvl_xp_add(xp_earned, data['lvl'])
@@ -600,6 +652,63 @@ async def _profile(self, ctx, *args):
600652
description='No user was found!',
601653
color=discord.Color.red()))
602654

655+
@commands.command(name='boost',
656+
aliases=['b'],
657+
description='give a friend a boost',
658+
help=' - Boosted einen Freund')
659+
async def _boost(self, ctx, *args):
660+
if ctx.guild is None:
661+
raise commands.NoPrivateMessage()
662+
await ctx.trigger_typing()
663+
if len(args) == 0:
664+
current_time = time.time()
665+
666+
boosting = await self.parent.get_boost_user(ctx.message.author)
667+
668+
if boosting is None or boosting['expires'] < current_time:
669+
return await ctx.send(embed=discord.Embed(title='Boost',
670+
description='You currently boosting no one!\n'
671+
'Use "boost {member} to start boosting!',
672+
color=discord.Color.gold()))
673+
674+
member = get(ctx.message.guild.members, id=int(boosting['boostedid']))
675+
676+
member_name = 'A USER WHO LEFT'
677+
678+
if member is not None:
679+
member_name = member.display_name
680+
681+
boost_remaining = (boosting['expires'] - current_time) / (24 * 60 * 60)
682+
boost_remaining_days = round(boost_remaining)
683+
boost_remaining_hours = round((boost_remaining - boost_remaining_days) * 24)
684+
return await ctx.send(embed=discord.Embed(title='Boost',
685+
description='You are boosting {}!\n'
686+
'Boost expires in {} days and {} hours!'
687+
.format(member_name,
688+
boost_remaining_days,
689+
boost_remaining_hours),
690+
color=discord.Color.gold()))
691+
692+
member = await self.parent.search_member(ctx, ' '.join(args))
693+
if member is None:
694+
return await ctx.send(embed=discord.Embed(title='',
695+
description='No matching user was found',
696+
color=discord.Color.red()))
697+
698+
res = await self.parent.set_boost_user(ctx.message.author, member)
699+
if res == ENUMS.BOOST_SUCCESS:
700+
return await ctx.send(embed=discord.Embed(title='',
701+
description='You are boosting {} now!'
702+
.format(member.display_name),
703+
color=discord.Color.green()))
704+
elif res == ENUMS.BOOSTING_YOURSELF_FORBIDDEN:
705+
return await ctx.send(embed=discord.Embed(title='',
706+
description='You cannot boost yourself!',
707+
color=discord.Color.red()))
708+
return await ctx.send(embed=discord.Embed(title='',
709+
description='Your boost has not expired yet!',
710+
color=discord.Color.red()))
711+
603712
@commands.command(name='leaderboard',
604713
aliases=[],
605714
description='show the leaderboard',
@@ -638,7 +747,7 @@ async def _send(self, ctx, *args):
638747
if len(args) == 0:
639748
return await ctx.send(embed=discord.Embed(title='Help',
640749
description='"send {msg}" to send into the system channel\n'
641-
'"send {channel_id} {msg}" to send'
750+
'"send {channel_id} {msg}" to send '
642751
'into a specific channel',
643752
color=discord.Color.gold()))
644753
elif len(args) == 1:
@@ -702,6 +811,9 @@ async def __setlvl(m):
702811
help=' - Alles ein-zu-stellen')
703812
@commands.has_permissions(administrator=True)
704813
async def _settings(self, ctx, *args):
814+
if ctx.guild is None:
815+
raise commands.NoPrivateMessage()
816+
705817
if len(args) == 0:
706818
pass
707819
elif args[0] in ['set', 's'] and len(args) >= 3:
@@ -763,6 +875,7 @@ async def _settings(self, ctx, *args):
763875
async def _lvlsys(self, ctx, *args):
764876
if ctx.guild is None:
765877
raise commands.NoPrivateMessage()
878+
766879
await ctx.trigger_typing()
767880

768881
embed = discord.Embed(title='Help',
@@ -868,6 +981,9 @@ async def __blacklist(m):
868981
help=' - Löscht Nachrichten in einem Text-Channel!')
869982
@commands.has_permissions(administrator=True)
870983
async def _clear(self, ctx, *args):
984+
if ctx.guild is None:
985+
raise commands.NoPrivateMessage()
986+
871987
await ctx.trigger_typing()
872988
if len(args) == 0:
873989
pass
@@ -973,6 +1089,9 @@ async def on_command_error(self, ctx, error):
9731089
await ctx.send(embed=discord.Embed(description=random.choice(
9741090
await self.parent.get_setting(ctx.message.author.guild.id, 'MISSING_PERMISSIONS_RESPONSES')),
9751091
color=discord.Color.red()))
1092+
1093+
elif isinstance(error, commands.NoPrivateMessage):
1094+
await ctx.send('This command does not work via Private Message')
9761095
else:
9771096
self.parent.lprint(error)
9781097

@@ -984,8 +1103,8 @@ async def on_ready(self):
9841103
async def on_member_join(self, member):
9851104
if not member.bot:
9861105
await self.parent.update_member(member)
987-
# send a private message on join
988-
# await member.send('Private message')
1106+
if await self.parent.get_setting(member.guild.id, 'SEND_WELCOME_IMAGE'):
1107+
await member.send(file=await self.parent.member_create_welcome_image(member))
9891108

9901109
@commands.Cog.listener()
9911110
async def on_member_remove(self, member):

images/welcome_template.png

57.4 KB
Loading

0 commit comments

Comments
 (0)