Make announcements async, work on bank upgrades

pull/119/head
stijndcl 2022-07-03 17:19:24 +02:00
parent 5b510d1f45
commit ba86d4a6f2
9 changed files with 143 additions and 14 deletions

View File

@ -0,0 +1,28 @@
"""Add missing defaults
Revision ID: 632b69cdadde
Revises: 8c4ad0a1d699
Create Date: 2022-07-03 16:29:07.387011
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '632b69cdadde'
down_revision = '8c4ad0a1d699'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###

View File

@ -0,0 +1,32 @@
"""Move dinks over to Bank & add invested amount
Revision ID: 8c4ad0a1d699
Revises: 0d03c226d881
Create Date: 2022-07-03 16:27:11.330746
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '8c4ad0a1d699'
down_revision = '0d03c226d881'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('bank', schema=None) as batch_op:
batch_op.add_column(sa.Column('invested', sa.BigInteger(), server_default='0', nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('bank', schema=None) as batch_op:
batch_op.drop_column('invested')
# ### end Alembic commands ###

View File

@ -17,16 +17,17 @@ class Bank(Base):
bank_id: int = Column(Integer, primary_key=True)
user_id: int = Column(BigInteger, ForeignKey("users.user_id"))
dinks: int = Column(BigInteger, default=0, nullable=False)
dinks: int = Column(BigInteger, server_default="0", nullable=False)
invested: int = Column(BigInteger, server_default="0", nullable=False)
# Interest rate
interest_level: int = Column(Integer, default=1, nullable=False)
interest_level: int = Column(Integer, server_default="1", nullable=False)
# Maximum amount that can be stored in the bank
capacity_level: int = Column(Integer, default=1, nullable=False)
capacity_level: int = Column(Integer, server_default="1", nullable=False)
# Maximum amount that can be robbed
rob_level: int = Column(Integer, default=1, nullable=False)
rob_level: int = Column(Integer, server_default="1", nullable=False)
user: User = relationship("User", uselist=False, back_populates="bank", lazy="selectin")
@ -67,7 +68,7 @@ class NightlyData(Base):
nightly_id: int = Column(Integer, primary_key=True)
user_id: int = Column(BigInteger, ForeignKey("users.user_id"))
last_nightly: Optional[datetime] = Column(DateTime(timezone=True), nullable=True)
count: int = Column(Integer, default=0, nullable=False)
count: int = Column(Integer, server_default="0", nullable=False)
user: User = relationship("User", back_populates="nightly_data", uselist=False, lazy="selectin")
@ -81,7 +82,7 @@ class UforaCourse(Base):
name: str = Column(Text, nullable=False, unique=True)
code: str = Column(Text, nullable=False, unique=True)
year: int = Column(Integer, nullable=False)
log_announcements: bool = Column(Boolean, default=False, nullable=False)
log_announcements: bool = Column(Boolean, server_default="0", nullable=False)
announcements: list[UforaAnnouncement] = relationship(
"UforaAnnouncement", back_populates="course", cascade="all, delete-orphan", lazy="selectin"

View File

@ -8,6 +8,7 @@ from database.exceptions.currency import DoubleNightly
from didier import Didier
from didier.utils.discord.checks import is_owner
from didier.utils.discord.converters import abbreviated_number
from didier.utils.math.currency import capacity_upgrade_price, interest_upgrade_price, rob_upgrade_price
from didier.utils.types.string import pluralize
@ -34,11 +35,42 @@ class Currency(commands.Cog):
mention_author=False,
)
@commands.hybrid_group(name="bank", case_insensitive=True, invoke_without_command=True)
@commands.group(name="bank", aliases=["B"], case_insensitive=True, invoke_without_command=True)
async def bank(self, ctx: commands.Context):
"""Show your Didier Bank information"""
async with self.client.db_session as session:
await crud.get_bank(session, ctx.author.id)
bank = await crud.get_bank(session, ctx.author.id)
embed = discord.Embed(colour=discord.Colour.blue())
embed.set_author(name=f"Bank van {ctx.author.display_name}")
embed.set_thumbnail(url=ctx.author.avatar.url)
embed.add_field(name="Interest level", value=bank.interest_level)
embed.add_field(name="Capaciteit level", value=bank.capacity_level)
embed.add_field(name="Momenteel geïnvesteerd", value=bank.invested, inline=False)
await ctx.reply(embed=embed, mention_author=False)
@bank.group(name="Upgrade", aliases=["U", "Upgrades"], case_insensitive=True, invoke_without_command=True)
async def bank_upgrades(self, ctx: commands.Context):
"""List the upgrades you can buy & their prices"""
async with self.client.db_session as session:
bank = await crud.get_bank(session, ctx.author.id)
embed = discord.Embed(colour=discord.Colour.blue())
embed.set_author(name="Bank upgrades")
embed.add_field(
name=f"Interest ({bank.interest_level})", value=str(interest_upgrade_price(bank.interest_level))
)
embed.add_field(
name=f"Capaciteit ({bank.capacity_level})", value=str(capacity_upgrade_price(bank.capacity_level))
)
embed.add_field(name=f"Rob ({bank.rob_level})", value=str(rob_upgrade_price(bank.rob_level)))
embed.set_footer(text="Didier Bank Upgrade [Categorie]")
await ctx.reply(embed=embed, mention_author=False)
@commands.hybrid_command(name="dinks")
async def dinks(self, ctx: commands.Context):

View File

@ -29,9 +29,9 @@ class Tasks(commands.Cog):
if settings.UFORA_RSS_TOKEN is None or settings.UFORA_ANNOUNCEMENTS_CHANNEL is None:
return
async with self.client.db_session as session:
async with self.client.db_session as db_session:
announcements_channel = self.client.get_channel(settings.UFORA_ANNOUNCEMENTS_CHANNEL)
announcements = await fetch_ufora_announcements(session)
announcements = await fetch_ufora_announcements(self.client.http_session, db_session)
for announcement in announcements:
await announcements_channel.send(embed=announcement.to_embed())

View File

@ -3,9 +3,11 @@ from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional
import async_timeout
import discord
import feedparser
import pytz
from aiohttp import ClientSession
from markdownify import markdownify as md
from sqlalchemy.ext.asyncio import AsyncSession
@ -116,7 +118,9 @@ def parse_ids(url: str) -> Optional[tuple[int, int]]:
return int(spl[0]), int(spl[1])
async def fetch_ufora_announcements(session: AsyncSession) -> list[UforaNotification]:
async def fetch_ufora_announcements(
http_session: ClientSession, database_session: AsyncSession
) -> list[UforaNotification]:
"""Fetch all new announcements"""
notifications: list[UforaNotification] = []
@ -124,7 +128,7 @@ async def fetch_ufora_announcements(session: AsyncSession) -> list[UforaNotifica
if settings.UFORA_RSS_TOKEN is None:
return notifications
courses = await crud.get_courses_with_announcements(session)
courses = await crud.get_courses_with_announcements(database_session)
for course in courses:
course_announcement_ids = list(map(lambda announcement: announcement.announcement_id, course.announcements))
@ -134,7 +138,9 @@ async def fetch_ufora_announcements(session: AsyncSession) -> list[UforaNotifica
)
# Get the updated feed
feed = feedparser.parse(course_url)
with async_timeout.timeout(10):
async with http_session.get(course_url) as response:
feed = feedparser.parse(await response.text())
# Remove old notifications
fresh_feed: list[dict] = []
@ -161,6 +167,6 @@ async def fetch_ufora_announcements(session: AsyncSession) -> list[UforaNotifica
notifications.append(notification)
# Create new db entry
await crud.create_new_announcement(session, notification_id, course, notification.published_dt)
await crud.create_new_announcement(database_session, notification_id, course, notification.published_dt)
return notifications

View File

@ -1,6 +1,7 @@
import os
import discord
from aiohttp import ClientSession
from discord.ext import commands
from sqlalchemy.ext.asyncio import AsyncSession
@ -14,6 +15,7 @@ class Didier(commands.Bot):
"""DIDIER <3"""
initial_extensions: tuple[str, ...] = ()
http_session: ClientSession
def __init__(self):
activity = discord.Activity(type=discord.ActivityType.playing, name=settings.DISCORD_STATUS_MESSAGE)
@ -43,6 +45,9 @@ class Didier(commands.Bot):
await self._load_initial_extensions()
await self._load_directory_extensions("didier/cogs")
# Create aiohttp session
self.http_session = ClientSession()
async def _load_initial_extensions(self):
"""Load all extensions that should be loaded before the others"""
for extension in self.initial_extensions:

View File

View File

@ -0,0 +1,25 @@
import math
def interest_upgrade_price(level: int) -> int:
"""Calculate the price to upgrade your interest level"""
base_cost = 600
growth_rate = 1.8
return math.floor(base_cost * (growth_rate**level))
def capacity_upgrade_price(level: int) -> int:
"""Calculate the price to upgrade your capacity level"""
base_cost = 800
growth_rate = 1.6
return math.floor(base_cost * (growth_rate**level))
def rob_upgrade_price(level: int) -> int:
"""Calculate the price to upgrade your rob level"""
base_cost = 950
growth_rate = 1.9
return math.floor(base_cost * (growth_rate**level))