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()
 |