209 lines
6.0 KiB
Python
209 lines
6.0 KiB
Python
# coolbot_matcher - 一尘数据库号码匹配工具
|
||
# Version: 0.0.1 (2026-04-24)
|
||
# 描述:从一尘数据库(coolbot_data)查询匹配的藏品号码
|
||
|
||
from typing import List
|
||
from sqlalchemy import text
|
||
from sqlalchemy.orm import Session
|
||
from app.core.coolbot_db import coolbot_engine
|
||
|
||
|
||
def match_pattern(col_number: str, pattern: str) -> bool:
|
||
"""匹配号码特征模式
|
||
|
||
通配符规则:
|
||
- X = 任意数字
|
||
- A = 非4
|
||
- B = 非47
|
||
- C = 非347
|
||
- D = 非247
|
||
- E = 非2347
|
||
"""
|
||
if not col_number or not pattern:
|
||
return False
|
||
|
||
if len(col_number) != len(pattern):
|
||
return False
|
||
|
||
for i, p in enumerate(pattern):
|
||
c = col_number[i]
|
||
if p == 'X':
|
||
continue # 任意数字
|
||
elif p == 'A':
|
||
if c == '4':
|
||
return False
|
||
elif p == 'B':
|
||
if c == '4':
|
||
return False
|
||
if i < len(col_number) - 1 and col_number[i+1] == '7' and pattern[i+1] == 'X':
|
||
return False
|
||
elif p == 'C':
|
||
if c in '347':
|
||
return False
|
||
elif p == 'D':
|
||
if c in '247':
|
||
return False
|
||
elif p == 'E':
|
||
if c in '2347':
|
||
return False
|
||
elif p == 'L':
|
||
# L = 带4
|
||
if c != '4':
|
||
return False
|
||
elif p == 'N':
|
||
# N = 无4
|
||
if c == '4':
|
||
return False
|
||
else:
|
||
if c != p:
|
||
return False
|
||
return True
|
||
|
||
|
||
def match_self_collections_count(db: Session, user_id: str, expect_number: str) -> int:
|
||
"""根据号码特征计算匹配藏品数量(从用户自有藏品)
|
||
|
||
Args:
|
||
db: 数据库会话
|
||
user_id: 用户ID
|
||
expect_number: 期望号码,如 "J012345678" (固定J0前缀+8位特征)
|
||
|
||
Returns:
|
||
匹配的藏品数量
|
||
"""
|
||
from app.models.models import Collection
|
||
|
||
if not expect_number or len(expect_number) != 10:
|
||
return 0
|
||
|
||
if not expect_number.startswith('J0'):
|
||
return 0
|
||
|
||
pattern = expect_number[2:] # 后8位
|
||
if not pattern:
|
||
return 0
|
||
|
||
# 获取用户所有藏品
|
||
collections = db.query(Collection).filter(
|
||
Collection.f99_91_user_id == user_id,
|
||
Collection.f01_04_status == "in_collection"
|
||
).all()
|
||
|
||
count = 0
|
||
for c in collections:
|
||
number = c.f02_10_prefix_serial or ''
|
||
if len(number) >= 10 and number.startswith('J0'):
|
||
col_pattern = number[2:10]
|
||
if match_pattern(col_pattern, pattern):
|
||
count += 1
|
||
elif len(number) >= 8:
|
||
col_pattern = number[:8]
|
||
if match_pattern(col_pattern, pattern):
|
||
count += 1
|
||
|
||
return count
|
||
|
||
|
||
def match_collections_count_from_coolbot(expect_number: str) -> int:
|
||
"""根据号码特征计算匹配藏品数量(从coolbot_data数据库)
|
||
|
||
Args:
|
||
expect_number: 期望号码,如 "J012345678" (固定J0前缀+8位特征)
|
||
|
||
Returns:
|
||
匹配的藏品数量
|
||
"""
|
||
if not expect_number or len(expect_number) != 10:
|
||
return 0
|
||
|
||
if not expect_number.startswith('J0'):
|
||
return 0
|
||
|
||
pattern = expect_number[2:] # 后8位
|
||
if not pattern:
|
||
return 0
|
||
|
||
query = text("""
|
||
SELECT id, crown_code FROM collections
|
||
WHERE crown_code IS NOT NULL
|
||
AND crown_code != ''
|
||
AND LENGTH(crown_code) >= 10
|
||
AND crown_code LIKE 'J0%'
|
||
""")
|
||
|
||
try:
|
||
with coolbot_engine.connect() as conn:
|
||
result = conn.execute(query)
|
||
|
||
match_count = 0
|
||
for row in result:
|
||
crown_code = row[1]
|
||
if crown_code and len(crown_code) >= 10:
|
||
col_pattern = crown_code[2:10]
|
||
if match_pattern(col_pattern, pattern):
|
||
match_count += 1
|
||
|
||
return match_count
|
||
except Exception as e:
|
||
print(f"Error querying coolbot_data: {e}")
|
||
return 0
|
||
|
||
|
||
def match_collections_list_from_coolbot(expect_number: str, limit: int = 20) -> List[dict]:
|
||
"""获取匹配的藏品列表(从coolbot_data数据库)
|
||
|
||
Args:
|
||
expect_number: 期望号码,如 "J012345678"
|
||
limit: 返回的最大数量
|
||
|
||
Returns:
|
||
匹配的藏品列表
|
||
"""
|
||
if not expect_number or len(expect_number) != 10:
|
||
return []
|
||
|
||
if not expect_number.startswith('J0'):
|
||
return []
|
||
|
||
pattern = expect_number[2:] # 后8位
|
||
if not pattern:
|
||
return []
|
||
|
||
query = text("""
|
||
SELECT id, name, category, crown_code, price, post_title, post_url, author, post_crawled_at
|
||
FROM collections
|
||
WHERE crown_code IS NOT NULL
|
||
AND crown_code != ''
|
||
AND LENGTH(crown_code) >= 10
|
||
AND crown_code LIKE 'J0%'
|
||
""")
|
||
|
||
try:
|
||
with coolbot_engine.connect() as conn:
|
||
result = conn.execute(query)
|
||
|
||
matched = []
|
||
for row in result:
|
||
crown_code = row[3]
|
||
if crown_code and len(crown_code) >= 10:
|
||
col_pattern = crown_code[2:10]
|
||
if match_pattern(col_pattern, pattern):
|
||
matched.append({
|
||
"id": row[0],
|
||
"name": row[1],
|
||
"category": row[2],
|
||
"crown_code": crown_code,
|
||
"price": float(row[4]) if row[4] else None,
|
||
"post_title": row[5],
|
||
"post_url": row[6],
|
||
"author": row[7],
|
||
"post_crawled_at": row[8].isoformat() if row[8] else None
|
||
})
|
||
if len(matched) >= limit:
|
||
break
|
||
|
||
return matched
|
||
except Exception as e:
|
||
print(f"Error querying coolbot_data: {e}")
|
||
return []
|