1
0
mirror of synced 2024-12-25 10:44:51 +01:00
artemis/titles/mai2/schema/profile.py
2023-08-08 10:17:56 -04:00

818 lines
27 KiB
Python

from core.data.schema import BaseData, metadata
from titles.mai2.const import Mai2Constants
from typing import Optional, Dict, List
from sqlalchemy import Table, Column, UniqueConstraint, PrimaryKeyConstraint, and_
from sqlalchemy.types import Integer, String, TIMESTAMP, Boolean, JSON, BigInteger
from sqlalchemy.schema import ForeignKey
from sqlalchemy.sql import func, select
from sqlalchemy.engine import Row
from sqlalchemy.dialects.mysql import insert
from datetime import datetime
detail = Table(
"mai2_profile_detail",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column(
"user",
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
nullable=False,
),
Column("version", Integer, nullable=False),
Column("userName", String(25)),
Column("isNetMember", Integer),
Column("iconId", Integer),
Column("plateId", Integer),
Column("titleId", Integer),
Column("partnerId", Integer),
Column("frameId", Integer),
Column("selectMapId", Integer),
Column("totalAwake", Integer),
Column("gradeRating", Integer),
Column("musicRating", Integer),
Column("playerRating", Integer),
Column("highestRating", Integer),
Column("gradeRank", Integer),
Column("classRank", Integer),
Column("courseRank", Integer),
Column("charaSlot", JSON),
Column("charaLockSlot", JSON),
Column("contentBit", BigInteger),
Column("playCount", Integer),
Column("eventWatchedDate", String(25)),
Column("lastGameId", String(25)),
Column("lastRomVersion", String(25)),
Column("lastDataVersion", String(25)),
Column("lastLoginDate", String(25)),
Column("lastPairLoginDate", String(25)), # new with uni+
Column("lastPlayDate", String(25)),
Column("lastTrialPlayDate", String(25)), # new with uni+
Column("lastPlayCredit", Integer),
Column("lastPlayMode", Integer),
Column("lastPlaceId", Integer),
Column("lastPlaceName", String(25)),
Column("lastAllNetId", Integer),
Column("lastRegionId", Integer),
Column("lastRegionName", String(25)),
Column("lastClientId", String(25)),
Column("lastCountryCode", String(25)),
Column("lastSelectEMoney", Integer),
Column("lastSelectTicket", Integer),
Column("lastSelectCourse", Integer),
Column("lastCountCourse", Integer),
Column("firstGameId", String(25)),
Column("firstRomVersion", String(25)),
Column("firstDataVersion", String(25)),
Column("firstPlayDate", String(25)),
Column("compatibleCmVersion", String(25)),
Column("dailyBonusDate", String(25)),
Column("dailyCourseBonusDate", String(25)),
Column("playVsCount", Integer),
Column("playSyncCount", Integer),
Column("winCount", Integer),
Column("helpCount", Integer),
Column("comboCount", Integer),
Column("totalDeluxscore", BigInteger),
Column("totalBasicDeluxscore", BigInteger),
Column("totalAdvancedDeluxscore", BigInteger),
Column("totalExpertDeluxscore", BigInteger),
Column("totalMasterDeluxscore", BigInteger),
Column("totalReMasterDeluxscore", BigInteger),
Column("totalSync", Integer),
Column("totalBasicSync", Integer),
Column("totalAdvancedSync", Integer),
Column("totalExpertSync", Integer),
Column("totalMasterSync", Integer),
Column("totalReMasterSync", Integer),
Column("totalAchievement", BigInteger),
Column("totalBasicAchievement", BigInteger),
Column("totalAdvancedAchievement", BigInteger),
Column("totalExpertAchievement", BigInteger),
Column("totalMasterAchievement", BigInteger),
Column("totalReMasterAchievement", BigInteger),
Column("playerOldRating", BigInteger),
Column("playerNewRating", BigInteger),
Column("dateTime", BigInteger),
Column("banState", Integer), # new with uni+
UniqueConstraint("user", "version", name="mai2_profile_detail_uk"),
mysql_charset="utf8mb4",
)
detail_old = Table(
"maimai_profile_detail",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column(
"user",
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
nullable=False,
),
Column("version", Integer, nullable=False),
Column("lastDataVersion", Integer),
Column("userName", String(8)),
Column("point", Integer),
Column("totalPoint", Integer),
Column("iconId", Integer),
Column("nameplateId", Integer),
Column("frameId", Integer),
Column("trophyId", Integer),
Column("playCount", Integer),
Column("playVsCount", Integer),
Column("playSyncCount", Integer),
Column("winCount", Integer),
Column("helpCount", Integer),
Column("comboCount", Integer),
Column("feverCount", Integer),
Column("totalHiScore", Integer),
Column("totalEasyHighScore", Integer),
Column("totalBasicHighScore", Integer),
Column("totalAdvancedHighScore", Integer),
Column("totalExpertHighScore", Integer),
Column("totalMasterHighScore", Integer),
Column("totalReMasterHighScore", Integer),
Column("totalHighSync", Integer),
Column("totalEasySync", Integer),
Column("totalBasicSync", Integer),
Column("totalAdvancedSync", Integer),
Column("totalExpertSync", Integer),
Column("totalMasterSync", Integer),
Column("totalReMasterSync", Integer),
Column("playerRating", Integer),
Column("highestRating", Integer),
Column("rankAuthTailId", Integer),
Column("eventWatchedDate", String(255)),
Column("webLimitDate", String(255)),
Column("challengeTrackPhase", Integer),
Column("firstPlayBits", Integer),
Column("lastPlayDate", String(255)),
Column("lastPlaceId", Integer),
Column("lastPlaceName", String(255)),
Column("lastRegionId", Integer),
Column("lastRegionName", String(255)),
Column("lastClientId", String(255)),
Column("lastCountryCode", String(255)),
Column("eventPoint", Integer),
Column("totalLv", Integer),
Column("lastLoginBonusDay", Integer),
Column("lastSurvivalBonusDay", Integer),
Column("loginBonusLv", Integer),
UniqueConstraint("user", "version", name="maimai_profile_detail_uk"),
mysql_charset="utf8mb4",
)
ghost = Table(
"mai2_profile_ghost",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column(
"user",
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
nullable=False,
),
Column("version_int", Integer, nullable=False),
Column("name", String(25)),
Column("iconId", Integer),
Column("plateId", Integer),
Column("titleId", Integer),
Column("rate", Integer),
Column("udemaeRate", Integer),
Column("courseRank", Integer),
Column("classRank", Integer),
Column("classValue", Integer),
Column("playDatetime", String(25)),
Column("shopId", Integer),
Column("regionCode", Integer),
Column("typeId", Integer),
Column("musicId", Integer),
Column("difficulty", Integer),
Column("version", Integer),
Column("resultBitList", JSON),
Column("resultNum", Integer),
Column("achievement", Integer),
UniqueConstraint(
"user", "version", "musicId", "difficulty", name="mai2_profile_ghost_uk"
),
mysql_charset="utf8mb4",
)
extend = Table(
"mai2_profile_extend",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column(
"user",
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
nullable=False,
),
Column("version", Integer, nullable=False),
Column("selectMusicId", Integer),
Column("selectDifficultyId", Integer),
Column("categoryIndex", Integer),
Column("musicIndex", Integer),
Column("extraFlag", Integer),
Column("selectScoreType", Integer),
Column("extendContentBit", BigInteger),
Column("isPhotoAgree", Boolean),
Column("isGotoCodeRead", Boolean),
Column("selectResultDetails", Boolean),
Column("sortCategorySetting", Integer),
Column("sortMusicSetting", Integer),
Column("selectedCardList", JSON),
Column("encountMapNpcList", JSON),
Column("playStatusSetting", Integer, server_default="0"),
UniqueConstraint("user", "version", name="mai2_profile_extend_uk"),
mysql_charset="utf8mb4",
)
option = Table(
"mai2_profile_option",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column(
"user",
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
nullable=False,
),
Column("version", Integer, nullable=False),
Column("selectMusicId", Integer),
Column("optionKind", Integer),
Column("noteSpeed", Integer),
Column("slideSpeed", Integer),
Column("touchSpeed", Integer),
Column("tapDesign", Integer),
Column("tapSe", Integer, server_default="0"),
Column("holdDesign", Integer),
Column("slideDesign", Integer),
Column("starType", Integer),
Column("outlineDesign", Integer),
Column("noteSize", Integer),
Column("slideSize", Integer),
Column("touchSize", Integer),
Column("starRotate", Integer),
Column("dispCenter", Integer),
Column("dispChain", Integer),
Column("dispRate", Integer),
Column("dispBar", Integer),
Column("touchEffect", Integer),
Column("submonitorAnimation", Integer),
Column("submonitorAchive", Integer),
Column("submonitorAppeal", Integer),
Column("matching", Integer),
Column("trackSkip", Integer),
Column("brightness", Integer),
Column("mirrorMode", Integer),
Column("dispJudge", Integer),
Column("dispJudgePos", Integer),
Column("dispJudgeTouchPos", Integer),
Column("adjustTiming", Integer),
Column("judgeTiming", Integer),
Column("ansVolume", Integer),
Column("tapHoldVolume", Integer),
Column("criticalSe", Integer),
Column("breakSe", Integer),
Column("breakVolume", Integer),
Column("exSe", Integer),
Column("exVolume", Integer),
Column("slideSe", Integer),
Column("slideVolume", Integer),
Column("touchHoldVolume", Integer),
Column("damageSeVolume", Integer),
Column("headPhoneVolume", Integer),
Column("sortTab", Integer),
Column("sortMusic", Integer),
UniqueConstraint("user", "version", name="mai2_profile_option_uk"),
mysql_charset="utf8mb4",
)
option_old = Table(
"maimai_profile_option",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column(
"user",
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
nullable=False,
),
Column("version", Integer, nullable=False),
Column("soudEffect", Integer),
Column("mirrorMode", Integer),
Column("guideSpeed", Integer),
Column("bgInfo", Integer),
Column("brightness", Integer),
Column("isStarRot", Integer),
Column("breakSe", Integer),
Column("slideSe", Integer),
Column("hardJudge", Integer),
Column("isTagJump", Integer),
Column("breakSeVol", Integer),
Column("slideSeVol", Integer),
Column("isUpperDisp", Integer),
Column("trackSkip", Integer),
Column("optionMode", Integer),
Column("simpleOptionParam", Integer),
Column("adjustTiming", Integer),
Column("dispTiming", Integer),
Column("timingPos", Integer),
Column("ansVol", Integer),
Column("noteVol", Integer),
Column("dmgVol", Integer),
Column("appealFlame", Integer),
Column("isFeverDisp", Integer),
Column("dispJudge", Integer),
Column("judgePos", Integer),
Column("ratingGuard", Integer),
Column("selectChara", Integer),
Column("sortType", Integer),
Column("filterGenre", Integer),
Column("filterLevel", Integer),
Column("filterRank", Integer),
Column("filterVersion", Integer),
Column("filterRec", Integer),
Column("filterFullCombo", Integer),
Column("filterAllPerfect", Integer),
Column("filterDifficulty", Integer),
Column("filterFullSync", Integer),
Column("filterReMaster", Integer),
Column("filterMaxFever", Integer),
Column("finalSelectId", Integer),
Column("finalSelectCategory", Integer),
UniqueConstraint("user", "version", name="maimai_profile_option_uk"),
mysql_charset="utf8mb4",
)
web_opt = Table(
"maimai_profile_web_option",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column(
"user",
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
nullable=False,
),
Column("version", Integer, nullable=False),
Column("isNetMember", Boolean),
Column("dispRate", Integer),
Column("dispJudgeStyle", Integer),
Column("dispRank", Integer),
Column("dispHomeRanker", Integer),
Column("dispTotalLv", Integer),
UniqueConstraint("user", "version", name="maimai_profile_web_option_uk"),
mysql_charset="utf8mb4",
)
grade_status = Table(
"maimai_profile_grade_status",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column(
"user",
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
nullable=False,
),
Column("gradeVersion", Integer),
Column("gradeLevel", Integer),
Column("gradeSubLevel", Integer),
Column("gradeMaxId", Integer),
UniqueConstraint("user", "gradeVersion", name="maimai_profile_grade_status_uk"),
mysql_charset="utf8mb4",
)
rating = Table(
"mai2_profile_rating",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column(
"user",
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
nullable=False,
),
Column("version", Integer, nullable=False),
Column("rating", Integer),
Column("ratingList", JSON),
Column("newRatingList", JSON),
Column("nextRatingList", JSON),
Column("nextNewRatingList", JSON),
Column("udemae", JSON),
UniqueConstraint("user", "version", name="mai2_profile_rating_uk"),
mysql_charset="utf8mb4",
)
region = Table(
"mai2_profile_region",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column(
"user",
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
nullable=False,
),
Column("regionId", Integer),
Column("playCount", Integer, server_default="1"),
Column("created", String(25)),
UniqueConstraint("user", "regionId", name="mai2_profile_region_uk"),
mysql_charset="utf8mb4",
)
activity = Table(
"mai2_profile_activity",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column(
"user",
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
nullable=False,
),
Column("kind", Integer),
Column("activityId", Integer),
Column("param1", Integer),
Column("param2", Integer),
Column("param3", Integer),
Column("param4", Integer),
Column("sortNumber", Integer),
UniqueConstraint("user", "kind", "activityId", name="mai2_profile_activity_uk"),
mysql_charset="utf8mb4",
)
boss = Table(
"maimai_profile_boss",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("pandoraFlagList0", Integer),
Column("pandoraFlagList1", Integer),
Column("pandoraFlagList2", Integer),
Column("pandoraFlagList3", Integer),
Column("pandoraFlagList4", Integer),
Column("pandoraFlagList5", Integer),
Column("pandoraFlagList6", Integer),
Column("emblemFlagList", Integer),
UniqueConstraint("user", name="mai2_profile_boss_uk"),
mysql_charset="utf8mb4",
)
recent_rating = Table(
"maimai_profile_recent_rating",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("userRecentRatingList", JSON),
UniqueConstraint("user", name="mai2_profile_recent_rating_uk"),
mysql_charset="utf8mb4",
)
consec_logins = Table(
"mai2_profile_consec_logins",
metadata,
Column("id", Integer, primary_key=True, nullable=False),
Column("user", ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"), nullable=False),
Column("version", Integer, nullable=False),
Column("logins", Integer),
UniqueConstraint("user", "version", name="mai2_profile_consec_logins_uk"),
mysql_charset="utf8mb4",
)
class Mai2ProfileData(BaseData):
def put_profile_detail(
self, user_id: int, version: int, detail_data: Dict, is_dx: bool = True
) -> Optional[Row]:
detail_data["user"] = user_id
detail_data["version"] = version
if is_dx:
sql = insert(detail).values(**detail_data)
else:
sql = insert(detail_old).values(**detail_data)
conflict = sql.on_duplicate_key_update(**detail_data)
result = self.execute(conflict)
if result is None:
self.logger.warning(
f"put_profile: Failed to create profile! user_id {user_id} is_dx {is_dx}"
)
return None
return result.lastrowid
def get_profile_detail(self, user_id: int, version: int, is_dx: bool = True) -> Optional[Row]:
if is_dx:
sql = (
select(detail)
.where(and_(detail.c.user == user_id, detail.c.version <= version))
.order_by(detail.c.version.desc())
)
else:
sql = (
select(detail_old)
.where(and_(detail_old.c.user == user_id, detail_old.c.version <= version))
.order_by(detail_old.c.version.desc())
)
result = self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_ghost(
self, user_id: int, version: int, ghost_data: Dict
) -> Optional[int]:
ghost_data["user"] = user_id
ghost_data["version_int"] = version
sql = insert(ghost).values(**ghost_data)
conflict = sql.on_duplicate_key_update(**ghost_data)
result = self.execute(conflict)
if result is None:
self.logger.warning(f"put_profile_ghost: failed to update! {user_id}")
return None
return result.lastrowid
def get_profile_ghost(self, user_id: int, version: int) -> Optional[Row]:
sql = (
select(ghost)
.where(and_(ghost.c.user == user_id, ghost.c.version_int <= version))
.order_by(ghost.c.version.desc())
)
result = self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_extend(
self, user_id: int, version: int, extend_data: Dict
) -> Optional[int]:
extend_data["user"] = user_id
extend_data["version"] = version
sql = insert(extend).values(**extend_data)
conflict = sql.on_duplicate_key_update(**extend_data)
result = self.execute(conflict)
if result is None:
self.logger.warning(f"put_profile_extend: failed to update! {user_id}")
return None
return result.lastrowid
def get_profile_extend(self, user_id: int, version: int) -> Optional[Row]:
sql = (
select(extend)
.where(and_(extend.c.user == user_id, extend.c.version <= version))
.order_by(extend.c.version.desc())
)
result = self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_option(
self, user_id: int, version: int, option_data: Dict, is_dx: bool = True
) -> Optional[int]:
option_data["user"] = user_id
option_data["version"] = version
if is_dx:
sql = insert(option).values(**option_data)
else:
sql = insert(option_old).values(**option_data)
conflict = sql.on_duplicate_key_update(**option_data)
result = self.execute(conflict)
if result is None:
self.logger.warning(f"put_profile_option: failed to update! {user_id} is_dx {is_dx}")
return None
return result.lastrowid
def get_profile_option(self, user_id: int, version: int, is_dx: bool = True) -> Optional[Row]:
if is_dx:
sql = (
select(option)
.where(and_(option.c.user == user_id, option.c.version <= version))
.order_by(option.c.version.desc())
)
else:
sql = (
select(option_old)
.where(and_(option_old.c.user == user_id, option_old.c.version <= version))
.order_by(option_old.c.version.desc())
)
result = self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_rating(
self, user_id: int, version: int, rating_data: Dict
) -> Optional[int]:
rating_data["user"] = user_id
rating_data["version"] = version
sql = insert(rating).values(**rating_data)
conflict = sql.on_duplicate_key_update(**rating_data)
result = self.execute(conflict)
if result is None:
self.logger.warning(f"put_profile_rating: failed to update! {user_id}")
return None
return result.lastrowid
def get_profile_rating(self, user_id: int, version: int) -> Optional[Row]:
sql = (
select(rating)
.where(and_(rating.c.user == user_id, rating.c.version <= version))
.order_by(rating.c.version.desc())
)
result = self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_profile_region(self, user_id: int, region_id: int) -> Optional[int]:
sql = insert(region).values(
user=user_id,
regionId=region_id,
created=datetime.strftime(datetime.now(), Mai2Constants.DATE_TIME_FORMAT),
)
conflict = sql.on_duplicate_key_update(playCount=region.c.playCount + 1)
result = self.execute(conflict)
if result is None:
self.logger.warning(f"put_region: failed to update! {user_id}")
return None
return result.lastrowid
def get_regions(self, user_id: int) -> Optional[List[Dict]]:
sql = select(region).where(region.c.user == user_id)
result = self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_profile_activity(self, user_id: int, activity_data: Dict) -> Optional[int]:
if "id" in activity_data:
activity_data["activityId"] = activity_data["id"]
activity_data.pop("id")
activity_data["user"] = user_id
sql = insert(activity).values(**activity_data)
conflict = sql.on_duplicate_key_update(**activity_data)
result = self.execute(conflict)
if result is None:
self.logger.warning(
f"put_profile_activity: failed to update! user_id: {user_id}"
)
return None
return result.lastrowid
def get_profile_activity(
self, user_id: int, kind: int = None
) -> Optional[List[Row]]:
sql = activity.select(
and_(
activity.c.user == user_id,
(activity.c.kind == kind) if kind is not None else True,
)
)
result = self.execute(sql)
if result is None:
return None
return result.fetchall()
def put_web_option(self, user_id: int, version: int, web_opts: Dict) -> Optional[int]:
web_opts["user"] = user_id
web_opts["version"] = version
sql = insert(web_opt).values(**web_opts)
conflict = sql.on_duplicate_key_update(**web_opts)
result = self.execute(conflict)
if result is None:
self.logger.warning(
f"put_web_option: failed to update! user_id: {user_id}"
)
return None
return result.lastrowid
def get_web_option(self, user_id: int, version: int) -> Optional[Row]:
sql = web_opt.select(and_(web_opt.c.user == user_id, web_opt.c.version == version))
result = self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_grade_status(self, user_id: int, grade_stat: Dict) -> Optional[int]:
grade_stat["user"] = user_id
sql = insert(grade_status).values(**grade_stat)
conflict = sql.on_duplicate_key_update(**grade_stat)
result = self.execute(conflict)
if result is None:
self.logger.warning(
f"put_grade_status: failed to update! user_id: {user_id}"
)
return None
return result.lastrowid
def get_grade_status(self, user_id: int) -> Optional[Row]:
sql = grade_status.select(grade_status.c.user == user_id)
result = self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_boss_list(self, user_id: int, boss_stat: Dict) -> Optional[int]:
boss_stat["user"] = user_id
sql = insert(boss).values(**boss_stat)
conflict = sql.on_duplicate_key_update(**boss_stat)
result = self.execute(conflict)
if result is None:
self.logger.warning(
f"put_boss_list: failed to update! user_id: {user_id}"
)
return None
return result.lastrowid
def get_boss_list(self, user_id: int) -> Optional[Row]:
sql = boss.select(boss.c.user == user_id)
result = self.execute(sql)
if result is None:
return None
return result.fetchone()
def put_recent_rating(self, user_id: int, rr: Dict) -> Optional[int]:
sql = insert(recent_rating).values(user=user_id, userRecentRatingList=rr)
conflict = sql.on_duplicate_key_update({'userRecentRatingList': rr})
result = self.execute(conflict)
if result is None:
self.logger.warning(
f"put_recent_rating: failed to update! user_id: {user_id}"
)
return None
return result.lastrowid
def get_recent_rating(self, user_id: int) -> Optional[Row]:
sql = recent_rating.select(recent_rating.c.user == user_id)
result = self.execute(sql)
if result is None:
return None
return result.fetchone()
def add_consec_login(self, user_id: int, version: int) -> None:
sql = insert(consec_logins).values(
user=user_id,
version=version,
logins=1
)
conflict = sql.on_duplicate_key_update(
logins=consec_logins.c.logins + 1
)
result = self.execute(conflict)
if result is None:
self.logger.error(f"Failed to update consecutive login count for user {user_id} version {version}")
def get_consec_login(self, user_id: int, version: int) -> Optional[Row]:
sql = select(consec_logins).where(and_(
consec_logins.c.user==user_id,
consec_logins.c.version==version,
))
result = self.execute(sql)
if result is None:
return None
return result.fetchone()
def reset_consec_login(self, user_id: int, version: int) -> Optional[Row]:
sql = consec_logins.update(and_(
consec_logins.c.user==user_id,
consec_logins.c.version==version,
)).values(
logins=1
)
result = self.execute(sql)
if result is None:
return None
return result.fetchone()