@@ -329,111 +329,194 @@ async def get_subscribed_workshop_items():
329329 # 存储处理后的物品信息
330330 items_info = []
331331
332- # 尝试获取物品详细信息(标题、描述等)- 使用官方推荐的方式
332+ # 批量查询所有物品的详情(一次查询,避免N次等待)
333+ ugc_results = {}
334+ try :
335+ # 转换所有ID为整数
336+ all_item_ids = []
337+ for sid in subscribed_items :
333338 try :
334- # 使用官方推荐的CreateQueryUGCDetailsRequest和SendQueryUGCRequest方法
335- # 我们一次性查询所有订阅物品的详情,这样更高效
336- logger .info (f'使用批量查询方式获取 { len (subscribed_items )} 个物品的详细信息' )
339+ all_item_ids .append (int (sid ))
340+ except (ValueError , TypeError ):
341+ continue
342+
343+ if all_item_ids :
344+ logger .info (f'批量查询 { len (all_item_ids )} 个物品的详细信息' )
345+ query_handle = steamworks .Workshop .CreateQueryUGCDetailsRequest (all_item_ids )
346+
347+ if query_handle :
348+ steamworks .Workshop .SendQueryUGCRequest (query_handle )
349+ await asyncio .sleep (0.5 ) # 只等待一次
337350
338- # 转换所有ID为整数
339- all_item_ids = []
340- for sid in subscribed_items :
341- try :
342- all_item_ids .append (int (sid ))
343- except : continue
351+ for i in range (len (all_item_ids )):
352+ res = steamworks .Workshop .GetQueryUGCResult (query_handle , i )
353+ if res :
354+ ugc_results [all_item_ids [i ]] = res
344355
345- if all_item_ids :
346- # 创建批量详情查询请求
347- query_handle = steamworks .Workshop .CreateQueryUGCDetailsRequest (all_item_ids )
348-
349- if query_handle :
350- # 发送查询请求
351- steamworks .Workshop .SendQueryUGCRequest (query_handle )
352-
353- # 异步回调,简单等待一下
354- await asyncio .sleep (0.5 )
355-
356- # 将查询结果存入字典,方便后续查找
357- ugc_results = {}
358- for i in range (len (all_item_ids )):
359- res = steamworks .Workshop .GetQueryUGCResult (query_handle , i )
360- if res :
361- ugc_results [all_item_ids [i ]] = res
362-
363- logger .info (f"成功获取 { len (ugc_results )} 个物品的详情结果" )
364- except Exception as api_error :
365- logger .warning (f"批量获取物品详情时出错: { api_error } " )
366- ugc_results = {}
367-
368- # 为每个物品获取基本信息和状态
369- for item_id in subscribed_items :
356+ logger .info (f"批量查询成功获取 { len (ugc_results )} 个物品的详情" )
357+ except Exception as batch_error :
358+ logger .warning (f"批量查询物品详情失败: { batch_error } " )
359+
360+ # 为每个物品获取基本信息和状态
361+ for item_id in subscribed_items :
362+ try :
363+ # 确保item_id是整数类型
364+ if isinstance (item_id , str ):
370365 try :
371- # 确保item_id是整数类型
372- if isinstance (item_id , str ):
373- try :
374- item_id = int (item_id )
375- except ValueError :
376- logger .error (f"无效的物品ID: { item_id } " )
377- continue
366+ item_id = int (item_id )
367+ except ValueError :
368+ logger .error (f"无效的物品ID: { item_id } " )
369+ continue
370+
371+ logger .info (f'正在处理物品ID: { item_id } ' )
372+
373+ # 获取物品状态
374+ item_state = steamworks .Workshop .GetItemState (item_id )
375+ logger .debug (f'物品 { item_id } 状态: { item_state } ' )
376+
377+ # 初始化基本物品信息(确保所有字段都有默认值)
378+ # 确保publishedFileId始终为字符串类型,避免前端toString()错误
379+ item_info = {
380+ "publishedFileId" : str (item_id ),
381+ "title" : f"未知物品_{ item_id } " ,
382+ "description" : "无法获取详细描述" ,
383+ "tags" : [],
384+ "state" : {
385+ "subscribed" : bool (item_state & 1 ), # EItemState.SUBSCRIBED
386+ "legacyItem" : bool (item_state & 2 ),
387+ "installed" : False ,
388+ "needsUpdate" : bool (item_state & 8 ), # EItemState.NEEDS_UPDATE
389+ "downloading" : False ,
390+ "downloadPending" : bool (item_state & 32 ), # EItemState.DOWNLOAD_PENDING
391+ "isWorkshopItem" : bool (item_state & 128 ) # EItemState.IS_WORKSHOP_ITEM
392+ },
393+ "installedFolder" : None ,
394+ "fileSizeOnDisk" : 0 ,
395+ "downloadProgress" : {
396+ "bytesDownloaded" : 0 ,
397+ "bytesTotal" : 0 ,
398+ "percentage" : 0
399+ },
400+ # 添加额外的时间戳信息 - 使用datetime替代time模块避免命名冲突
401+ "timeAdded" : int (datetime .now ().timestamp ()),
402+ "timeUpdated" : int (datetime .now ().timestamp ())
403+ }
404+
405+ # 尝试获取物品安装信息(如果已安装)
406+ try :
407+ logger .debug (f'获取物品 { item_id } 的安装信息' )
408+ result = steamworks .Workshop .GetItemInstallInfo (item_id )
409+
410+ # 检查返回值的结构 - 支持字典格式(根据日志显示)
411+ if isinstance (result , dict ):
412+ logger .debug (f'物品 { item_id } 安装信息字典: { result } ' )
378413
379- logger .info (f'正在处理物品ID: { item_id } ' )
414+ # 从字典中提取信息
415+ item_info ["state" ]["installed" ] = True # 如果返回字典,假设已安装
416+ # 获取安装路径 - workshop.py中已经将folder解码为字符串
417+ folder_path = result .get ('folder' , '' )
418+ item_info ["installedFolder" ] = str (folder_path ) if folder_path else None
419+ logger .debug (f'物品 { item_id } 的安装路径: { item_info ["installedFolder" ]} ' )
380420
381- # 获取物品状态
382- item_state = steamworks .Workshop .GetItemState (item_id )
383- logger .debug (f'物品 { item_id } 状态: { item_state } ' )
421+ # 处理磁盘大小 - GetItemInstallInfo返回的disk_size是普通整数
422+ disk_size = result .get ('disk_size' , 0 )
423+ item_info ["fileSizeOnDisk" ] = int (disk_size ) if isinstance (disk_size , (int , float )) else 0
424+ # 也支持元组格式作为备选
425+ elif isinstance (result , tuple ) and len (result ) >= 3 :
426+ installed , folder , size = result
427+ logger .debug (f'物品 { item_id } 安装状态: 已安装={ installed } , 路径={ folder } , 大小={ size } ' )
384428
385- # 初始化基本物品信息(确保所有字段都有默认值)
386- # 确保publishedFileId始终为字符串类型,避免前端toString()错误
387- item_info = {
388- "publishedFileId" : str (item_id ),
389- "title" : f"未知物品_{ item_id } " ,
390- "description" : "无法获取详细描述" ,
391- "tags" : [],
392- "state" : {
393- "subscribed" : bool (item_state & 1 ), # EItemState.SUBSCRIBED
394- "legacyItem" : bool (item_state & 2 ),
395- "installed" : False ,
396- "needsUpdate" : bool (item_state & 8 ), # EItemState.NEEDS_UPDATE
397- "downloading" : False ,
398- "downloadPending" : bool (item_state & 32 ), # EItemState.DOWNLOAD_PENDING
399- "isWorkshopItem" : bool (item_state & 128 ) # EItemState.IS_WORKSHOP_ITEM
400- },
401- "installedFolder" : None ,
402- "fileSizeOnDisk" : 0 ,
403- "downloadProgress" : {
404- "bytesDownloaded" : 0 ,
405- "bytesTotal" : 0 ,
406- "percentage" : 0
407- },
408- # 添加额外的时间戳信息 - 使用datetime替代time模块避免命名冲突
409- "timeAdded" : int (datetime .now ().timestamp ()),
410- "timeUpdated" : int (datetime .now ().timestamp ())
411- }
429+ # 安全的类型转换
430+ item_info ["state" ]["installed" ] = bool (installed )
431+ item_info ["installedFolder" ] = str (folder ) if folder and isinstance (folder , (str , bytes )) else None
412432
413- # 从批量查询结果中提取详情
414- if item_id in ugc_results :
415- result = ugc_results [item_id ]
416- # 从结果中提取信息
417- if hasattr (result , 'title' ) and result .title :
418- item_info ['title' ] = result .title .decode ('utf-8' , errors = 'replace' )
419- if hasattr (result , 'description' ) and result .description :
420- item_info ['description' ] = result .description .decode ('utf-8' , errors = 'replace' )
421- # 获取创建和更新时间
422- if hasattr (result , 'timeCreated' ):
423- item_info ['timeAdded' ] = int (result .timeCreated )
424- if hasattr (result , 'timeUpdated' ):
425- item_info ['timeUpdated' ] = int (result .timeUpdated )
426- # 获取作者信息
427- if hasattr (result , 'steamIDOwner' ):
428- item_info ['steamIDOwner' ] = str (result .steamIDOwner )
429- # 获取文件大小信息
430- if hasattr (result , 'fileSize' ):
431- item_info ['fileSizeOnDisk' ] = int (result .fileSize )
432-
433- logger .info (f"使用批量查询结果填充物品 { item_id } 详情" )
433+ # 处理大小值
434+ if isinstance (size , (int , float )):
435+ item_info ["fileSizeOnDisk" ] = int (size )
436+ else :
437+ item_info ["fileSizeOnDisk" ] = 0
438+ else :
439+ logger .warning (f'物品 { item_id } 的安装信息返回格式未知: { type (result )} - { result } ' )
440+ item_info ["state" ]["installed" ] = False
441+ except Exception as e :
442+ logger .warning (f'获取物品 { item_id } 安装信息失败: { e } ' )
443+ item_info ["state" ]["installed" ] = False
444+
445+ # 尝试获取物品下载信息(如果正在下载)
446+ try :
447+ logger .debug (f'获取物品 { item_id } 的下载信息' )
448+ result = steamworks .Workshop .GetItemDownloadInfo (item_id )
449+
450+ # 检查返回值的结构 - 支持字典格式(与安装信息保持一致)
451+ if isinstance (result , dict ):
452+ logger .debug (f'物品 { item_id } 下载信息字典: { result } ' )
434453
435- # 尝试获取物品安装信息(如果已安装)
436-
454+ # 使用正确的键名获取下载信息
455+ downloaded = result .get ('downloaded' , 0 )
456+ total = result .get ('total' , 0 )
457+ progress = result .get ('progress' , 0.0 )
458+
459+ # 根据total和downloaded确定是否正在下载
460+ item_info ["state" ]["downloading" ] = total > 0 and downloaded < total
461+
462+ # 设置下载进度信息
463+ if downloaded > 0 or total > 0 :
464+ item_info ["downloadProgress" ] = {
465+ "bytesDownloaded" : int (downloaded ),
466+ "bytesTotal" : int (total ),
467+ "percentage" : progress * 100 if isinstance (progress , (int , float )) else 0
468+ }
469+ # 也支持元组格式作为备选
470+ elif isinstance (result , tuple ) and len (result ) >= 3 :
471+ # 元组中应该包含下载状态、已下载字节数和总字节数
472+ downloaded , total , progress = result if len (result ) >= 3 else (0 , 0 , 0.0 )
473+ logger .debug (f'物品 { item_id } 下载状态: 已下载={ downloaded } , 总计={ total } , 进度={ progress } ' )
474+
475+ # 根据total和downloaded确定是否正在下载
476+ item_info ["state" ]["downloading" ] = total > 0 and downloaded < total
477+
478+ # 设置下载进度信息
479+ if downloaded > 0 or total > 0 :
480+ # 处理可能的类型转换
481+ try :
482+ downloaded_value = int (downloaded .value ) if hasattr (downloaded , 'value' ) else int (downloaded )
483+ total_value = int (total .value ) if hasattr (total , 'value' ) else int (total )
484+ progress_value = float (progress .value ) if hasattr (progress , 'value' ) else float (progress )
485+ except : # noqa
486+ downloaded_value , total_value , progress_value = 0 , 0 , 0.0
487+
488+ item_info ["downloadProgress" ] = {
489+ "bytesDownloaded" : downloaded_value ,
490+ "bytesTotal" : total_value ,
491+ "percentage" : progress_value * 100
492+ }
493+ else :
494+ logger .warning (f'物品 { item_id } 的下载信息返回格式未知: { type (result )} - { result } ' )
495+ item_info ["state" ]["downloading" ] = False
496+ except Exception as e :
497+ logger .warning (f'获取物品 { item_id } 下载信息失败: { e } ' )
498+ item_info ["state" ]["downloading" ] = False
499+
500+ # 从批量查询结果中提取物品详情
501+ if item_id in ugc_results :
502+ result = ugc_results [item_id ]
503+ try :
504+ if hasattr (result , 'title' ) and result .title :
505+ item_info ['title' ] = result .title .decode ('utf-8' , errors = 'replace' )
506+ if hasattr (result , 'description' ) and result .description :
507+ item_info ['description' ] = result .description .decode ('utf-8' , errors = 'replace' )
508+ if hasattr (result , 'timeCreated' ):
509+ item_info ['timeAdded' ] = int (result .timeCreated )
510+ if hasattr (result , 'timeUpdated' ):
511+ item_info ['timeUpdated' ] = int (result .timeUpdated )
512+ if hasattr (result , 'steamIDOwner' ):
513+ item_info ['steamIDOwner' ] = str (result .steamIDOwner )
514+ if hasattr (result , 'fileSize' ):
515+ item_info ['fileSizeOnDisk' ] = int (result .fileSize )
516+ logger .debug (f"从批量查询结果填充物品 { item_id } 详情" )
517+ except Exception as detail_error :
518+ logger .warning (f"提取物品 { item_id } 详情时出错: { detail_error } " )
519+
437520 # 作为备选方案,如果本地有安装路径,尝试从本地文件获取信息
438521 if item_info ['title' ].startswith ('未知物品_' ) or not item_info ['description' ]:
439522 install_folder = item_info .get ('installedFolder' )
0 commit comments