255 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			255 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | 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() |