Passed
Branch BonHowi (cdc12d)
by Bartosz
01:26
created

DatabaseCog.db_update_spots_old()   A

Complexity

Conditions 3

Size

Total Lines 25
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 24
nop 2
dl 0
loc 25
rs 9.304
c 0
b 0
f 0
1
from discord.ext import commands, tasks
2
from discord_slash import cog_ext
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
fk_member_id = "member.id"
18
19
spots = Table('spots', metadata_obj,
20
              Column('member_id', BigInteger, ForeignKey(fk_member_id), primary_key=True),
21
              Column('legendary', Integer, default=0),
22
              Column('rare', Integer, default=0),
23
              Column('common', Integer, default=0),
24
              Column('event1', Integer, default=0),
25
              Column('event2', Integer, default=0)
26
              )
27
28
spots_temp = Table('spots_temp', metadata_obj,
29
                   Column('member_id', BigInteger, ForeignKey(fk_member_id), primary_key=True),
30
                   Column('legendary', Integer, default=0),
31
                   Column('rare', Integer, default=0),
32
                   Column('common', Integer, default=0),
33
                   Column('event1', Integer, default=0),
34
                   Column('event2', Integer, default=0)
35
                   )
36
37
warn = Table('warn', metadata_obj,
38
             Column('id', Integer, primary_key=True),
39
             Column('member_id', BigInteger, ForeignKey(fk_member_id)),
40
             Column('reason', String(120), nullable=False),
41
             Column('date', DateTime, nullable=False),
42
             )
43
44
coords = Table('coords', metadata_obj,
45
               Column('id', Integer, primary_key=True),
46
               Column('coords', String(50), nullable=False),
47
               Column('monster_type', String(50), nullable=False)
48
               )
49
50
51
class DatabaseCog(cogbase.BaseCog):
52
    password = get_settings("DB_P")
53
    engine = create_engine(f"mysql+mysqldb://BonHowi:{password}@localhost/server_database")
54
    metadata_obj.create_all(engine)
55
    conn = engine.connect()
56
57
    def __init__(self, base):
58
        super().__init__(base)
59
60
        # Connect to database
61
        password = get_settings("DB_P")
62
        self.engine = create_engine(f"mysql+mysqldb://BonHowi:{password}@localhost/server_database")
63
        metadata_obj.create_all(self.engine)
64
        self.conn = self.engine.connect()
65
        self.db_update_loop.start()
66
67
    # ----- BASE DATABASE OPERATIONS -----
68
69
    def db_add_update_member(self, _member):
70
        stmt = insert(member).values(
71
            id=_member.id, name=_member.name,
72
            display_name=_member.display_name)
73
        do_update_stmt = stmt.on_duplicate_key_update(
74
            name=stmt.inserted.name, display_name=stmt.inserted.display_name
75
        )
76
        self.conn.execute(do_update_stmt)
77
78
    def db_add_update_spots(self, spots_table, guild_member):
79
        stmt = insert(spots_table).values(
80
            member_id=guild_member.id)
81
        do_update_stmt = stmt.on_duplicate_key_update(member_id=stmt.inserted.member_id)
82
        self.conn.execute(do_update_stmt)
83
84
    # Add or refresh all guild members and spots to database
85
    async def db_update(self):
86
        guild = self.bot.get_guild(self.bot.guild[0])
87
        # Member tables
88
        print(f"[{self.__class__.__name__}]: Refreshing member count")
89
        for guild_member in guild.members:
90
            self.db_add_update_member(guild_member)
91
        print(f"[{self.__class__.__name__}]: Member count refreshed")
92
93
        # Spots tables
94
        for guild_member in guild.members:
95
            self.db_add_update_spots(spots, guild_member)
96
            self.db_add_update_spots(spots_temp, guild_member)
97
98
    @tasks.loop(hours=12)
99
    async def db_update_loop(self):
100
        await self.db_update()
101
102
    @db_update_loop.before_loop
103
    async def before_db_update_loop(self):
104
        print(f'[{self.__class__.__name__}]: Waiting until Bot is ready')
105
        await self.bot.wait_until_ready()
106
107
    # TODO: Placeholder for simpler function(now it updates whole tables instead of one row)
108
    @commands.Cog.listener()
109
    async def on_member_join(self, _member):
110
        self.db_add_update_member(_member)
111
        self.db_add_update_spots(spots, _member)
112
        self.db_add_update_spots(spots_temp, _member)
113
114
    @cog_ext.cog_slash(name="updateSpotsWithOld", guild_ids=cogbase.GUILD_IDS,
115
                       description="Change N-Word channel name",
116
                       permissions=cogbase.PERMISSION_ADMINS)
117
    async def db_update_spots_old(self, ctx):
118
        import json
119
        with open('server_files/old_base_test.json', 'r', encoding='utf-8-sig') as fp:
120
            old_db = json.load(fp)
