Passed
Branch BonHowi (242417)
by Bartosz
01:38
created

DatabaseCog.db_add_update_member()   A

Complexity

Conditions 1

Size

Total Lines 8
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nop 2
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
import inspect
2
from discord.ext import commands, tasks
3
from modules.get_settings import get_settings
4
from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, ForeignKey, \
5
    BigInteger, update, select, DateTime, delete
6
from sqlalchemy.dialects.mysql import insert
7
import cogs.cogbase as cogbase
8
from datetime import datetime
9
import pandas as pd
10
11
metadata_obj = MetaData()
12
member = Table('member', metadata_obj,
13
               Column('id', BigInteger, primary_key=True),
14
               Column('name', String(50), nullable=False),
15
               Column('display_name', String(50), nullable=False)
16
               )
17
18
spots = Table('spots', metadata_obj,
19
              Column('member_id', BigInteger, ForeignKey("member.id"), primary_key=True),
20
              Column('legendary', Integer),
21
              Column('rare', Integer),
22
              Column('common', Integer)
23
              )
24
25
spots_temp = Table('spots_temp', metadata_obj,
26
                   Column('member_id', BigInteger, ForeignKey("member.id"), primary_key=True),
27
                   Column('legendary', Integer),
28
                   Column('rare', Integer),
29
                   Column('common', Integer)
30
                   )
31
32
warn = Table('warn', metadata_obj,
33
             Column('id', Integer, primary_key=True),
34
             Column('member_id', BigInteger, ForeignKey("member.id")),
35
             Column('reason', String(120), nullable=False),
36
             Column('date', DateTime, nullable=False),
37
             )
38
39
coords = Table('coords', metadata_obj,
40
               Column('id', Integer, primary_key=True),
41
               Column('coords', String(50), nullable=False),
42
               Column('monster_type', String(50), nullable=False)
43
               )
44
45
46
class DatabaseCog(cogbase.BaseCog):
47
    password = get_settings("DB_P")
48
    engine = create_engine(f"mysql+mysqldb://BonHowi:{password}@localhost/server_database")
49
    metadata_obj.create_all(engine)
50
    conn = engine.connect()
51
52
    def __init__(self, base):
53
        super().__init__(base)
54
55
        # Connect to database
56
        password = get_settings("DB_P")
57
        self.engine = create_engine(f"mysql+mysqldb://BonHowi:{password}@localhost/server_database")
58
        metadata_obj.create_all(self.engine)
59
        self.conn = self.engine.connect()
60
        self.db_update_loop.start()
61
62
    # ----- BASE DATABASE OPERATIONS -----
63
64
    def db_add_update_member(self, _member):
65
        stmt = insert(member).values(
66
            id=_member.id, name=_member.name,
67
            display_name=_member.display_name)
68
        do_update_stmt = stmt.on_duplicate_key_update(
69
            name=stmt.inserted.name, display_name=stmt.inserted.display_name
70
        )
71
        self.conn.execute(do_update_stmt)
72
73
    def db_add_update_spots(self, spots_table, guild_member):
74
        stmt = insert(spots_table).values(
75
            member_id=guild_member.id, legendary=0,
76
            rare=0, common=0)
77
        do_update_stmt = stmt.on_duplicate_key_update(member_id=stmt.inserted.member_id)
78
        self.conn.execute(do_update_stmt)
79
80
    # Add or refresh all guild members and spots to database
81
    async def db_update(self):
82
        guild = self.bot.get_guild(self.bot.guild[0])
83
        # Member tables
84
        print(f"[{self.__class__.__name__}]: Refreshing member count")
85
        for guild_member in guild.members:
86
            self.db_add_update_member(guild_member)
87
        print(f"[{self.__class__.__name__}]: Member count refreshed")
88
89
        # Spots tables
90
        guild = self.bot.get_guild(self.bot.guild[0])
91
        for guild_member in guild.members:
92
            self.db_add_update_spots(spots, guild_member)
93
            self.db_add_update_spots(spots_temp, guild_member)
94
95
    @tasks.loop(hours=12)
96
    async def db_update_loop(self):
97
        await self.db_update()
98
99
    @db_update_loop.before_loop
100
    async def before_db_update_loop(self):
101
        print(f'[{self.__class__.__name__}]: Waiting until Bot is ready')
