diff --git a/alembic/versions/489dbe73a913_added_login_table.py b/alembic/versions/489dbe73a913_added_login_table.py new file mode 100644 index 0000000..7878add --- /dev/null +++ b/alembic/versions/489dbe73a913_added_login_table.py @@ -0,0 +1,42 @@ +"""Added Login Table + +Revision ID: 489dbe73a913 +Revises: b53c793562c7 +Create Date: 2023-05-16 19:03:34.855509 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utils + + +# revision identifiers, used by Alembic. +revision = "489dbe73a913" +down_revision = "b53c793562c7" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "logins", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("account_id", sa.Integer(), nullable=False), + sa.Column("character_id", sa.Integer(), nullable=True), + sa.Column("login_time", sqlalchemy_utils.types.arrow.ArrowType(), nullable=True), + sa.PrimaryKeyConstraint("id"), + ) + with op.batch_alter_table("characters", schema=None) as batch_op: + batch_op.add_column(sa.Column("last_login", sqlalchemy_utils.types.arrow.ArrowType(), nullable=True)) + + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("characters", schema=None) as batch_op: + batch_op.drop_column("last_login") + + op.drop_table("logins") + # ### end Alembic commands ### diff --git a/dndserver/handlers/character.py b/dndserver/handlers/character.py index a79720e..d5b5071 100644 --- a/dndserver/handlers/character.py +++ b/dndserver/handlers/character.py @@ -1,4 +1,5 @@ import random +import arrow from dndserver.data import perks as pk from dndserver.data import skills as sk @@ -84,7 +85,12 @@ def list_characters(ctx, msg): req = SC2S_ACCOUNT_CHARACTER_LIST_REQ() req.ParseFromString(msg) - query = db.query(Character).filter_by(account_id=sessions[ctx.transport].account.id).all() + query = ( + db.query(Character) + .filter_by(account_id=sessions[ctx.transport].account.id) + .order_by(Character.last_login) + .all() + ) res = SS2C_ACCOUNT_CHARACTER_LIST_RES(totalCharacterCount=len(query), pageIndex=req.pageIndex) start = (res.pageIndex - 1) * 7 @@ -100,7 +106,7 @@ def list_characters(ctx, msg): characterClass=CharacterClass(result.character_class).value, gender=Gender(result.gender).value, createAt=result.created_at.int_timestamp, - # lastloginDate=result.last_logged_at # TODO: Need to implement access logs. + lastloginDate=result.last_login.int_timestamp, ) for item, attributes in inventory.get_all_items(result.id, Define_Item.InventoryId.EQUIPMENT): @@ -137,6 +143,7 @@ def create_character(ctx, msg): streaming_nickname=f"Fighter#{random.randrange(1000000, 1700000)}", gender=Gender(req.gender), character_class=char_class, + last_login=arrow.utcnow(), ) # select the default perks and skills diff --git a/dndserver/handlers/lobby.py b/dndserver/handlers/lobby.py index 884babe..3bdf1d9 100644 --- a/dndserver/handlers/lobby.py +++ b/dndserver/handlers/lobby.py @@ -1,6 +1,7 @@ +import arrow from dndserver.database import db from dndserver.handlers import character -from dndserver.models import Character +from dndserver.models import Character, Login from dndserver.objects.party import Party from dndserver.objects.state import State from dndserver.persistent import parties, sessions @@ -29,6 +30,11 @@ def enter_lobby(ctx, msg): sessions[ctx.transport].character = query sessions[ctx.transport].state = State() + # update the last login time of the character and Login table + query.last_login = arrow.utcnow() + q_login = Login(account_id=query.account_id, login_time=arrow.utcnow(), character_id=query.id) + q_login.save() + party = Party(player_1=sessions[ctx.transport]) sessions[ctx.transport].party = party parties.append(party) diff --git a/dndserver/handlers/login.py b/dndserver/handlers/login.py index 830b277..5c2e1ea 100644 --- a/dndserver/handlers/login.py +++ b/dndserver/handlers/login.py @@ -5,7 +5,7 @@ import arrow from dndserver.database import db -from dndserver.models import Hwid, Account +from dndserver.models import Hwid, Account, Login from dndserver.persistent import sessions from dndserver.protos.Account import SC2S_ACCOUNT_LOGIN_REQ, SLOGIN_ACCOUNT_INFO, SS2C_ACCOUNT_LOGIN_RES from dndserver.protos.Common import SS2C_SERVICE_POLICY_NOT, FSERVICE_POLICY @@ -40,6 +40,10 @@ def process_login(ctx, msg): res.secretToken = account.secret_token + # # add a new login + login = Login(account_id=account.id, login_time=arrow.utcnow()) + login.save() + # Check if an hwId is associated to an account_id, if not add to db for hwid in req.hwIds: if not db.query(Hwid).filter_by(hwid=hwid).filter_by(account_id=account.id).first(): diff --git a/dndserver/models.py b/dndserver/models.py index 8a778ba..3dd4914 100644 --- a/dndserver/models.py +++ b/dndserver/models.py @@ -1,4 +1,5 @@ import arrow + from sqlalchemy import Column from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.types import Boolean, Enum, Integer, String, Text @@ -12,6 +13,19 @@ base = declarative_base() +class Login(base): + __tablename__ = "logins" + + id = Column(Integer, primary_key=True, autoincrement="auto") + account_id = Column(Integer, nullable=False) + character_id = Column(Integer, nullable=True) + login_time = Column(ArrowType, default=arrow.utcnow()) + + def save(self): + db.add(self) + db.commit() + + class Account(base): __tablename__ = "accounts" @@ -40,6 +54,7 @@ class Character(base): experience = Column(Integer, default=0) karma_rating = Column(Integer, default=0) streaming_nickname = Column(String(15)) + last_login = Column(ArrowType, default=arrow.utcnow()) perk0 = Column(String, default="") perk1 = Column(String, default="") @@ -55,7 +70,6 @@ class Character(base): ranking_adventure = Column(Integer, default=0) ranking_lich = Column(Integer, default=0) ranking_ghostking = Column(Integer, default=0) - # TODO: store all logins in a database and grab the latest from that def save(self): db.add(self) @@ -202,8 +216,3 @@ def save(self): def delete(self): db.delete(self) db.commit() - - -# class Login(base): -# __tablename__ = "logins" -# id = Column(Integer, primary_key=True, autoincrement="auto")