From c95c17ced172ce502b4d938d368a55b46cec0ade Mon Sep 17 00:00:00 2001 From: Bakk Date: Wed, 10 May 2023 13:07:27 +0200 Subject: [PATCH 01/13] last login character implementation --- ...83_added_last_login_column_to_character.py | 33 +++++++++++++++++++ dndserver/handlers/character.py | 12 +++++-- dndserver/models.py | 1 + 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 alembic/versions/c7772e3df583_added_last_login_column_to_character.py diff --git a/alembic/versions/c7772e3df583_added_last_login_column_to_character.py b/alembic/versions/c7772e3df583_added_last_login_column_to_character.py new file mode 100644 index 00000000..bdbcb40a --- /dev/null +++ b/alembic/versions/c7772e3df583_added_last_login_column_to_character.py @@ -0,0 +1,33 @@ +"""added last_login column to character + +Revision ID: c7772e3df583 +Revises: 64412c0be1f7 +Create Date: 2023-05-10 13:02:07.495640 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utils + + +# revision identifiers, used by Alembic. +revision = "c7772e3df583" +down_revision = "64412c0be1f7" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + 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") + + # ### end Alembic commands ### diff --git a/dndserver/handlers/character.py b/dndserver/handlers/character.py index 1855bc22..c70d25b0 100644 --- a/dndserver/handlers/character.py +++ b/dndserver/handlers/character.py @@ -1,4 +1,6 @@ import random +import arrow +from sqlalchemy import update from dndserver.data import perks as pk from dndserver.data import skills as sk @@ -69,7 +71,8 @@ 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 @@ -85,7 +88,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 # TODO: Need to implement access logs. ) for item, attributes in inventory.get_all_items(result.id, Define_Item.InventoryId.EQUIPMENT): @@ -122,6 +125,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 @@ -222,6 +226,10 @@ def character_info(ctx, msg): level=character.level, ) + # update the last_login column + update_query = update(Character).values(last_login=arrow.utcnow()).where(Character.id == character.id) + db.execute(update_query) + # get all the items and attributes of the character for item, attributes in inventory.get_all_items(character.id): char_info.CharacterItemList.append(item_to_proto_item(item, attributes)) diff --git a/dndserver/models.py b/dndserver/models.py index 682bf99a..7a02cc7c 100644 --- a/dndserver/models.py +++ b/dndserver/models.py @@ -40,6 +40,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="") From 404b853946bd18e3ac0367683dd51bf7533d9e8b Mon Sep 17 00:00:00 2001 From: Bakk Date: Wed, 10 May 2023 14:40:50 +0200 Subject: [PATCH 02/13] Store logins implementation --- .../6fba7ad19a43_added_login_table.py | 44 +++++++++++++++++++ dndserver/handlers/character.py | 22 ++++++++-- dndserver/handlers/login.py | 12 ++++- dndserver/models.py | 24 +++++++--- 4 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 alembic/versions/6fba7ad19a43_added_login_table.py diff --git a/alembic/versions/6fba7ad19a43_added_login_table.py b/alembic/versions/6fba7ad19a43_added_login_table.py new file mode 100644 index 00000000..c229e6df --- /dev/null +++ b/alembic/versions/6fba7ad19a43_added_login_table.py @@ -0,0 +1,44 @@ +"""added Login table + +Revision ID: 6fba7ad19a43 +Revises: c7772e3df583 +Create Date: 2023-05-10 14:30:35.630972 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utils + + +# revision identifiers, used by Alembic. +revision = "6fba7ad19a43" +down_revision = "c7772e3df583" +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.ForeignKeyConstraint( + ["account_id"], + ["accounts.id"], + ), + sa.ForeignKeyConstraint( + ["character_id"], + ["characters.id"], + ), + sa.PrimaryKeyConstraint("id"), + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table("logins") + # ### end Alembic commands ### diff --git a/dndserver/handlers/character.py b/dndserver/handlers/character.py index c70d25b0..7648f852 100644 --- a/dndserver/handlers/character.py +++ b/dndserver/handlers/character.py @@ -8,7 +8,7 @@ from dndserver.database import db from dndserver.enums.classes import CharacterClass, Gender from dndserver.handlers import inventory -from dndserver.models import Character, Item, ItemAttribute, Spell +from dndserver.models import Character, Item, ItemAttribute, Spell, Login from dndserver.persistent import sessions from dndserver.objects import items from dndserver.enums.items import ItemType, Rarity, Item as ItemEnum @@ -211,6 +211,18 @@ def customise_character_info(ctx, msg): return res +def update_last_login(character_id): + update_query = update(Character).values(last_login=arrow.utcnow()).where(Character.id == character_id) + db.execute(update_query) + db.commit() + + +def add_login_character(account_id, character_id): + login = Login(account_id=account_id, login_time=arrow.utcnow(), character_id=character_id) + db.add(login) + db.commit() + + def character_info(ctx, msg): """Occurs when the user loads into the lobby/tavern.""" character = sessions[ctx.transport].character @@ -226,9 +238,11 @@ def character_info(ctx, msg): level=character.level, ) - # update the last_login column - update_query = update(Character).values(last_login=arrow.utcnow()).where(Character.id == character.id) - db.execute(update_query) + # update character table with the last_login of a chararacter + update_last_login(character.id) + + # update login table with account_id and character_id + add_login_character(character.account_id, character.id) # get all the items and attributes of the character for item, attributes in inventory.get_all_items(character.id): diff --git a/dndserver/handlers/login.py b/dndserver/handlers/login.py index c7a1a8cd..ed0062ba 100644 --- a/dndserver/handlers/login.py +++ b/dndserver/handlers/login.py @@ -2,9 +2,10 @@ import string import argon2 +import arrow from dndserver.database import db -from dndserver.models import Account +from dndserver.models import Account, Login from dndserver.persistent import sessions from dndserver.protos.Account import SC2S_ACCOUNT_LOGIN_REQ, SLOGIN_ACCOUNT_INFO, SS2C_ACCOUNT_LOGIN_RES @@ -39,6 +40,9 @@ def process_login(ctx, msg): # TODO: Create new hwid objects and save them to the db here res.secretToken = account.secret_token + # update_logins_by_account(account.id) + add_login(account.id) + # Return FAIL_PASSWORD on invalid password. try: argon2.PasswordHasher().verify(account.password, req.password) @@ -69,3 +73,9 @@ def kick_concurrent_user(newly_connected_account): if user.account == newly_connected_account: transport.loseConnection() break + + +def add_login(account_id): + login = Login(account_id=account_id, login_time=arrow.utcnow()) + db.add(login) + db.commit() diff --git a/dndserver/models.py b/dndserver/models.py index 7a02cc7c..092a4cb6 100644 --- a/dndserver/models.py +++ b/dndserver/models.py @@ -1,6 +1,7 @@ import arrow -from sqlalchemy import Column +from sqlalchemy import Column, ForeignKey from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship from sqlalchemy.types import Boolean, Enum, Integer, String, Text from sqlalchemy_utils import ArrowType @@ -12,6 +13,20 @@ base = declarative_base() +class Login(base): + __tablename__ = "logins" + + id = Column(Integer, primary_key=True, autoincrement="auto") + account_id = Column(Integer, ForeignKey('accounts.id'), nullable=False) + character_id = Column(Integer, ForeignKey('characters.id'), nullable=True) + login_time = Column(ArrowType, default=arrow.utcnow()) + account = relationship("Account", backref="logins") + + def save(self): + db.add(self) + db.commit() + + class Account(base): __tablename__ = "accounts" @@ -41,6 +56,7 @@ class Character(base): karma_rating = Column(Integer, default=0) streaming_nickname = Column(String(15)) last_login = Column(ArrowType, default=arrow.utcnow()) + # TODO: store all logins in a database and grab the latest from that perk0 = Column(String, default="") perk1 = Column(String, default="") @@ -56,7 +72,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) @@ -179,8 +194,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") From 278605ccfcbba285a9c31c11c34e32b02c6db5ec Mon Sep 17 00:00:00 2001 From: Bakk Date: Wed, 10 May 2023 16:11:57 +0200 Subject: [PATCH 03/13] cleaned code smells --- ...e.py => 6aec8b735541_added_login_table.py} | 6 ++--- dndserver/handlers/character.py | 22 +++++-------------- dndserver/models.py | 1 + 3 files changed, 10 insertions(+), 19 deletions(-) rename alembic/versions/{6fba7ad19a43_added_login_table.py => 6aec8b735541_added_login_table.py} (92%) diff --git a/alembic/versions/6fba7ad19a43_added_login_table.py b/alembic/versions/6aec8b735541_added_login_table.py similarity index 92% rename from alembic/versions/6fba7ad19a43_added_login_table.py rename to alembic/versions/6aec8b735541_added_login_table.py index c229e6df..7dd268d1 100644 --- a/alembic/versions/6fba7ad19a43_added_login_table.py +++ b/alembic/versions/6aec8b735541_added_login_table.py @@ -1,8 +1,8 @@ """added Login table -Revision ID: 6fba7ad19a43 +Revision ID: 6aec8b735541 Revises: c7772e3df583 -Create Date: 2023-05-10 14:30:35.630972 +Create Date: 2023-05-10 15:47:44.516564 """ from alembic import op @@ -11,7 +11,7 @@ # revision identifiers, used by Alembic. -revision = "6fba7ad19a43" +revision = "6aec8b735541" down_revision = "c7772e3df583" branch_labels = None depends_on = None diff --git a/dndserver/handlers/character.py b/dndserver/handlers/character.py index 7648f852..b273797a 100644 --- a/dndserver/handlers/character.py +++ b/dndserver/handlers/character.py @@ -211,18 +211,6 @@ def customise_character_info(ctx, msg): return res -def update_last_login(character_id): - update_query = update(Character).values(last_login=arrow.utcnow()).where(Character.id == character_id) - db.execute(update_query) - db.commit() - - -def add_login_character(account_id, character_id): - login = Login(account_id=account_id, login_time=arrow.utcnow(), character_id=character_id) - db.add(login) - db.commit() - - def character_info(ctx, msg): """Occurs when the user loads into the lobby/tavern.""" character = sessions[ctx.transport].character @@ -238,11 +226,13 @@ def character_info(ctx, msg): level=character.level, ) - # update character table with the last_login of a chararacter - update_last_login(character.id) + # update character table with the last_login chararacter date + q_update = update(Character).values(last_login=arrow.utcnow()).where(Character.id == character.id) + db.execute(q_update) - # update login table with account_id and character_id - add_login_character(character.account_id, character.id) + # update login table with account_id and character_id date + q_login = Login(account_id=character.account_id, login_time=arrow.utcnow(), character_id=character.id) + Login.save(q_login) # get all the items and attributes of the character for item, attributes in inventory.get_all_items(character.id): diff --git a/dndserver/models.py b/dndserver/models.py index 092a4cb6..a33d300a 100644 --- a/dndserver/models.py +++ b/dndserver/models.py @@ -21,6 +21,7 @@ class Login(base): character_id = Column(Integer, ForeignKey('characters.id'), nullable=True) login_time = Column(ArrowType, default=arrow.utcnow()) account = relationship("Account", backref="logins") + character = relationship("Character", backref="logins") def save(self): db.add(self) From 3b5356a6234bd478a7a28dfe52078c954ff83db7 Mon Sep 17 00:00:00 2001 From: Bakk Date: Wed, 10 May 2023 17:25:43 +0200 Subject: [PATCH 04/13] query change, no more update(); login_table now updating correctly --- dndserver/handlers/character.py | 22 ++++++++++++++++------ dndserver/handlers/login.py | 4 ++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/dndserver/handlers/character.py b/dndserver/handlers/character.py index b273797a..f7e6de64 100644 --- a/dndserver/handlers/character.py +++ b/dndserver/handlers/character.py @@ -1,6 +1,5 @@ import random import arrow -from sqlalchemy import update from dndserver.data import perks as pk from dndserver.data import skills as sk @@ -8,7 +7,7 @@ from dndserver.database import db from dndserver.enums.classes import CharacterClass, Gender from dndserver.handlers import inventory -from dndserver.models import Character, Item, ItemAttribute, Spell, Login +from dndserver.models import Character, Item, ItemAttribute, Login, Spell from dndserver.persistent import sessions from dndserver.objects import items from dndserver.enums.items import ItemType, Rarity, Item as ItemEnum @@ -227,12 +226,15 @@ def character_info(ctx, msg): ) # update character table with the last_login chararacter date - q_update = update(Character).values(last_login=arrow.utcnow()).where(Character.id == character.id) - db.execute(q_update) + login_char = db.query(Character).filter(Character.id.ilike(character.id)).first() + login_char.last_login = arrow.utcnow() + login_char.save() # update login table with account_id and character_id date - q_login = Login(account_id=character.account_id, login_time=arrow.utcnow(), character_id=character.id) - Login.save(q_login) + # login_account = db.query(Login).filter(Login.account_id.ilike(character.account_id)).first() + # login_account.character_id = character.id + # login_account.login_time = arrow.utcnow() + # login_account.save() # get all the items and attributes of the character for item, attributes in inventory.get_all_items(character.id): @@ -243,6 +245,12 @@ def character_info(ctx, msg): return res +# update login table with account_id and character_id date +def update_login(account_id, character_id): + q_login = Login(account_id=account_id, login_time=arrow.utcnow(), character_id=character_id) + q_login.save() + + def get_experience(ctx, msg): """Occurs when the user loads into the lobby.""" character = sessions[ctx.transport].character @@ -255,6 +263,8 @@ def get_experience(ctx, msg): # 1 - 4 = 40 exp, 5 - 9 = 60 exp, 10 - 14 = 80 exp, 15 - 19 = 100 res.expLimit = 40 + (int(character.level / 5) * 20) + update_login(character.account_id, character.id) + return res diff --git a/dndserver/handlers/login.py b/dndserver/handlers/login.py index ed0062ba..0b3697e3 100644 --- a/dndserver/handlers/login.py +++ b/dndserver/handlers/login.py @@ -75,7 +75,7 @@ def kick_concurrent_user(newly_connected_account): break +# add a new login def add_login(account_id): login = Login(account_id=account_id, login_time=arrow.utcnow()) - db.add(login) - db.commit() + login.save() From 65e3f466ddeaef00868ce45a700175a35b7d84ec Mon Sep 17 00:00:00 2001 From: Bakk Date: Wed, 10 May 2023 18:03:11 +0200 Subject: [PATCH 05/13] cleaned smells --- dndserver/handlers/character.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/dndserver/handlers/character.py b/dndserver/handlers/character.py index f7e6de64..da57f3a6 100644 --- a/dndserver/handlers/character.py +++ b/dndserver/handlers/character.py @@ -230,12 +230,6 @@ def character_info(ctx, msg): login_char.last_login = arrow.utcnow() login_char.save() - # update login table with account_id and character_id date - # login_account = db.query(Login).filter(Login.account_id.ilike(character.account_id)).first() - # login_account.character_id = character.id - # login_account.login_time = arrow.utcnow() - # login_account.save() - # get all the items and attributes of the character for item, attributes in inventory.get_all_items(character.id): char_info.CharacterItemList.append(item_to_proto_item(item, attributes)) @@ -245,8 +239,8 @@ def character_info(ctx, msg): return res -# update login table with account_id and character_id date def update_login(account_id, character_id): + """Update login table with account_id and character_id date """ q_login = Login(account_id=account_id, login_time=arrow.utcnow(), character_id=character_id) q_login.save() @@ -263,6 +257,7 @@ def get_experience(ctx, msg): # 1 - 4 = 40 exp, 5 - 9 = 60 exp, 10 - 14 = 80 exp, 15 - 19 = 100 res.expLimit = 40 + (int(character.level / 5) * 20) + # Update the login table here, becouse get_experience() is called only once update_login(character.account_id, character.id) return res From 32ecfe48f99bbc9abcb9d25fe15a727a5cac60f4 Mon Sep 17 00:00:00 2001 From: Bakk Date: Wed, 10 May 2023 19:32:23 +0200 Subject: [PATCH 06/13] deleted alembic file --- .../6aec8b735541_added_login_table.py | 44 ------------------- ...83_added_last_login_column_to_character.py | 33 -------------- 2 files changed, 77 deletions(-) delete mode 100644 alembic/versions/6aec8b735541_added_login_table.py delete mode 100644 alembic/versions/c7772e3df583_added_last_login_column_to_character.py diff --git a/alembic/versions/6aec8b735541_added_login_table.py b/alembic/versions/6aec8b735541_added_login_table.py deleted file mode 100644 index 7dd268d1..00000000 --- a/alembic/versions/6aec8b735541_added_login_table.py +++ /dev/null @@ -1,44 +0,0 @@ -"""added Login table - -Revision ID: 6aec8b735541 -Revises: c7772e3df583 -Create Date: 2023-05-10 15:47:44.516564 - -""" -from alembic import op -import sqlalchemy as sa -import sqlalchemy_utils - - -# revision identifiers, used by Alembic. -revision = "6aec8b735541" -down_revision = "c7772e3df583" -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.ForeignKeyConstraint( - ["account_id"], - ["accounts.id"], - ), - sa.ForeignKeyConstraint( - ["character_id"], - ["characters.id"], - ), - sa.PrimaryKeyConstraint("id"), - ) - # ### end Alembic commands ### - - -def downgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table("logins") - # ### end Alembic commands ### diff --git a/alembic/versions/c7772e3df583_added_last_login_column_to_character.py b/alembic/versions/c7772e3df583_added_last_login_column_to_character.py deleted file mode 100644 index bdbcb40a..00000000 --- a/alembic/versions/c7772e3df583_added_last_login_column_to_character.py +++ /dev/null @@ -1,33 +0,0 @@ -"""added last_login column to character - -Revision ID: c7772e3df583 -Revises: 64412c0be1f7 -Create Date: 2023-05-10 13:02:07.495640 - -""" -from alembic import op -import sqlalchemy as sa -import sqlalchemy_utils - - -# revision identifiers, used by Alembic. -revision = "c7772e3df583" -down_revision = "64412c0be1f7" -branch_labels = None -depends_on = None - - -def upgrade() -> None: - # ### commands auto generated by Alembic - please adjust! ### - 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") - - # ### end Alembic commands ### From 3f9df87cc57bdb7a2defe3dfb8e327d57c65f9ef Mon Sep 17 00:00:00 2001 From: Bakk Date: Wed, 10 May 2023 20:21:14 +0200 Subject: [PATCH 07/13] Better position for updating login table; Cleaned smells; Removed Foreign Key; --- dndserver/handlers/character.py | 18 ++---------------- dndserver/handlers/lobby.py | 13 ++++++++++++- dndserver/models.py | 11 ++++------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/dndserver/handlers/character.py b/dndserver/handlers/character.py index da57f3a6..7f82f479 100644 --- a/dndserver/handlers/character.py +++ b/dndserver/handlers/character.py @@ -7,7 +7,7 @@ from dndserver.database import db from dndserver.enums.classes import CharacterClass, Gender from dndserver.handlers import inventory -from dndserver.models import Character, Item, ItemAttribute, Login, Spell +from dndserver.models import Character, Item, ItemAttribute, Spell from dndserver.persistent import sessions from dndserver.objects import items from dndserver.enums.items import ItemType, Rarity, Item as ItemEnum @@ -87,7 +87,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_login.int_timestamp # 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): @@ -225,11 +225,6 @@ def character_info(ctx, msg): level=character.level, ) - # update character table with the last_login chararacter date - login_char = db.query(Character).filter(Character.id.ilike(character.id)).first() - login_char.last_login = arrow.utcnow() - login_char.save() - # get all the items and attributes of the character for item, attributes in inventory.get_all_items(character.id): char_info.CharacterItemList.append(item_to_proto_item(item, attributes)) @@ -239,12 +234,6 @@ def character_info(ctx, msg): return res -def update_login(account_id, character_id): - """Update login table with account_id and character_id date """ - q_login = Login(account_id=account_id, login_time=arrow.utcnow(), character_id=character_id) - q_login.save() - - def get_experience(ctx, msg): """Occurs when the user loads into the lobby.""" character = sessions[ctx.transport].character @@ -257,9 +246,6 @@ def get_experience(ctx, msg): # 1 - 4 = 40 exp, 5 - 9 = 60 exp, 10 - 14 = 80 exp, 15 - 19 = 100 res.expLimit = 40 + (int(character.level / 5) * 20) - # Update the login table here, becouse get_experience() is called only once - update_login(character.account_id, character.id) - return res diff --git a/dndserver/handlers/lobby.py b/dndserver/handlers/lobby.py index 218f4e2f..725d96af 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.persistent import parties, sessions from dndserver.protos import PacketCommand as pc @@ -27,6 +28,16 @@ def enter_lobby(ctx, msg): sessions[ctx.transport].character = query + # update the last login time of the character + query.last_login = arrow.utcnow() + q_login = Login(account_id=query.account_id, login_time=arrow.utcnow(), character_id=query.id) + q_login.save() + + # update character table with the last_login chararacter date + login_char = db.query(Character).filter(Character.id.ilike(query.id)).first() + login_char.last_login = arrow.utcnow() + login_char.save() + party = Party(player_1=sessions[ctx.transport]) sessions[ctx.transport].party = party parties.append(party) diff --git a/dndserver/models.py b/dndserver/models.py index a33d300a..201fd4ae 100644 --- a/dndserver/models.py +++ b/dndserver/models.py @@ -1,7 +1,7 @@ import arrow -from sqlalchemy import Column, ForeignKey + +from sqlalchemy import Column from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import relationship from sqlalchemy.types import Boolean, Enum, Integer, String, Text from sqlalchemy_utils import ArrowType @@ -17,11 +17,9 @@ class Login(base): __tablename__ = "logins" id = Column(Integer, primary_key=True, autoincrement="auto") - account_id = Column(Integer, ForeignKey('accounts.id'), nullable=False) - character_id = Column(Integer, ForeignKey('characters.id'), nullable=True) + account_id = Column(Integer, nullable=False) + character_id = Column(Integer, nullable=True) login_time = Column(ArrowType, default=arrow.utcnow()) - account = relationship("Account", backref="logins") - character = relationship("Character", backref="logins") def save(self): db.add(self) @@ -57,7 +55,6 @@ class Character(base): karma_rating = Column(Integer, default=0) streaming_nickname = Column(String(15)) last_login = Column(ArrowType, default=arrow.utcnow()) - # TODO: store all logins in a database and grab the latest from that perk0 = Column(String, default="") perk1 = Column(String, default="") From 8ad12e0654aafe3767e50acb2962fdf3a906ba9f Mon Sep 17 00:00:00 2001 From: Bakk Date: Wed, 10 May 2023 20:48:31 +0200 Subject: [PATCH 08/13] Corrected leftover errors --- dndserver/handlers/lobby.py | 7 +------ dndserver/handlers/login.py | 11 +++-------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/dndserver/handlers/lobby.py b/dndserver/handlers/lobby.py index 725d96af..7284c728 100644 --- a/dndserver/handlers/lobby.py +++ b/dndserver/handlers/lobby.py @@ -28,16 +28,11 @@ def enter_lobby(ctx, msg): sessions[ctx.transport].character = query - # update the last login time of the character + # 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() - # update character table with the last_login chararacter date - login_char = db.query(Character).filter(Character.id.ilike(query.id)).first() - login_char.last_login = arrow.utcnow() - login_char.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 0b3697e3..91f9ebd5 100644 --- a/dndserver/handlers/login.py +++ b/dndserver/handlers/login.py @@ -40,8 +40,9 @@ def process_login(ctx, msg): # TODO: Create new hwid objects and save them to the db here res.secretToken = account.secret_token - # update_logins_by_account(account.id) - add_login(account.id) + # # add a new login + login = Login(account_id=account.id, login_time=arrow.utcnow()) + login.save() # Return FAIL_PASSWORD on invalid password. try: @@ -73,9 +74,3 @@ def kick_concurrent_user(newly_connected_account): if user.account == newly_connected_account: transport.loseConnection() break - - -# add a new login -def add_login(account_id): - login = Login(account_id=account_id, login_time=arrow.utcnow()) - login.save() From 86bb3f1f556fd9b9b3442513052877a869701dfb Mon Sep 17 00:00:00 2001 From: Bakk Date: Wed, 10 May 2023 20:50:48 +0200 Subject: [PATCH 09/13] black format indentation --- dndserver/handlers/character.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dndserver/handlers/character.py b/dndserver/handlers/character.py index 7f82f479..efdff96a 100644 --- a/dndserver/handlers/character.py +++ b/dndserver/handlers/character.py @@ -70,8 +70,10 @@ 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).order_by(Character.last_login).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 From 74fbc7bd809841a1f88dd14275ca9969f9ba38fa Mon Sep 17 00:00:00 2001 From: Bakk Date: Fri, 12 May 2023 17:33:06 +0200 Subject: [PATCH 10/13] Added alembic file --- alembic/e0609644dd8c_added_login_table.py | 42 +++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 alembic/e0609644dd8c_added_login_table.py diff --git a/alembic/e0609644dd8c_added_login_table.py b/alembic/e0609644dd8c_added_login_table.py new file mode 100644 index 00000000..39f09849 --- /dev/null +++ b/alembic/e0609644dd8c_added_login_table.py @@ -0,0 +1,42 @@ +"""added Login table + +Revision ID: e0609644dd8c +Revises: 64412c0be1f7 +Create Date: 2023-05-10 20:07:24.540366 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utils + + +# revision identifiers, used by Alembic. +revision = "e0609644dd8c" +down_revision = "64412c0be1f7" +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 ### From 9456a4a7bb4758ab266be77b9fbe75e469fece9c Mon Sep 17 00:00:00 2001 From: Bakk Date: Sun, 14 May 2023 15:37:49 +0200 Subject: [PATCH 11/13] coorected alembic file location --- alembic/{ => versions}/e0609644dd8c_added_login_table.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename alembic/{ => versions}/e0609644dd8c_added_login_table.py (100%) diff --git a/alembic/e0609644dd8c_added_login_table.py b/alembic/versions/e0609644dd8c_added_login_table.py similarity index 100% rename from alembic/e0609644dd8c_added_login_table.py rename to alembic/versions/e0609644dd8c_added_login_table.py From d1f83d4e061965148ad88037269d51285e0b1840 Mon Sep 17 00:00:00 2001 From: Bakk Date: Mon, 15 May 2023 16:40:16 +0200 Subject: [PATCH 12/13] back formatting --- dndserver/handlers/character.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/dndserver/handlers/character.py b/dndserver/handlers/character.py index efdff96a..ab6eb7bf 100644 --- a/dndserver/handlers/character.py +++ b/dndserver/handlers/character.py @@ -70,10 +70,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) - .order_by(Character.last_login) - .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 @@ -89,7 +91,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_login.int_timestamp + lastloginDate=result.last_login.int_timestamp, ) for item, attributes in inventory.get_all_items(result.id, Define_Item.InventoryId.EQUIPMENT): From ea7a200b223c53fec125597b752834d3632e6636 Mon Sep 17 00:00:00 2001 From: Bakk Date: Tue, 16 May 2023 19:05:59 +0200 Subject: [PATCH 13/13] alembic heads correction --- ...in_table.py => 489dbe73a913_added_login_table.py} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename alembic/versions/{e0609644dd8c_added_login_table.py => 489dbe73a913_added_login_table.py} (86%) diff --git a/alembic/versions/e0609644dd8c_added_login_table.py b/alembic/versions/489dbe73a913_added_login_table.py similarity index 86% rename from alembic/versions/e0609644dd8c_added_login_table.py rename to alembic/versions/489dbe73a913_added_login_table.py index 39f09849..7878add2 100644 --- a/alembic/versions/e0609644dd8c_added_login_table.py +++ b/alembic/versions/489dbe73a913_added_login_table.py @@ -1,8 +1,8 @@ -"""added Login table +"""Added Login Table -Revision ID: e0609644dd8c -Revises: 64412c0be1f7 -Create Date: 2023-05-10 20:07:24.540366 +Revision ID: 489dbe73a913 +Revises: b53c793562c7 +Create Date: 2023-05-16 19:03:34.855509 """ from alembic import op @@ -11,8 +11,8 @@ # revision identifiers, used by Alembic. -revision = "e0609644dd8c" -down_revision = "64412c0be1f7" +revision = "489dbe73a913" +down_revision = "b53c793562c7" branch_labels = None depends_on = None