diff --git a/app/callbacks/menu.py b/app/callbacks/menu.py
index d485e58..21fbea8 100644
--- a/app/callbacks/menu.py
+++ b/app/callbacks/menu.py
@@ -29,6 +29,7 @@ async def profile_callback(callback: CallbackQuery) -> None:
sex=user.sex.capitalize(),
country=user.country,
city=user.city,
+ date_joined=user.get_human_readable_datejoined(),
),
reply_markup=get(),
)
diff --git a/app/callbacks/profile.py b/app/callbacks/profile.py
index 1b6f04d..f6d404a 100644
--- a/app/callbacks/profile.py
+++ b/app/callbacks/profile.py
@@ -211,6 +211,7 @@ async def profile_change_entered(message: Message, state: FSMContext) -> None:
sex=user.sex.capitalize(),
country=user.country,
city=user.city,
+ date_joined=user.get_human_readable_datejoined(),
),
message.chat.id,
state_data["profile_message_id"],
diff --git a/app/handlers/profile_command.py b/app/handlers/profile_command.py
index 03a76b5..5b05b7d 100644
--- a/app/handlers/profile_command.py
+++ b/app/handlers/profile_command.py
@@ -28,6 +28,7 @@ async def command_profile_handler(message: Message) -> None:
sex=user.sex.capitalize(),
country=user.country,
city=user.city,
+ date_joined=user.get_human_readable_datejoined(),
),
reply_markup=get(),
)
diff --git a/app/messages.py b/app/messages.py
index 4adfdf2..6a1452f 100644
--- a/app/messages.py
+++ b/app/messages.py
@@ -27,6 +27,7 @@ PROFILE = (
"\tCountry: {country}\n"
"\tCity: {city}\n"
"\tBio: {bio}\n"
+ "\tDate joined: {date_joined}\n"
)
NOT_SET = "Not set"
EDIT_USERNAME = "Enter your username:\nAllowed characters: a-z, A-Z, 0-9, _\nLength: 5-20 characters"
diff --git a/app/migrations/versions/1ea8d34d6232_added_user_model.py b/app/migrations/versions/4914f00ae14a_added_user_model.py
similarity index 75%
rename from app/migrations/versions/1ea8d34d6232_added_user_model.py
rename to app/migrations/versions/4914f00ae14a_added_user_model.py
index 06d4f95..57590bf 100644
--- a/app/migrations/versions/1ea8d34d6232_added_user_model.py
+++ b/app/migrations/versions/4914f00ae14a_added_user_model.py
@@ -1,8 +1,8 @@
"""Added User model
-Revision ID: 1ea8d34d6232
+Revision ID: 4914f00ae14a
Revises:
-Create Date: 2024-03-22 00:57:44.526995
+Create Date: 2024-03-22 12:23:37.993976
"""
@@ -13,7 +13,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
-revision: str = '1ea8d34d6232'
+revision: str = '4914f00ae14a'
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
@@ -23,13 +23,21 @@ def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
'users',
- sa.Column('telegram_id', sa.BigInteger(), nullable=False),
+ sa.Column(
+ 'telegram_id', sa.BigInteger(), autoincrement=False, nullable=False
+ ),
sa.Column('username', sa.String(length=32), nullable=False),
sa.Column('age', sa.SmallInteger(), nullable=False),
sa.Column('bio', sa.String(length=100), nullable=True),
sa.Column('sex', sa.String(length=6), nullable=True),
sa.Column('country', sa.Text(), nullable=False),
sa.Column('city', sa.Text(), nullable=False),
+ sa.Column(
+ 'date_joined',
+ sa.DateTime(timezone=True),
+ server_default=sa.text("TIMEZONE('utc', CURRENT_TIMESTAMP)"),
+ nullable=False,
+ ),
sa.PrimaryKeyConstraint('telegram_id'),
sa.UniqueConstraint('username'),
)
diff --git a/app/models/user.py b/app/models/user.py
index f4337d6..a5b27cd 100644
--- a/app/models/user.py
+++ b/app/models/user.py
@@ -9,6 +9,7 @@ from sqlalchemy.orm import validates
from app import session
from app.utils import geo
+from app.utils.db import utcnow
Base: Any = declarative_base()
@@ -23,6 +24,7 @@ class User(Base):
index=True,
unique=True,
nullable=False,
+ autoincrement=False,
)
username = sa.Column(sa.String(32), nullable=False, unique=True)
age = sa.Column(sa.SmallInteger, nullable=False)
@@ -30,6 +32,11 @@ class User(Base):
sex = sa.Column(sa.String(6), nullable=True)
country = sa.Column(sa.Text, nullable=False)
city = sa.Column(sa.Text, nullable=False)
+ date_joined = sa.Column(
+ sa.DateTime(timezone=True),
+ nullable=False,
+ server_default=utcnow(),
+ )
@validates("username")
def validate_username(self, key, value):
@@ -91,6 +98,9 @@ class User(Base):
return normalized_value
+ def get_human_readable_datejoined(self):
+ return self.date_joined.strftime("%Y-%m-%d %H:%M:%S")
+
@classmethod
def get_user_queryset_by_telegram_id(cls, telegram_id):
return session.query(cls).filter(cls.telegram_id == telegram_id)
diff --git a/app/utils/db.py b/app/utils/db.py
new file mode 100644
index 0000000..567cf09
--- /dev/null
+++ b/app/utils/db.py
@@ -0,0 +1,15 @@
+__all__ = ("utcnow",)
+
+from sqlalchemy.ext.compiler import compiles
+from sqlalchemy.sql import expression
+from sqlalchemy.types import DateTime
+
+
+class utcnow(expression.FunctionElement): # noqa: N801
+ type = DateTime() # noqa: A003
+ inherit_cache = True
+
+
+@compiles(utcnow, "postgresql")
+def pg_utcnow(element, compiler, **kw):
+ return "TIMEZONE('utc', CURRENT_TIMESTAMP)"