121
122
        for mem_id in old_db:
123
            stmt = insert(spots).values(
124
                member_id=mem_id, legendary=old_db[mem_id]["type_1"],
125
                rare=old_db[mem_id]["type_0"])
126
            do_update_stmt = stmt.on_duplicate_key_update(legendary=stmt.inserted.legendary,
127
                                                          rare=stmt.inserted.rare,
128
                                                          common=stmt.inserted.common)
129
            self.conn.execute(do_update_stmt)
130
            stmt = insert(spots_temp).values(
131
                member_id=mem_id, legendary=old_db[mem_id]["type_1"],
132
                rare=old_db[mem_id]["type_0"])
133
            do_update_stmt = stmt.on_duplicate_key_update(legendary=stmt.inserted.legendary,
134
                                                          rare=stmt.inserted.rare,
135
                                                          common=stmt.inserted.common)
136
            self.conn.execute(do_update_stmt)
137
        await ctx.send(f"Spot tables updated with old data", delete_after=3.0)
138
        print(f'[{self.__class__.__name__}]: Spot tables updated with old data')
139
140
    # ----- SPOTTING OPERATIONS -----
141
142
    @classmethod
143
    async def db_count_spot(cls, _id: int, monster_type: str):
144
        # Get member nr of spots for certain monster type
145
        stmt = select(spots.c.member_id, spots.c.legendary, spots.c.rare, spots.c.common).where(
146
            spots.c.member_id == _id)
147
        result = cls.conn.execute(stmt)
148
        counter = []
149
        for nr_of_kills in result.columns(monster_type):
150
            counter = nr_of_kills[0]
151
        stmt = update(spots).where(spots.c.member_id == _id).values({f"{monster_type}": counter + 1})
152
        cls.conn.execute(stmt)
153
154
        stmt = select(spots_temp.c.member_id, spots_temp.c.legendary, spots_temp.c.rare, spots_temp.c.common).where(
155
            spots_temp.c.member_id == _id)
156
        result = cls.conn.execute(stmt)
157
        for nr_of_kills in result.columns(monster_type):
158
            counter = nr_of_kills[0]
159
        stmt = update(spots_temp).where(spots_temp.c.member_id == _id).values({f"{monster_type}": counter + 1})
160
        cls.conn.execute(stmt)
161
162
    @classmethod
163
    async def db_save_coords(cls, _coords: str, _monster_type):
164
        stmt = insert(coords).values(coords=_coords, monster_type=_monster_type)
165
        cls.conn.execute(stmt)
166
167
    @classmethod
168
    async def db_clear_spots_temp_table(cls):
169
        stmt = delete(spots_temp)
170
        cls.conn.execute(stmt)
171
172
    # ----- LEADERBOARD OPERATIONS -----
173
174
    @classmethod
175
    async def db_get_spots_df(cls):
176
        stmt = select(member.c.display_name, spots.c.legendary, spots.c.rare, spots.c.common).select_from(member).join(
177
            spots,
178
            member.c.id == spots.c.member_id)
179
        df = pd.read_sql(stmt, cls.conn)
180
        return df
181
182
    async def db_update_spotting_roles(self):
183
        pass
184
185
    # ----- WARN OPERATIONS -----
186
187
    @classmethod
188
    async def db_add_warn(cls, _member: int, _reason: str):
189
        stmt = insert(warn).values(member_id=_member, reason=_reason, date=datetime.now())
190
        cls.conn.execute(stmt)
191
192
    @classmethod
193
    async def db_get_warns(cls, _member: int):
194
        stmt = select(warn.c.reason, warn.c.date).select_from(member).join(warn, member.c.id == warn.c.member_id).where(
195
            member.c.id == _member)
196
        result = cls.conn.execute(stmt)
197
        date_warn = []
198
        counter = 0
199
        for warns in result.columns("reason", "date"):
200
            reason_with_date = [warns[1], warns[0]]
201
            date_warn.append(reason_with_date)
202
            counter += 1
203
        warns_list = [': \t'.join([str(elem) for elem in sublist]) for sublist in date_warn]
204
        return warns_list, counter
205
206
    @classmethod
207
    async def db_remove_warns(cls, _member: int):
208
        stmt = delete(warn).where(warn.c.member_id == _member)
209
        cls.conn.execute(stmt)
210
211
    # ----- MEMBER OPERATIONS -----
212
213
    @classmethod
214
    async def db_get_member_stats(cls, _member: int):
215
        stmt = select(member.c.display_name, spots.c.legendary, spots.c.rare, spots.c.common).select_from(member).join(
216
            spots,
217
            member.c.id == spots.c.member_id).where(spots.c.member_id == _member)
218
        df = pd.read_sql(stmt, cls.conn)
219
        return df
220
221
222
def setup(bot: commands.Bot):
223
    bot.add_cog(DatabaseCog(bot))
224