Files
weidian/server/routers/accounts.py

140 lines
4.2 KiB
Python
Raw Normal View History

import asyncio
import os
import threading
from flask import Blueprint, request, jsonify, render_template
from server.database import get_db
from server.services.auth_service import get_auth_path, has_auth, login_with_password
bp = Blueprint('accounts', __name__, url_prefix='/accounts')
@bp.route('/')
def list_accounts():
db = get_db()
accounts = db.execute('SELECT * FROM accounts ORDER BY id DESC').fetchall()
db.close()
return render_template('accounts.html', accounts=accounts)
@bp.route('/add', methods=['POST'])
def add_account():
name = request.form.get('name', '').strip()
phone = request.form.get('phone', '').strip()
password = request.form.get('password', '').strip()
if not name or not phone or not password:
return jsonify(success=False, msg='请填写完整信息'), 400
db = get_db()
cursor = db.execute(
'INSERT INTO accounts (name, phone, password, auth_file, login_msg) VALUES (?, ?, ?, ?, ?)',
(name, phone, password, '', '登录中...')
)
account_id = cursor.lastrowid
auth_file = get_auth_path(account_id)
db.execute('UPDATE accounts SET auth_file = ? WHERE id = ?', (auth_file, account_id))
db.commit()
db.close()
# 后台异步登录
_start_bg_login(account_id, phone, password)
return jsonify(success=True, id=account_id)
@bp.route('/delete/<int:account_id>', methods=['POST'])
def delete_account(account_id):
db = get_db()
db.execute('DELETE FROM tasks WHERE account_id = ?', (account_id,))
db.execute('DELETE FROM accounts WHERE id = ?', (account_id,))
db.commit()
db.close()
path = get_auth_path(account_id)
if os.path.exists(path):
os.remove(path)
return jsonify(success=True)
@bp.route('/login/<int:account_id>', methods=['POST'])
def do_login(account_id):
"""用 Playwright 模拟浏览器自动登录微店"""
db = get_db()
account = db.execute('SELECT * FROM accounts WHERE id = ?', (account_id,)).fetchone()
db.close()
if not account:
return jsonify(success=False, msg='账号不存在'), 404
phone = account['phone']
password = account['password']
if not phone or not password:
return jsonify(success=False, msg='该账号未设置手机号或密码'), 400
# 标记为登录中
db = get_db()
db.execute(
"UPDATE accounts SET is_logged_in = 0, login_msg = '登录中...', updated_at = datetime('now','localtime') WHERE id = ?",
(account_id,)
)
db.commit()
db.close()
# 后台异步登录
_start_bg_login(account_id, phone, password)
return jsonify(success=True, msg='登录中...')
@bp.route('/status/<int:account_id>')
def get_status(account_id):
"""轮询账号登录状态"""
db = get_db()
account = db.execute(
'SELECT is_logged_in, login_msg FROM accounts WHERE id = ?',
(account_id,)
).fetchone()
db.close()
if not account:
return jsonify(is_logged_in=False, login_msg='账号不存在', done=True)
msg = account['login_msg'] or ''
is_logged_in = bool(account['is_logged_in'])
# 登录中... 表示还在进行
done = msg != '登录中...'
return jsonify(is_logged_in=is_logged_in, login_msg=msg, done=done)
def _start_bg_login(account_id, phone, password):
"""在后台线程中执行登录"""
def _run():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
ok, msg = loop.run_until_complete(
login_with_password(account_id, phone, password)
)
except Exception as e:
ok, msg = False, str(e)
finally:
loop.close()
db = get_db()
if ok:
db.execute(
"UPDATE accounts SET is_logged_in = 1, login_msg = '登录成功', "
"updated_at = datetime('now','localtime') WHERE id = ?",
(account_id,)
)
else:
db.execute(
"UPDATE accounts SET is_logged_in = 0, login_msg = ?, "
"updated_at = datetime('now','localtime') WHERE id = ?",
(msg, account_id)
)
db.commit()
db.close()
t = threading.Thread(target=_run, daemon=True)
t.start()