async def on_start() -> None: glob.http = aiohttp.ClientSession(json_serialize=orjson.dumps) # connect to mysql glob.db = cmyui.AsyncSQLPool() await glob.db.connect(glob.config.mysql) # run the sql updater updater = Updater(glob.version) await updater.run() await updater.log_startup() # create our bot & append it to the global player list. glob.bot = Player(id=1, name='Aika', priv=Privileges.Normal) glob.bot.last_recv_time = float(0x7fffffff) glob.players.append(glob.bot) # add all channels from db. async for chan in glob.db.iterall('SELECT * FROM channels'): chan['read_priv'] = Privileges(chan.pop('read_priv', 1)) chan['write_priv'] = Privileges(chan.pop('write_priv', 2)) glob.channels.append(Channel(**chan)) # add all mappools from db. async for pool in glob.db.iterall('SELECT * FROM tourney_pools'): # overwrite basic types with some class types creator = await glob.players.get(id=pool['created_by'], sql=True) pool['created_by'] = creator # replace id with player object pool = MapPool(**pool) await pool.maps_from_sql() glob.pools.append(pool) # add new donation ranks & enqueue tasks to remove current ones. # TODO: this system can get quite a bit better; rather than just # removing, it should rather update with the new perks (potentially # a different tier, enqueued after their current perks). async def rm_donor(userid: int, delay: int): await asyncio.sleep(delay) p = await glob.players.get(id=userid, sql=True) await p.remove_privs(Privileges.Donator) log(f"{p}'s donation perks have expired.", Ansi.MAGENTA) query = ('SELECT id, donor_end FROM users ' 'WHERE donor_end > UNIX_TIMESTAMP()') async for donation in glob.db.iterall(query): # calculate the delta between now & the exp date. delta = donation['donor_end'] - time.time() if delta > (60 * 60 * 24 * 30): # ignore donations expiring in over a months time; # the server should restart relatively often anyways. continue asyncio.create_task(rm_donor(donation['id'], delta))
async def pool_create(p: 'Player', c: Messageable, msg: Sequence[str]) -> str: """Add a new mappool to the database.""" if len(msg) != 1: return 'Invalid syntax: !pool create <name>' name = msg[0] if glob.pools.get(name): return 'Pool already exists with that name!' # insert pool into db await glob.db.execute( 'INSERT INTO tourney_pools ' '(name, created_at, created_by) ' 'VALUES (%s, NOW(), %s)', [name, p.id] ) # add to cache (get from sql for id & time) res = await glob.db.fetch('SELECT * FROM tourney_pools ' 'WHERE name = %s', [name]) glob.pools.append(MapPool(**res)) return f'{name} created.'
async def prepare(cls) -> None: """Fetch data from sql & return; preparing to run the server.""" log('Fetching mappools from sql', Ansi.LCYAN) return cls([ MapPool(id=row['id'], name=row['name'], created_at=row['created_at'], created_by=await glob.players.get_ensure(id=row['created_by'])) for row in await glob.db.fetchall('SELECT * FROM tourney_pools') ])
async def prepare(cls, db_cursor: aiomysql.DictCursor) -> 'MapPools': """Fetch data from sql & return; preparing to run the server.""" log('Fetching mappools from sql.', Ansi.LCYAN) await db_cursor.execute('SELECT * FROM tourney_pools') obj = cls([ MapPool(id=row['id'], name=row['name'], created_at=row['created_at'], created_by=await glob.players.get_ensure(id=row['created_by'])) async for row in db_cursor ]) for pool in obj: await pool.maps_from_sql(db_cursor) return obj
async def prepare(cls, db_cursor: aiomysql.DictCursor) -> "MapPools": """Fetch data from sql & return; preparing to run the server.""" log("Fetching mappools from sql.", Ansi.LCYAN) await db_cursor.execute("SELECT * FROM tourney_pools") obj = cls([ MapPool( id=row["id"], name=row["name"], created_at=row["created_at"], created_by=await glob.players.from_cache_or_sql( id=row["created_by"], ), ) async for row in db_cursor ], ) for pool in obj: await pool.maps_from_sql(db_cursor) return obj
async def setup_collections() -> None: """Setup & cache many global collections (mostly from sql).""" # create our bot & append it to the global player list. res = await glob.db.fetch('SELECT name FROM users WHERE id = 1') # global players list glob.players = PlayerList() glob.bot = Player( id=1, name=res['name'], priv=Privileges.Normal, last_recv_time=float(0x7fffffff) # never auto-dc ) glob.players.append(glob.bot) # global channels list glob.channels = ChannelList() async for res in glob.db.iterall('SELECT * FROM channels'): chan = Channel(name=res['name'], topic=res['topic'], read_priv=Privileges(res['read_priv']), write_priv=Privileges(res['write_priv']), auto_join=res['auto_join'] == 1) glob.channels.append(chan) # global matches list glob.matches = MatchList() # global clans list glob.clans = ClanList() async for res in glob.db.iterall('SELECT * FROM clans'): clan = Clan(**res) await clan.members_from_sql() glob.clans.append(clan) # global mappools list glob.pools = MapPoolList() async for res in glob.db.iterall('SELECT * FROM tourney_pools'): pool = MapPool(id=res['id'], name=res['name'], created_at=res['created_at'], created_by=await glob.players.get_ensure(id=res['created_by'])) await pool.maps_from_sql() glob.pools.append(pool) # global achievements (sorted by vn gamemodes) glob.achievements = {0: [], 1: [], 2: [], 3: []} async for res in glob.db.iterall( 'SELECT `id`, `file`, `name`, `desc`, `cond`, `mode` FROM achievements' ): # NOTE: achievement conditions are stored as # stringified python expressions in the database # to allow for easy custom achievements. condition = eval(f'lambda score: {res.pop("cond")}') achievement = Achievement(**res, cond=condition) # NOTE: achievements are grouped by modes internally. glob.achievements[res['mode']].append(achievement) """ XXX: Unfinished code for beatmap submission.
async def on_start() -> None: glob.http = aiohttp.ClientSession(json_serialize=orjson.dumps) # connect to mysql glob.db = cmyui.AsyncSQLPool() await glob.db.connect(glob.config.mysql) # run the sql updater updater = Updater(glob.version) await updater.run() await updater.log_startup() # create our bot & append it to the global player list. glob.bot = Player(id=1, name='Aika', priv=Privileges.Normal) glob.bot.last_recv_time = float(0x7fffffff) glob.players.append(glob.bot) # TODO: this section is getting a bit gross.. :P # should be moved and probably refactored pretty hard. # add all channels from db. async for c_res in glob.db.iterall('SELECT * FROM channels'): c_res['read_priv'] = Privileges(c_res.get('read_priv', 1)) c_res['write_priv'] = Privileges(c_res.get('write_priv', 2)) glob.channels.append(Channel(**c_res)) # add all mappools from db. async for p_res in glob.db.iterall('SELECT * FROM tourney_pools'): # overwrite basic types with some class types creator = await glob.players.get(id=p_res['created_by'], sql=True) p_res['created_by'] = creator # replace id with player object pool = MapPool(**p_res) await pool.maps_from_sql() glob.pools.append(pool) # add all clans from db. async for c_res in glob.db.iterall('SELECT * FROM clans'): # fetch all members from sql m_res = await glob.db.fetchall( 'SELECT id, clan_rank ' 'FROM users ' 'WHERE clan_id = %s', c_res['id'], _dict=False) members = set() for p_id, clan_rank in m_res: if clan_rank == 3: c_res['owner'] = p_id members.add(p_id) glob.clans.append(Clan(**c_res, members=members)) # add all achievements from db. async for a_res in glob.db.iterall('SELECT * FROM achievements'): condition = eval(f'lambda score: {a_res.pop("cond")}') achievement = Achievement(**a_res, cond=condition) glob.achievements[a_res['mode']].append(achievement) """ bmsubmit stuff # get the latest set & map id offsets for custom maps. maps_res = await glob.db.fetch( 'SELECT id, set_id FROM maps ' 'WHERE server = "gulag" ' 'ORDER BY id ASC LIMIT 1' ) if maps_res: glob.gulag_maps = maps_res """ # add new donation ranks & enqueue tasks to remove current ones. # TODO: this system can get quite a bit better; rather than just # removing, it should rather update with the new perks (potentially # a different tier, enqueued after their current perks). async def rm_donor(userid: int, delay: int): await asyncio.sleep(delay) p = await glob.players.get(id=userid, sql=True) await p.remove_privs(Privileges.Donator) log(f"{p}'s donation perks have expired.", Ansi.MAGENTA) query = ('SELECT id, donor_end FROM users ' 'WHERE donor_end > UNIX_TIMESTAMP()') async for donation in glob.db.iterall(query): # calculate the delta between now & the exp date. delta = donation['donor_end'] - time.time() if delta > (60 * 60 * 24 * 30): # ignore donations expiring in over a months time; # the server should restart relatively often anyways. continue asyncio.create_task(rm_donor(donation['id'], delta))