MySQL 数据库管理类
| 16 | |
| 17 | |
| 18 | class MySQLDatabase: |
| 19 | """MySQL 数据库管理类""" |
| 20 | |
| 21 | def __init__(self): |
| 22 | """初始化数据库连接""" |
| 23 | import os |
| 24 | |
| 25 | # 从环境变量读取配置(推荐)或使用默认值 |
| 26 | self.config = { |
| 27 | 'host': os.getenv('MYSQL_HOST', 'localhost'), |
| 28 | 'port': int(os.getenv('MYSQL_PORT', 3306)), |
| 29 | 'user': os.getenv('MYSQL_USER', 'tgbot_user'), |
| 30 | 'password': os.getenv('MYSQL_PASSWORD', 'your_password_here'), |
| 31 | 'database': os.getenv('MYSQL_DATABASE', 'tgbot_verify'), |
| 32 | 'charset': 'utf8mb4', |
| 33 | 'autocommit': False, |
| 34 | } |
| 35 | logger.info(f"MySQL 数据库初始化: {self.config['user']}@{self.config['host']}/{self.config['database']}") |
| 36 | self.init_database() |
| 37 | |
| 38 | def get_connection(self): |
| 39 | """获取数据库连接""" |
| 40 | return pymysql.connect(**self.config) |
| 41 | |
| 42 | def init_database(self): |
| 43 | """初始化数据库表结构""" |
| 44 | conn = self.get_connection() |
| 45 | cursor = conn.cursor() |
| 46 | |
| 47 | try: |
| 48 | # 用户表 |
| 49 | cursor.execute( |
| 50 | """ |
| 51 | CREATE TABLE IF NOT EXISTS users ( |
| 52 | user_id BIGINT PRIMARY KEY, |
| 53 | username VARCHAR(255), |
| 54 | full_name VARCHAR(255), |
| 55 | balance INT DEFAULT 1, |
| 56 | is_blocked TINYINT(1) DEFAULT 0, |
| 57 | invited_by BIGINT, |
| 58 | created_at DATETIME DEFAULT CURRENT_TIMESTAMP, |
| 59 | last_checkin DATETIME NULL, |
| 60 | INDEX idx_username (username), |
| 61 | INDEX idx_invited_by (invited_by) |
| 62 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
| 63 | """ |
| 64 | ) |
| 65 | |
| 66 | # 邀请记录表 |
| 67 | cursor.execute( |
| 68 | """ |
| 69 | CREATE TABLE IF NOT EXISTS invitations ( |
| 70 | id INT AUTO_INCREMENT PRIMARY KEY, |
| 71 | inviter_id BIGINT NOT NULL, |
| 72 | invitee_id BIGINT NOT NULL, |
| 73 | created_at DATETIME DEFAULT CURRENT_TIMESTAMP, |
| 74 | INDEX idx_inviter (inviter_id), |
| 75 | INDEX idx_invitee (invitee_id), |
nothing calls this directly
no outgoing calls
no test coverage detected