steam_account_service.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. """
  2. Steam账号管理服务
  3. 处理Steam账号的绑定、查询等操作。敏感信息存客户端本地,数据库仅记录账号绑定关系。
  4. 每用户最大绑定数由表 user_steam_account_limit 管理,默认 3。
  5. """
  6. from typing import Optional, Tuple
  7. from sqlalchemy.orm import Session
  8. from app.models.steam_account import SteamAccount
  9. from app.models.user_steam_account_limit import UserSteamAccountLimit
  10. from app.core.logger import logger
  11. from app.utils.timezone import beijing_now_naive
  12. DEFAULT_MAX_STEAM_ACCOUNTS = 3
  13. class SteamAccountService:
  14. """Steam账号服务"""
  15. def __init__(self, db: Session):
  16. self.db = db
  17. def _get_max_steam_accounts_for_user(self, user_id: int) -> int:
  18. """查询该用户允许绑定的最大 Steam 账号数;无记录时默认 3。"""
  19. try:
  20. row = (
  21. self.db.query(UserSteamAccountLimit)
  22. .filter(UserSteamAccountLimit.user_id == user_id)
  23. .first()
  24. )
  25. if not row:
  26. return DEFAULT_MAX_STEAM_ACCOUNTS
  27. return max(1, int(row.max_steam_accounts))
  28. except Exception:
  29. return DEFAULT_MAX_STEAM_ACCOUNTS
  30. def get_steam_account_limit(self, user_id: int) -> Tuple[bool, str, dict]:
  31. """
  32. 获取用户 Steam 账号绑定限制信息。
  33. 返回:max_steam_accounts(最大可绑定数)、current_bound_count(已验证绑定数)。
  34. """
  35. try:
  36. max_count = self._get_max_steam_accounts_for_user(user_id)
  37. current_bound = (
  38. self.db.query(SteamAccount)
  39. .filter(
  40. SteamAccount.user_id == user_id,
  41. SteamAccount.is_deleted == 0,
  42. SteamAccount.steam_id.isnot(None),
  43. SteamAccount.steam_id != "",
  44. )
  45. .count()
  46. )
  47. return True, "获取成功", {
  48. "max_steam_accounts": max_count,
  49. "current_bound_count": current_bound,
  50. }
  51. except Exception as e:
  52. logger.exception(f"获取Steam账号限制失败: {e}")
  53. return False, f"获取失败: {str(e)}", {}
  54. def create_steam_account(
  55. self,
  56. user_id: int,
  57. steam_username: str,
  58. steam_id: Optional[str] = None,
  59. ) -> Tuple[bool, str, dict]:
  60. """
  61. 绑定 Steam 账号(仅记录账号标识,敏感信息存客户端本地)。
  62. Args:
  63. user_id: 用户ID
  64. steam_username: Steam 用户名
  65. steam_id: Steam ID(可选,来自客户端登录验证结果)
  66. Returns:
  67. (success, message, account_data)
  68. """
  69. try:
  70. # 检查是否已绑定相同 Steam 账号
  71. existing = (
  72. self.db.query(SteamAccount)
  73. .filter(
  74. SteamAccount.user_id == user_id,
  75. SteamAccount.steam_username == steam_username,
  76. SteamAccount.is_deleted == 0,
  77. )
  78. .first()
  79. )
  80. if existing:
  81. return False, "该Steam账号已绑定", {}
  82. # 仅当本次是“验证绑定”(带 steam_id)时检查上限;仅新增(steam_id 为空)不占绑定名额
  83. if steam_id:
  84. max_count = self._get_max_steam_accounts_for_user(user_id)
  85. current_bound = (
  86. self.db.query(SteamAccount)
  87. .filter(
  88. SteamAccount.user_id == user_id,
  89. SteamAccount.is_deleted == 0,
  90. SteamAccount.steam_id.isnot(None),
  91. SteamAccount.steam_id != "",
  92. )
  93. .count()
  94. )
  95. if current_bound >= max_count:
  96. return False, f"已达到最大绑定数量({max_count} 个),无法再绑定更多 Steam 账号", {}
  97. account = SteamAccount(
  98. user_id=user_id,
  99. steam_username=steam_username,
  100. steam_id=steam_id,
  101. is_active=True,
  102. )
  103. self.db.add(account)
  104. self.db.commit()
  105. logger.info(f"Steam账号绑定成功: user_id={user_id}, steam_username={steam_username}")
  106. return True, "绑定成功", {
  107. "id": account.id,
  108. "steam_username": account.steam_username,
  109. "steam_id": account.steam_id,
  110. "is_active": account.is_active,
  111. "created_at": account.created_at.isoformat(),
  112. }
  113. except Exception as e:
  114. self.db.rollback()
  115. logger.exception(f"Steam账号绑定失败: {e}")
  116. return False, f"绑定失败: {str(e)}", {}
  117. def bind_steam_account(
  118. self,
  119. user_id: int,
  120. steam_username: str,
  121. steam_id: str,
  122. ) -> Tuple[bool, str, dict]:
  123. """
  124. 对已新增的 Steam 账号进行验证绑定:将 steam_id 写入该账号记录。
  125. 仅当“已验证绑定数”未达上限时允许。
  126. """
  127. try:
  128. max_count = self._get_max_steam_accounts_for_user(user_id)
  129. current_bound = (
  130. self.db.query(SteamAccount)
  131. .filter(
  132. SteamAccount.user_id == user_id,
  133. SteamAccount.is_deleted == 0,
  134. SteamAccount.steam_id.isnot(None),
  135. SteamAccount.steam_id != "",
  136. )
  137. .count()
  138. )
  139. if current_bound >= max_count:
  140. return False, f"已达到最大绑定数量({max_count} 个),无法再绑定更多 Steam 账号", {}
  141. account = (
  142. self.db.query(SteamAccount)
  143. .filter(
  144. SteamAccount.user_id == user_id,
  145. SteamAccount.steam_username == steam_username,
  146. SteamAccount.is_deleted == 0,
  147. SteamAccount.steam_id.is_(None),
  148. )
  149. .first()
  150. )
  151. if not account:
  152. account_empty = (
  153. self.db.query(SteamAccount)
  154. .filter(
  155. SteamAccount.user_id == user_id,
  156. SteamAccount.steam_username == steam_username,
  157. SteamAccount.is_deleted == 0,
  158. )
  159. .first()
  160. )
  161. if account_empty and account_empty.steam_id:
  162. return False, "该Steam账号已绑定", {}
  163. return False, "请先新增该Steam账号后再进行验证绑定", {}
  164. account.steam_id = steam_id
  165. self.db.commit()
  166. logger.info(f"Steam账号验证绑定成功: user_id={user_id}, steam_username={steam_username}")
  167. return True, "绑定成功", {
  168. "id": account.id,
  169. "steam_username": account.steam_username,
  170. "steam_id": account.steam_id,
  171. "is_active": account.is_active,
  172. "created_at": account.created_at.isoformat(),
  173. }
  174. except Exception as e:
  175. self.db.rollback()
  176. logger.exception(f"Steam账号验证绑定失败: {e}")
  177. return False, f"绑定失败: {str(e)}", {}
  178. def get_accounts_by_user(self, user_id: int) -> Tuple[bool, str, list]:
  179. """
  180. 获取用户绑定的所有Steam账号
  181. Args:
  182. user_id: 用户ID
  183. Returns:
  184. (success, message, accounts_list)
  185. """
  186. try:
  187. accounts = self.db.query(SteamAccount).filter(
  188. SteamAccount.user_id == user_id,
  189. SteamAccount.is_deleted == 0
  190. ).all()
  191. result = []
  192. for acc in accounts:
  193. # 隐藏敏感信息
  194. result.append({
  195. "id": acc.id,
  196. "steam_username": acc.steam_username,
  197. "steam_id": acc.steam_id,
  198. "is_active": acc.is_active,
  199. "created_at": acc.created_at.isoformat()
  200. })
  201. return True, "获取成功", result
  202. except Exception as e:
  203. logger.exception(f"获取Steam账号列表失败: {e}")
  204. return False, f"获取失败: {str(e)}", []
  205. def get_account_by_id(self, account_id: int, user_id: int) -> Optional[SteamAccount]:
  206. """
  207. 根据ID获取账号(验证所有权)
  208. Args:
  209. account_id: 账号ID
  210. user_id: 用户ID
  211. Returns:
  212. SteamAccount or None
  213. """
  214. return self.db.query(SteamAccount).filter(
  215. SteamAccount.id == account_id,
  216. SteamAccount.user_id == user_id,
  217. SteamAccount.is_deleted == 0
  218. ).first()
  219. def update_account(
  220. self,
  221. account_id: int,
  222. user_id: int,
  223. is_active: bool = None
  224. ) -> Tuple[bool, str]:
  225. """
  226. 更新账号状态
  227. Args:
  228. account_id: 账号ID
  229. user_id: 用户ID
  230. is_active: 是否启用
  231. Returns:
  232. (success, message)
  233. """
  234. try:
  235. account = self.get_account_by_id(account_id, user_id)
  236. if not account:
  237. return False, "账号不存在"
  238. if is_active is not None:
  239. account.is_active = is_active
  240. self.db.commit()
  241. logger.info(f"Steam账号更新成功: account_id={account_id}")
  242. return True, "更新成功"
  243. except Exception as e:
  244. self.db.rollback()
  245. logger.exception(f"更新Steam账号失败: {e}")
  246. return False, f"更新失败: {str(e)}"
  247. def delete_account(self, account_id: int, user_id: int) -> Tuple[bool, str]:
  248. """
  249. 解绑Steam账号 (软删除)
  250. Args:
  251. account_id: 账号ID
  252. user_id: 用户ID
  253. Returns:
  254. (success, message)
  255. """
  256. try:
  257. account = self.get_account_by_id(account_id, user_id)
  258. if not account:
  259. return False, "账号不存在"
  260. # 已绑定的账号不可删除
  261. if account.steam_id and str(account.steam_id).strip():
  262. return False, "已绑定的账号不可删除,请先解绑"
  263. # 先写历史表,再改/删
  264. from app.utils.history import create_steam_account_history
  265. create_steam_account_history(self.db, account, "DELETE")
  266. # 软删除
  267. account.is_deleted = True
  268. self.db.commit()
  269. logger.info(f"Steam账号解绑成功: account_id={account_id}")
  270. return True, "解绑成功"
  271. except Exception as e:
  272. self.db.rollback()
  273. logger.exception(f"解绑Steam账号失败: {e}")
  274. return False, f"解绑失败: {str(e)}"