import mysql.connector from mysql.connector import Error import uuid from datetime import datetime, timedelta import hashlib import os class LicenseDatabase: def __init__(self, host=None, database=None, user=None, password=None): self.host = host or os.environ.get('DB_HOST', 'taiyiagi.xyz') self.database = database or os.environ.get('DB_NAME', 'filesend') self.user = user or os.environ.get('DB_USER', 'taiyi') self.password = password or os.environ.get('DB_PASSWORD', 'taiyi1224') self.connection = None def connect(self): """连接到数据库""" try: self.connection = mysql.connector.connect( host=self.host, database=self.database, user=self.user, password=self.password ) if self.connection.is_connected(): return True return False except Error as e: print(f"数据库连接错误: {e}") return False def create_tables(self): """创建必要的数据库表""" if not self.connection or not self.connection.is_connected(): if not self.connect(): return False try: cursor = self.connection.cursor() # 创建卡密表 cursor.execute(''' CREATE TABLE IF NOT EXISTS license_keys ( id INT AUTO_INCREMENT PRIMARY KEY, key_code VARCHAR(50) NOT NULL UNIQUE, machine_code VARCHAR(100) DEFAULT NULL, start_time DATETIME DEFAULT NULL, end_time DATETIME NOT NULL, status ENUM('unused', 'active', 'expired', 'banned') DEFAULT 'unused', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) ''') self.connection.commit() cursor.close() return True except Error as e: print(f"创建表错误: {e}") return False def generate_key(self, days_valid): """生成一个新的卡密并保存到数据库""" if not self.connection or not self.connection.is_connected(): if not self.connect(): return None try: # 生成UUID作为基础,然后进行哈希处理 key_uuid = uuid.uuid4().hex hash_obj = hashlib.sha256(key_uuid.encode()) # 取前20个字符作为卡密 key_code = hash_obj.hexdigest()[:20].upper() # 格式化卡密,每5个字符一组 formatted_key = '-'.join([key_code[i:i + 5] for i in range(0, len(key_code), 5)]) # 计算过期时间 end_time = datetime.now() + timedelta(days=days_valid) cursor = self.connection.cursor() query = """ INSERT INTO license_keys (key_code, end_time) VALUES (%s, %s) """ cursor.execute(query, (formatted_key, end_time)) self.connection.commit() cursor.close() return formatted_key except Error as e: print(f"生成卡密错误: {e}") return None def validate_key(self, key_code, machine_code): """验证卡密是否有效,并绑定机器码 - 严格一机一码""" if not self.connection or not self.connection.is_connected(): if not self.connect(): return False, "数据库连接失败" try: cursor = self.connection.cursor(dictionary=True) # 查询卡密信息 query = "SELECT * FROM license_keys WHERE key_code = %s" cursor.execute(query, (key_code,)) key_info = cursor.fetchone() if not key_info: cursor.close() return False, "无效的激活码" # 检查卡密状态 if key_info['status'] == 'banned': cursor.close() return False, "激活码已被封禁" if key_info['status'] == 'expired': cursor.close() return False, "激活码已过期" # 一机一码严格检查:每个激活码只能在一台机器上使用 if key_info['status'] == 'active': if key_info['machine_code'] != machine_code: # 这个码已经用过了,不能再次使用 cursor.close() return False, f"此激活码已在设备{key_info['machine_code'][:8]}...上使用,一个激活码只能在一台设备上使用一次" else: # 已经激活过这台机器,验证是否过期 if datetime.now() > key_info['end_time']: update_query = "UPDATE license_keys SET status = 'expired' WHERE key_code = %s" cursor.execute(update_query, (key_code,)) self.connection.commit() cursor.close() return False, "激活码已过期" else: cursor.close() return True, "此设备已激活,继续使用" # 首次激活:验证通过后绑定到机器 if key_info['status'] == 'unused': update_query = """ UPDATE license_keys SET status = 'active', machine_code = %s, start_time = %s WHERE key_code = %s AND status = 'unused' """ cursor.execute(update_query, (machine_code, datetime.now(), key_code)) rows_affected = cursor.rowcount self.connection.commit() if rows_affected == 0: # 可能已经被其他并发操作激活 cursor.close() return False, "激活码已被使用,请使用新的激活码" # 再次检查是否过期(防止并发问题) final_check_query = "SELECT * FROM license_keys WHERE key_code = %s" cursor.execute(final_check_query, (key_code,)) final_info = cursor.fetchone() if final_info and datetime.now() > final_info['end_time']: update_query = "UPDATE license_keys SET status = 'expired' WHERE key_code = %s" cursor.execute(update_query, (key_code,)) self.connection.commit() cursor.close() return False, "激活码已过期" cursor.close() return True, "激活成功" except Error as e: print(f"验证激活码错误: {e}") return False, f"验证过程出错: {str(e)}" def get_all_keys(self): """获取所有卡密信息""" if not self.connection or not self.connection.is_connected(): if not self.connect(): return [] try: cursor = self.connection.cursor(dictionary=True) query = "SELECT * FROM license_keys ORDER BY created_at DESC" cursor.execute(query) keys = cursor.fetchall() cursor.close() return keys except Error as e: print(f"获取卡密列表错误: {e}") return [] def update_key_status(self, key_code, status): """更新卡密状态""" if not self.connection or not self.connection.is_connected(): if not self.connect(): return False try: cursor = self.connection.cursor() query = "UPDATE license_keys SET status = %s WHERE key_code = %s" cursor.execute(query, (status, key_code)) self.connection.commit() cursor.close() return True except Error as e: print(f"更新卡密状态错误: {e}") return False def release_key(self, key_code): """释放已使用的激活码 - 将其重置为未使用状态,清空机器码""" if not self.connection or not self.connection.is_connected(): if not self.connect(): return False, "数据库连接失败" try: cursor = self.connection.cursor(dictionary=True) # 检查卡密是否存在且处于已激活状态 check_query = "SELECT * FROM license_keys WHERE key_code = %s" cursor.execute(check_query, (key_code,)) key_info = cursor.fetchone() if not key_info: cursor.close() return False, "激活码不存在" if key_info['status'] != 'active': cursor.close() return False, f"激活码处于 {key_info['status']} 状态,只能释放已使用的激活码" # 释放激活码:重置为未使用状态,清空机器码和开始时间 release_query = """ UPDATE license_keys SET status = 'unused', machine_code = NULL, start_time = NULL WHERE key_code = %s """ cursor.execute(release_query, (key_code,)) rows_affected = cursor.rowcount self.connection.commit() cursor.close() if rows_affected > 0: return True, "激活码已释放,可以重新使用" else: return False, "释放激活码失败" except Error as e: print(f"释放激活码错误: {e}") return False, f"释放过程出错: {str(e)}" def close(self): """关闭数据库连接""" if self.connection and self.connection.is_connected(): self.connection.close()