102
        await self.bot.wait_until_ready()
103
104
    # Placeholder for simpler function(now it updates whole tables instead of one row)
105
    @commands.Cog.listener()
106
    async def on_member_join(self, _member):
107
        self.db_add_update_member(_member)
108
        self.db_add_update_spots(spots, _member)
109
        self.db_add_update_spots(spots_temp, _member)
110
111
    # ----- SPOTTING OPERATIONS -----
112
113
    @classmethod
114
    async def db_count_spot(cls, _id: int, monster_type: str):
115
        # Get member nr of spots for certain monster type
116
        stmt = select(spots.c.member_id, spots.c.legendary, spots.c.rare, spots.c.common).where(
117
            spots.c.member_id == _id)
118
        result = cls.conn.execute(stmt)
119
        for nr_of_kills in result.columns(monster_type):
120
            counter = nr_of_kills[0]
121
        stmt = update(spots).where(spots.c.member_id == _id).values({f"{monster_type}": counter + 1})
0 ignored issues
show
introduced by
The variable counter does not seem to be defined in case the for loop on line 119 is not entered. Are you sure this can never be the case?
Loading history...
122
        cls.conn.execute(stmt)
123
124
        stmt = select(spots_temp.c.member_id, spots_temp.c.legendary, spots_temp.c.rare, spots_temp.c.common).where(
125
            spots_temp.c.member_id == _id)
126
        result = cls.conn.execute(stmt)
127
        for nr_of_kills in result.columns(monster_type):
128
            counter = nr_of_kills[0]
129
        stmt = update(spots_temp).where(spots_temp.c.member_id == _id).values({f"{monster_type}": counter + 1})
130
        cls.conn.execute(stmt)
131
132
    @classmethod
133
    async def db_save_coords(cls, _coords: str, _monster_type):
134
        stmt = insert(coords).values(coords=_coords, monster_type=_monster_type)
135
        cls.conn.execute(stmt)
136
137
    @classmethod
138
    async def db_clear_spots_temp_table(cls):
139
        stmt = delete(spots_temp)
140
        cls.conn.execute(stmt)
141
142
    # ----- LEADERBOARD OPERATIONS -----
143
144
    @classmethod
145
    async def db_get_spots_df(cls):
146
        stmt = select(member.c.display_name, spots.c.legendary, spots.c.rare, spots.c.common).select_from(member).join(
147
            spots,
148
            member.c.id == spots.c.member_id)
149
        df = pd.read_sql(stmt, cls.conn)
150
        return df
151
152
    async def db_update_spotting_roles(self):
153
        pass
154
155
    # ----- WARN OPERATIONS -----
156
157
    @classmethod
158
    async def db_add_warn(cls, _member: int, _reason: str):
159
        stmt = insert(warn).values(member_id=_member, reason=_reason, date=datetime.now())
160
        cls.conn.execute(stmt)
161
162
    @classmethod
163
    async def db_get_warns(cls, _member: int):
164
        stmt = select(warn.c.reason, warn.c.date).select_from(member).join(warn, member.c.id == warn.c.member_id).where(
165
            member.c.id == _member)
166
        result = cls.conn.execute(stmt)
167
        date_warn = []
168
        counter = 0
169
        for warns in result.columns("reason", "date"):
170
            reason_with_date = [warns[1], warns[0]]
171
            date_warn.append(reason_with_date)
172
            counter += 1
173
        warns_list = [': \t'.join([str(elem) for elem in sublist]) for sublist in date_warn]
174
        return warns_list, counter
175
176
    @classmethod
177
    async def db_remove_warns(cls, _member: int):
178
        stmt = delete(warn).where(warn.c.member_id == _member)
179
        cls.conn.execute(stmt)
180
181
    # ----- MEMBER OPERATIONS -----
182
183
    @classmethod
184
    async def db_get_member_stats(cls, _member: int):
185
        stmt = select(member.c.display_name, spots.c.legendary, spots.c.rare, spots.c.common).select_from(member).join(
186
            spots,
187
            member.c.id == spots.c.member_id).where(spots.c.member_id == _member)
188
        df = pd.read_sql(stmt, cls.conn)
189
        return df
190
191
192
def setup(bot: commands.Bot):
193
    bot.add_cog(DatabaseCog(bot))
194