From 5a0441e1083747a25132b3a23c77850d7bf45910 Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Thu, 2 Feb 2023 22:37:52 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 更改项目结构为软件包 * 使用PyCharm进行自动格式化及优化导入 * 重构丘丘语查询 --- CHANGELOG.md | 11 +- README.md | 19 +- __init__.py | 50 - almanac/assets/almanac_list.json | 70 - almanac/assets/config.json | 6 - almanac/assets/lots_list.json | 1922 ----------------- artifact_collect/artifact_list.json | 165 -- artifact_collect/artifact_property.json | 12 - artifact_collect/property_list.json | 34 - config.py | 42 - poetry.lock | 174 ++ pyproject.toml | 19 + qiu_qiu_translation/__init__.py | 36 - qiu_qiu_translation/qiu_qiu_translation.py | 85 - src/__init__.py | 0 {almanac => src/almanac}/__init__.py | 5 +- {almanac => src/almanac}/almanac.py | 10 +- src/almanac/assets/almanac_list.json | 159 ++ {almanac => src/almanac}/assets/back.png | Bin src/almanac/assets/config.json | 6 + {almanac => src/almanac}/assets/lots_bg.png | Bin src/almanac/assets/lots_list.json | 1922 +++++++++++++++++ ...1\344\273\252\346\226\207\351\273\221.ttf" | Bin {almanac => src/almanac}/draw_lots.py | 13 +- {almanac => src/almanac}/group_list.json | 0 {almanac => src/almanac}/tweaks.py | 7 +- .../artifact_collect}/Artifact.py | 111 +- .../artifact_collect}/__init__.py | 8 +- src/artifact_collect/artifact_list.json | 272 +++ src/artifact_collect/artifact_property.json | 68 + .../artifact_collect}/icon/0.png | Bin .../artifact_collect}/icon/1.png | Bin .../artifact_collect}/icon/14001_0.png | Bin .../artifact_collect}/icon/14001_1.png | Bin .../artifact_collect}/icon/14001_2.png | Bin .../artifact_collect}/icon/14001_3.png | Bin .../artifact_collect}/icon/14001_4.png | Bin .../artifact_collect}/icon/14002_0.png | Bin .../artifact_collect}/icon/14002_1.png | Bin .../artifact_collect}/icon/14002_2.png | Bin .../artifact_collect}/icon/14002_3.png | Bin .../artifact_collect}/icon/14002_4.png | Bin .../artifact_collect}/icon/14003_0.png | Bin .../artifact_collect}/icon/14003_1.png | Bin .../artifact_collect}/icon/14003_2.png | Bin .../artifact_collect}/icon/14003_3.png | Bin .../artifact_collect}/icon/14003_4.png | Bin .../artifact_collect}/icon/14004_0.png | Bin .../artifact_collect}/icon/14004_1.png | Bin .../artifact_collect}/icon/14004_2.png | Bin .../artifact_collect}/icon/14004_3.png | Bin .../artifact_collect}/icon/14004_4.png | Bin .../artifact_collect}/icon/14005_0.png | Bin .../artifact_collect}/icon/14005_1.png | Bin .../artifact_collect}/icon/14005_2.png | Bin .../artifact_collect}/icon/14005_3.png | Bin .../artifact_collect}/icon/14005_4.png | Bin .../artifact_collect}/icon/14006_0.png | Bin .../artifact_collect}/icon/14006_1.png | Bin .../artifact_collect}/icon/14006_2.png | Bin .../artifact_collect}/icon/14006_3.png | Bin .../artifact_collect}/icon/14006_4.png | Bin .../artifact_collect}/icon/15001_0.png | Bin .../artifact_collect}/icon/15001_1.png | Bin .../artifact_collect}/icon/15001_2.png | Bin .../artifact_collect}/icon/15001_3.png | Bin .../artifact_collect}/icon/15001_4.png | Bin .../artifact_collect}/icon/15002_0.png | Bin .../artifact_collect}/icon/15002_1.png | Bin .../artifact_collect}/icon/15002_2.png | Bin .../artifact_collect}/icon/15002_3.png | Bin .../artifact_collect}/icon/15002_4.png | Bin .../artifact_collect}/icon/15003_0.png | Bin .../artifact_collect}/icon/15003_1.png | Bin .../artifact_collect}/icon/15003_2.png | Bin .../artifact_collect}/icon/15003_3.png | Bin .../artifact_collect}/icon/15003_4.png | Bin .../artifact_collect}/icon/15004_0.png | Bin .../artifact_collect}/icon/15004_1.png | Bin .../artifact_collect}/icon/15004_2.png | Bin .../artifact_collect}/icon/15004_3.png | Bin .../artifact_collect}/icon/15004_4.png | Bin .../artifact_collect}/icon/15005_0.png | Bin .../artifact_collect}/icon/15005_1.png | Bin .../artifact_collect}/icon/15005_2.png | Bin .../artifact_collect}/icon/15005_3.png | Bin .../artifact_collect}/icon/15005_4.png | Bin .../artifact_collect}/icon/15006_0.png | Bin .../artifact_collect}/icon/15006_1.png | Bin .../artifact_collect}/icon/15006_2.png | Bin .../artifact_collect}/icon/15006_3.png | Bin .../artifact_collect}/icon/15006_4.png | Bin .../artifact_collect}/icon/15007_0.png | Bin .../artifact_collect}/icon/15007_1.png | Bin .../artifact_collect}/icon/15007_2.png | Bin .../artifact_collect}/icon/15007_3.png | Bin .../artifact_collect}/icon/15007_4.png | Bin .../artifact_collect}/icon/15008_0.png | Bin .../artifact_collect}/icon/15008_1.png | Bin .../artifact_collect}/icon/15008_2.png | Bin .../artifact_collect}/icon/15008_3.png | Bin .../artifact_collect}/icon/15008_4.png | Bin .../artifact_collect}/icon/15017_0.png | Bin .../artifact_collect}/icon/15017_1.png | Bin .../artifact_collect}/icon/15017_2.png | Bin .../artifact_collect}/icon/15017_3.png | Bin .../artifact_collect}/icon/15017_4.png | Bin .../artifact_collect}/icon/15018_0.png | Bin .../artifact_collect}/icon/15018_1.png | Bin .../artifact_collect}/icon/15018_2.png | Bin .../artifact_collect}/icon/15018_3.png | Bin .../artifact_collect}/icon/15018_4.png | Bin .../artifact_collect}/icon/15019_0.png | Bin .../artifact_collect}/icon/15019_1.png | Bin .../artifact_collect}/icon/15019_2.png | Bin .../artifact_collect}/icon/15019_3.png | Bin .../artifact_collect}/icon/15019_4.png | Bin .../artifact_collect}/icon/15020_0.png | Bin .../artifact_collect}/icon/15020_1.png | Bin .../artifact_collect}/icon/15020_2.png | Bin .../artifact_collect}/icon/15020_3.png | Bin .../artifact_collect}/icon/15020_4.png | Bin .../artifact_collect}/icon/15021_0.png | Bin .../artifact_collect}/icon/15021_1.png | Bin .../artifact_collect}/icon/15021_2.png | Bin .../artifact_collect}/icon/15021_3.png | Bin .../artifact_collect}/icon/15021_4.png | Bin .../artifact_collect}/icon/15022_0.png | Bin .../artifact_collect}/icon/15022_1.png | Bin .../artifact_collect}/icon/15022_2.png | Bin .../artifact_collect}/icon/15022_3.png | Bin .../artifact_collect}/icon/15022_4.png | Bin .../artifact_collect}/icon/15023_0.png | Bin .../artifact_collect}/icon/15023_1.png | Bin .../artifact_collect}/icon/15023_2.png | Bin .../artifact_collect}/icon/15023_3.png | Bin .../artifact_collect}/icon/15023_4.png | Bin .../artifact_collect}/icon/15024_0.png | Bin .../artifact_collect}/icon/15024_1.png | Bin .../artifact_collect}/icon/15024_2.png | Bin .../artifact_collect}/icon/15024_3.png | Bin .../artifact_collect}/icon/15024_4.png | Bin .../artifact_collect}/icon/2.png | Bin .../artifact_collect}/icon/3.png | Bin .../artifact_collect}/icon/4.png | Bin .../artifact_collect}/icon/background.png | Bin .../artifact_collect}/json_rw.py | 27 +- src/artifact_collect/property_list.json | 204 ++ .../artifact_collect}/zh-cn.ttf | Bin .../artifact_rate}/__init__.py | 12 +- .../artifact_rate}/artifact_eval.py | 5 +- src/asset_manager.py | 130 ++ {gacha => src/gacha}/__init__.py | 47 +- {gacha => src/gacha}/gacha.py | 93 +- {gacha => src/gacha}/icon/1_star.png | Bin {gacha => src/gacha}/icon/1_star_bg.png | Bin {gacha => src/gacha}/icon/2_star.png | Bin {gacha => src/gacha}/icon/2_star_bg.png | Bin {gacha => src/gacha}/icon/3_star.png | Bin {gacha => src/gacha}/icon/3_star_bg.png | Bin {gacha => src/gacha}/icon/4_star.png | Bin {gacha => src/gacha}/icon/4_star_bg.png | Bin {gacha => src/gacha}/icon/5_star.png | Bin {gacha => src/gacha}/icon/5_star_bg.png | Bin {gacha => src/gacha}/icon/anemo.png | Bin {gacha => src/gacha}/icon/cryo.png | Bin {gacha => src/gacha}/icon/default.png | Bin {gacha => src/gacha}/icon/dendro.png | Bin {gacha => src/gacha}/icon/electro.png | Bin {gacha => src/gacha}/icon/geo.png | Bin {gacha => src/gacha}/icon/hydro.png | Bin {gacha => src/gacha}/icon/pyro.png | Bin {gacha => src/gacha}/pool_data.py | 118 +- .../material_remind}/__init__.py | 57 +- ...0\344\270\200\345\221\250\345\233\233.png" | Bin ...0\344\270\211\345\221\250\345\205\255.png" | Bin ...0\344\272\214\345\221\250\344\272\224.png" | Bin ...0\344\270\200\345\221\250\345\233\233.png" | Bin ...0\344\270\211\345\221\250\345\205\255.png" | Bin ...0\344\272\214\345\221\250\344\272\224.png" | Bin src/qiu_qiu_translation/__init__.py | 1 + .../qiu_qiu_dictionary.json | 35 +- .../qiu_qiu_translation.py | 114 + .../query_resource_points}/__init__.py | 3 +- .../query_resource_points}/icon/0.png | Bin .../query_resource_points}/icon/box.png | Bin .../query_resource_points}/icon/box_alpha.png | Bin .../query_resource_points.py | 117 +- 188 files changed, 3368 insertions(+), 2821 deletions(-) delete mode 100644 __init__.py delete mode 100644 almanac/assets/almanac_list.json delete mode 100644 almanac/assets/config.json delete mode 100644 almanac/assets/lots_list.json delete mode 100644 artifact_collect/artifact_list.json delete mode 100644 artifact_collect/artifact_property.json delete mode 100644 artifact_collect/property_list.json delete mode 100644 config.py create mode 100644 poetry.lock create mode 100644 pyproject.toml delete mode 100644 qiu_qiu_translation/__init__.py delete mode 100644 qiu_qiu_translation/qiu_qiu_translation.py create mode 100644 src/__init__.py rename {almanac => src/almanac}/__init__.py (99%) rename {almanac => src/almanac}/almanac.py (100%) create mode 100644 src/almanac/assets/almanac_list.json rename {almanac => src/almanac}/assets/back.png (100%) create mode 100644 src/almanac/assets/config.json rename {almanac => src/almanac}/assets/lots_bg.png (100%) create mode 100644 src/almanac/assets/lots_list.json rename "almanac/assets/\346\261\211\344\273\252\346\226\207\351\273\221.ttf" => "src/almanac/assets/\346\261\211\344\273\252\346\226\207\351\273\221.ttf" (100%) rename {almanac => src/almanac}/draw_lots.py (99%) rename {almanac => src/almanac}/group_list.json (100%) rename {almanac => src/almanac}/tweaks.py (97%) rename {artifact_collect => src/artifact_collect}/Artifact.py (77%) rename {artifact_collect => src/artifact_collect}/__init__.py (99%) create mode 100644 src/artifact_collect/artifact_list.json create mode 100644 src/artifact_collect/artifact_property.json rename {artifact_collect => src/artifact_collect}/icon/0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14001_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14001_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14001_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14001_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14001_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14002_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14002_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14002_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14002_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14002_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14003_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14003_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14003_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14003_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14003_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14004_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14004_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14004_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14004_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14004_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14005_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14005_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14005_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14005_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14005_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14006_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14006_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14006_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14006_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/14006_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15001_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15001_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15001_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15001_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15001_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15002_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15002_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15002_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15002_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15002_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15003_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15003_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15003_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15003_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15003_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15004_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15004_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15004_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15004_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15004_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15005_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15005_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15005_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15005_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15005_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15006_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15006_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15006_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15006_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15006_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15007_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15007_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15007_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15007_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15007_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15008_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15008_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15008_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15008_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15008_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15017_0.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15017_1.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15017_2.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15017_3.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15017_4.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15018_0.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15018_1.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15018_2.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15018_3.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15018_4.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15019_0.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15019_1.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15019_2.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15019_3.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15019_4.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15020_0.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15020_1.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15020_2.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15020_3.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15020_4.png (100%) mode change 100755 => 100644 rename {artifact_collect => src/artifact_collect}/icon/15021_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15021_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15021_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15021_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15021_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15022_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15022_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15022_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15022_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15022_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15023_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15023_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15023_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15023_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15023_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15024_0.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15024_1.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15024_2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15024_3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/15024_4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/2.png (100%) rename {artifact_collect => src/artifact_collect}/icon/3.png (100%) rename {artifact_collect => src/artifact_collect}/icon/4.png (100%) rename {artifact_collect => src/artifact_collect}/icon/background.png (100%) rename {artifact_collect => src/artifact_collect}/json_rw.py (76%) create mode 100644 src/artifact_collect/property_list.json rename {artifact_collect => src/artifact_collect}/zh-cn.ttf (100%) rename {artifact_rate => src/artifact_rate}/__init__.py (97%) rename {artifact_rate => src/artifact_rate}/artifact_eval.py (99%) create mode 100644 src/asset_manager.py rename {gacha => src/gacha}/__init__.py (77%) rename {gacha => src/gacha}/gacha.py (88%) rename {gacha => src/gacha}/icon/1_star.png (100%) rename {gacha => src/gacha}/icon/1_star_bg.png (100%) rename {gacha => src/gacha}/icon/2_star.png (100%) rename {gacha => src/gacha}/icon/2_star_bg.png (100%) rename {gacha => src/gacha}/icon/3_star.png (100%) rename {gacha => src/gacha}/icon/3_star_bg.png (100%) rename {gacha => src/gacha}/icon/4_star.png (100%) rename {gacha => src/gacha}/icon/4_star_bg.png (100%) rename {gacha => src/gacha}/icon/5_star.png (100%) rename {gacha => src/gacha}/icon/5_star_bg.png (100%) rename {gacha => src/gacha}/icon/anemo.png (100%) rename {gacha => src/gacha}/icon/cryo.png (100%) rename {gacha => src/gacha}/icon/default.png (100%) rename {gacha => src/gacha}/icon/dendro.png (100%) rename {gacha => src/gacha}/icon/electro.png (100%) rename {gacha => src/gacha}/icon/geo.png (100%) rename {gacha => src/gacha}/icon/hydro.png (100%) rename {gacha => src/gacha}/icon/pyro.png (100%) rename {gacha => src/gacha}/pool_data.py (73%) rename {material_remind => src/material_remind}/__init__.py (70%) rename "material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" => "src/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" (100%) rename "material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" => "src/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" (100%) rename "material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" => "src/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" (100%) rename "material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" => "src/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" (100%) rename "material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" => "src/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" (100%) rename "material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" => "src/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" (100%) create mode 100644 src/qiu_qiu_translation/__init__.py rename {qiu_qiu_translation => src/qiu_qiu_translation}/qiu_qiu_dictionary.json (97%) create mode 100644 src/qiu_qiu_translation/qiu_qiu_translation.py rename {query_resource_points => src/query_resource_points}/__init__.py (98%) rename {query_resource_points => src/query_resource_points}/icon/0.png (100%) rename {query_resource_points => src/query_resource_points}/icon/box.png (100%) rename {query_resource_points => src/query_resource_points}/icon/box_alpha.png (100%) rename {query_resource_points => src/query_resource_points}/query_resource_points.py (78%) diff --git a/CHANGELOG.md b/CHANGELOG.md index f39e8ac..b5d24ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,6 @@ * 修复卡池问题 @ [89f162b](https://github.com/H-K-Y/Genshin_Impact_bot/commit/89f162b) * 修复了抽卡、材料获取、黄历在频道中报错的问题 @ [fd28f9e](https://github.com/H-K-Y/Genshin_Impact_bot/commit/fd28f9e) - ### 2021-10-30 * 解决超时导致的图鉴图标更新失败问题 @ [542f48e](https://github.com/H-K-Y/Genshin_Impact_bot/commit/542f48e) @@ -42,11 +41,12 @@ ### 2021-8-16 -* 项目移植到nonebot 2 @ [6c1f73b](https://github.com/H-K-Y/Genshin_Impact_bot/commit/6c1f73b) +* 项目移植到nonebot 2 @ [6c1f73b](https://github.com/H-K-Y/Genshin_Impact_bot/commit/6c1f73b) ### 2021-8-14 -* 加入 [圣遗物评分](https://github.com/H-K-Y/Genshin_Impact_bot/issues/31) @ [9e5eabf](https://github.com/H-K-Y/Genshin_Impact_bot/commit/9e5eabf) +* 加入 [圣遗物评分](https://github.com/H-K-Y/Genshin_Impact_bot/issues/31) + @ [9e5eabf](https://github.com/H-K-Y/Genshin_Impact_bot/commit/9e5eabf) * 更新卡池 @ [8b68ef6](https://github.com/H-K-Y/Genshin_Impact_bot/commit/8b68ef6) ### 2021-7-27 @@ -60,7 +60,6 @@ * 更新README.md @ [33a4712](https://github.com/H-K-Y/Genshin_Impact_bot/commit/33a4712) * 部分代码依照PEP标准进行格式化 @ [33a4712](https://github.com/H-K-Y/Genshin_Impact_bot/commit/33a4712) - ### 2021-3-28 * 圣遗物收集修改冰本的圣遗物名称,增加岩本 @ [c949f00](https://github.com/H-K-Y/Genshin_Impact_bot/commit/c949f00) @@ -113,14 +112,14 @@ ### 2020-10-21 * 在config.py加入了抽卡限制功能,限制每个人一天最多抽多少次 @ [bcdcba0](https://github.com/H-K-Y/Genshin_Impact_bot/commit/bcdcba0) - 感谢[corvo007](https://github.com/corvo007)提出的粪pr (粪pr是他自己说的 + 感谢[corvo007](https://github.com/corvo007)提出的粪pr (粪pr是他自己说的 * 修复了第一次切换卡池后不能再切换卡池的问题 @ [2ea0ea2](https://github.com/H-K-Y/Genshin_Impact_bot/commit/2ea0ea2) * 修复了查看UP信息时报错的问题 @ [2ea0ea2](https://github.com/H-K-Y/Genshin_Impact_bot/commit/2ea0ea2) ### 2020-10-20 * 重构了项目代码 @ [d446ce6](https://github.com/H-K-Y/Genshin_Impact_bot/commit/d446ce6) - ~~第二天就重写?,过几天怕是忘了写的啥了........~~ + ~~第二天就重写?,过几天怕是忘了写的啥了........~~ * 加入的武器UP池和常驻池 @ [d446ce6](https://github.com/H-K-Y/Genshin_Impact_bot/commit/d446ce6) * 加入了切换卡池的功能 @ [d446ce6](https://github.com/H-K-Y/Genshin_Impact_bot/commit/d446ce6) diff --git a/README.md b/README.md index 29fce6f..99f0d3a 100644 --- a/README.md +++ b/README.md @@ -10,18 +10,19 @@ ![LANG](https://img.shields.io/badge/language-python-3572A5?style=flat-square) ![Hoshino](https://img.shields.io/badge/%E7%89%88%E6%9C%AC-Hoshino-ff8a80?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyBkYXRhLXYtMTEyNDFiYTI9IiIgYXJpYS1oaWRkZW49InRydWUiIGZvY3VzYWJsZT0iZmFsc2UiIGRhdGEtcHJlZml4PSJmYXMiIGRhdGEtaWNvbj0iY29kZS1icmFuY2giIHJvbGU9ImltZyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMzg0IDUxMiIgY2xhc3M9InN2Zy1pbmxpbmUtLWZhIGZhLWNvZGUtYnJhbmNoIGZhLXctMTIiIGNvbG9yPSIjZmZmZmZmIj48cGF0aCBkYXRhLXYtMTEyNDFiYTI9IiIgZmlsbD0iY3VycmVudENvbG9yIiBkPSJNMzg0IDE0NGMwLTQ0LjItMzUuOC04MC04MC04MHMtODAgMzUuOC04MCA4MGMwIDM2LjQgMjQuMyA2Ny4xIDU3LjUgNzYuOC0uNiAxNi4xLTQuMiAyOC41LTExIDM2LjktMTUuNCAxOS4yLTQ5LjMgMjIuNC04NS4yIDI1LjctMjguMiAyLjYtNTcuNCA1LjQtODEuMyAxNi45di0xNDRjMzIuNS0xMC4yIDU2LTQwLjUgNTYtNzYuMyAwLTQ0LjItMzUuOC04MC04MC04MFMwIDM1LjggMCA4MGMwIDM1LjggMjMuNSA2Ni4xIDU2IDc2LjN2MTk5LjNDMjMuNSAzNjUuOSAwIDM5Ni4yIDAgNDMyYzAgNDQuMiAzNS44IDgwIDgwIDgwczgwLTM1LjggODAtODBjMC0zNC0yMS4yLTYzLjEtNTEuMi03NC42IDMuMS01LjIgNy44LTkuOCAxNC45LTEzLjQgMTYuMi04LjIgNDAuNC0xMC40IDY2LjEtMTIuOCA0Mi4yLTMuOSA5MC04LjQgMTE4LjItNDMuNCAxNC0xNy40IDIxLjEtMzkuOCAyMS42LTY3LjkgMzEuNi0xMC44IDU0LjQtNDAuNyA1NC40LTc1Ljl6TTgwIDY0YzguOCAwIDE2IDcuMiAxNiAxNnMtNy4yIDE2LTE2IDE2LTE2LTcuMi0xNi0xNiA3LjItMTYgMTYtMTZ6bTAgMzg0Yy04LjggMC0xNi03LjItMTYtMTZzNy4yLTE2IDE2LTE2IDE2IDcuMiAxNiAxNi03LjIgMTYtMTYgMTZ6bTIyNC0zMjBjOC44IDAgMTYgNy4yIDE2IDE2cy03LjIgMTYtMTYgMTYtMTYtNy4yLTE2LTE2IDcuMi0xNiAxNi0xNnoiIGNsYXNzPSIiPjwvcGF0aD48L3N2Zz4=) -![Nonebot2](https://img.shields.io/badge/%E7%89%88%E6%9C%AC-Nonebot2-a7ffeb?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyBkYXRhLXYtMTEyNDFiYTI9IiIgYXJpYS1oaWRkZW49InRydWUiIGZvY3VzYWJsZT0iZmFsc2UiIGRhdGEtcHJlZml4PSJmYXMiIGRhdGEtaWNvbj0iY29kZS1icmFuY2giIHJvbGU9ImltZyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMzg0IDUxMiIgY2xhc3M9InN2Zy1pbmxpbmUtLWZhIGZhLWNvZGUtYnJhbmNoIGZhLXctMTIiIGNvbG9yPSIjZmZmZmZmIj48cGF0aCBkYXRhLXYtMTEyNDFiYTI9IiIgZmlsbD0iY3VycmVudENvbG9yIiBkPSJNMzg0IDE0NGMwLTQ0LjItMzUuOC04MC04MC04MHMtODAgMzUuOC04MCA4MGMwIDM2LjQgMjQuMyA2Ny4xIDU3LjUgNzYuOC0uNiAxNi4xLTQuMiAyOC41LTExIDM2LjktMTUuNCAxOS4yLTQ5LjMgMjIuNC04NS4yIDI1LjctMjguMiAyLjYtNTcuNCA1LjQtODEuMyAxNi45di0xNDRjMzIuNS0xMC4yIDU2LTQwLjUgNTYtNzYuMyAwLTQ0LjItMzUuOC04MC04MC04MFMwIDM1LjggMCA4MGMwIDM1LjggMjMuNSA2Ni4xIDU2IDc2LjN2MTk5LjNDMjMuNSAzNjUuOSAwIDM5Ni4yIDAgNDMyYzAgNDQuMiAzNS44IDgwIDgwIDgwczgwLTM1LjggODAtODBjMC0zNC0yMS4yLTYzLjEtNTEuMi03NC42IDMuMS01LjIgNy44LTkuOCAxNC45LTEzLjQgMTYuMi04LjIgNDAuNC0xMC40IDY2LjEtMTIuOCA0Mi4yLTMuOSA5MC04LjQgMTE4LjItNDMuNCAxNC0xNy40IDIxLjEtMzkuOCAyMS42LTY3LjkgMzEuNi0xMC44IDU0LjQtNDAuNyA1NC40LTc1Ljl6TTgwIDY0YzguOCAwIDE2IDcuMiAxNiAxNnMtNy4yIDE2LTE2IDE2LTE2LTcuMi0xNi0xNiA3LjItMTYgMTYtMTZ6bTAgMzg0Yy04LjggMC0xNi03LjItMTYtMTZzNy4yLTE2IDE2LTE2IDE2IDcuMiAxNiAxNi03LjIgMTYtMTYgMTZ6bTIyNC0zMjBjOC44IDAgMTYgNy4yIDE2IDE2cy03LjIgMTYtMTYgMTYtMTYtNy4yLTE2LTE2IDcuMi0xNiAxNi0xNnoiIGNsYXNzPSIiPjwvcGF0aD48L3N2Zz4=) -![QQ](https://img.shields.io/badge/QQ-GI%20Bot%20Group-9cf?logo=Tencent%20QQ&style=for-the-badge) +![Nonebot2](https://img.shields.io/badge/%E7%89%88%E6%9C%AC-Nonebot2-a7ffeb?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyBkYXRhLXYtMTEyNDFiYTI9IiIgYXJpYS1oaWRkZW49InRydWUiIGZvY3VzYWJsZT0iZmFsc2UiIGRhdGEtcHJlZml4PSJmYXMiIGRhdGEtaWNvbj0iY29kZS1icmFuY2giIHJvbGU9ImltZyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMzg0IDUxMiIgY2xhc3M9InN2Zy1pbmxpbmUtLWZhIGZhLWNvZGUtYnJhbmNoIGZhLXctMTIiIGNvbG9yPSIjZmZmZmZmIj48cGF0aCBkYXRhLXYtMTEyNDFiYTI9IiIgZmlsbD0iY3VycmVudENvbG9yIiBkPSJNMzg0IDE0NGMwLTQ0LjItMzUuOC04MC04MC04MHMtODAgMzUuOC04MCA4MGMwIDM2LjQgMjQuMyA2Ny4xIDU3LjUgNzYuOC0uNiAxNi4xLTQuMiAyOC41LTExIDM2LjktMTUuNCAxOS4yLTQ5LjMgMjIuNC04NS4yIDI1LjctMjguMiAyLjYtNTcuNCA1LjQtODEuMyAxNi45di0xNDRjMzIuNS0xMC4yIDU2LTQwLjUgNTYtNzYuMyAwLTQ0LjItMzUuOC04MC04MC04MFMwIDM1LjggMCA4MGMwIDM1LjggMjMuNSA2Ni4xIDU2IDc2LjN2MTk5LjNDMjMuNSAzNjUuOSAwIDM5Ni4yIDAgNDMyYzAgNDQuMiAzNS44IDgwIDgwIDgwczgwLTM1LjggODAtODBjMC0zNC0yMS4yLTYzLjEtNTEuMi03NC42IDMuMS01LjIgNy44LTkuOCAxNC45LTEzLjQgMTYuMi04LjIgNDAuNC0xMC40IDY2LjEtMTIuOCA0Mi4yLTMuOSA5MC04LjQgMTE4LjItNDMuNCAxNC0xNy40IDIxLjEtMzkuOCAyMS42LTY3LjkgMzEuNi0xMC44IDU0LjQtNDAuNyA1NC40LTc1Ljl6TTgwIDY0YzguOCAwIDE2IDcuMiAxNiAxNnMtNy4yIDE2LTE2IDE2LTE2LTcuMi0xNi0xNiA3LjItMTYgMTYtMTZ6bTAgMzg0Yy04LjggMC0xNi03LjItMTYtMTZzNy4yLTE2IDE2LTE2IDE2IDcuMiAxNiAxNi03LjIgMTYtMTYgMTZ6bTIyNC0zMjBjOC44IDAgMTYgNy4yIDE2IDE2cy03LjIgMTYtMTYgMTYtMTYtNy4yLTE2LTE2IDcuMi0xNiAxNi0xNnoiIGNsYXNzPSIiPjwvcGF0aD48L3N2Zz4=) +![QQ](https://img.shields.io/badge/QQ-GI%20Bot%20Group-9cf?logo=Tencent%20QQ&style=for-the-badge) ->This is a Genshin Impact plugin for [HoshinoBot](https://github.com/Ice-Cirno/HoshinoBot) +> This is a Genshin Impact plugin for [HoshinoBot](https://github.com/Ice-Cirno/HoshinoBot) > >这是一个[HoshinoBot](https://github.com/Ice-Cirno/HoshinoBot)和[nonebot2](https://github.com/nonebot/nonebot2)的原神相关插件 ~~这个项目目前正在扩展,加入更多原神相关娱乐和信息查询功能,敬请期待~~ -#### 因原作者弃坑/nonebot进入beta时代/米游社API变动/多维度地图等诸多原因导致难以在原有版本上进行修改,将于不久后**停止对该版本功能的增加**并完全转向下一个版本;加群了解更多 [GI Bot Group](https://jq.qq.com/?_wv=1027&k=1faV2txy) +#### 因原作者弃坑/nonebot进入beta时代/米游社API变动/多维度地图等诸多原因导致难以在原有版本上进行修改,将于不久后** +停止对该版本功能的增加**并完全转向下一个版本;加群了解更多 [GI Bot Group](https://jq.qq.com/?_wv=1027&k=1faV2txy) 讨论群[GI Bot Group](https://jq.qq.com/?_wv=1027&k=1faV2txy) @@ -34,12 +35,12 @@ ## 目录 - **部署** - - [安装(HoshinoBot)](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%AE%89%E8%A3%85%EF%BC%88Hoshino%EF%BC%89) - - [安装(NoneBot2)](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%AE%89%E8%A3%85%EF%BC%88Nonebot2%EF%BC%89) + - [安装(HoshinoBot)](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%AE%89%E8%A3%85%EF%BC%88Hoshino%EF%BC%89) + - [安装(NoneBot2)](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%AE%89%E8%A3%85%EF%BC%88Nonebot2%EF%BC%89) - **使用** - - [命令](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%91%BD%E4%BB%A4) - - [演示](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E6%95%88%E6%9E%9C%E6%BC%94%E7%A4%BA) - - [常见问题](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) + - [命令](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%91%BD%E4%BB%A4) + - [演示](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E6%95%88%E6%9E%9C%E6%BC%94%E7%A4%BA) + - [常见问题](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) ## 更新记录 diff --git a/__init__.py b/__init__.py deleted file mode 100644 index d24de60..0000000 --- a/__init__.py +++ /dev/null @@ -1,50 +0,0 @@ -from hoshino import Service - -sv = Service("原神帮助") - -help_txt = '''这是一个HoshinoBot的原神相关插件,包含原神抽卡,丘丘语翻译,找神瞳,找资源点等功能 -插件仓库在 https://github.com/H-K-Y/Genshin_Impact_bot.git - -指令: - -@bot相遇之缘:10连抽卡 -@bot纠缠之缘:90连抽卡 -@bot原之井:180连抽卡 -原神卡池:查看当前UP池 -原神卡池切换:切换其他原神卡池 -更新原神卡池:爬取官方的卡池数据 - -丘丘一下 丘丘语句 :翻译丘丘语,注意这个翻译只能把丘丘语翻译成中文,不能反向 -丘丘词典 丘丘语句 :查询丘丘语句的单词含义 - -XXX哪里有:查询XXX的位置图,XXX是资源的名字 -原神资源列表:查询所有的资源名称 - -圣遗物收集 -原神副本 : 查询当前有哪些副本,掉落哪个套装 -刷副本 副本名称 : 刷一次副本,可获得狗粮点数和圣遗物 -查看圣遗物仓库 1 : 查询仓库第一页有哪些圣遗物 -强化圣遗物10级 5 : 把仓库编号为5的圣遗物强化10级 -圣遗物洗点 5 : 把仓库编号为5的圣遗物洗点,洗点后返还50%的强化点数,强化等级降为0,全属性重新随机 -圣遗物详情 5 : 查看圣遗物详情 -转换狗粮 5 : 把仓库编号为5的圣遗物销毁转化为狗粮,会返还80%狗粮点数 -查看体力值 : 查看自己体力值 -氪体力 @群友 : 给群友氪体力,这个命令只有机器人管理员才能执行 - -原神黄历 -原神黄历 : 查看今天的黄历 -原神抽签 : 抽一签 -解签 : 解答抽签结果 -开启\关闭原神黄历提醒 : 开启或关闭本群的每日黄历提醒 - -原神每日材料提醒 -今日武器突破材料 : 查看今日武器突破材料 -今日角色天赋材料 : 查看今日角色天赋材料 -今日材料 : 查看今天的武器突破材料和角色天赋材料 -开启\关闭原神每日素材提醒 : 开启或关闭本群的每日素材提醒 -''' - - -@sv.on_fullmatch("原神帮助") -async def help(bot, ev): - await bot.send(ev, help_txt) diff --git a/almanac/assets/almanac_list.json b/almanac/assets/almanac_list.json deleted file mode 100644 index ebd1e35..0000000 --- a/almanac/assets/almanac_list.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "抽卡":{ - "buff": ["欧气满满,十连出金","出金不歪"], - "debuff": ["武器大师","保底出金","金色会是痛苦大剑"] - }, - "刷世界boss":{ - "buff": ["双攻双爆角斗士"], - "debuff": ["只有保底材料","贪生怕死角斗士"] - }, - "刷风本":{ - "buff": ["会有极品猎人套","会掉真正的少女心","治疗加成少女头"], - "debuff": ["勇往直前少女心","少女飘摇的杀意","少女暴怒的容颜"] - }, - "刷火本":{ - "buff": ["魔女帽子火伤杯","暴伤魔女帽!","火伤魔女心!"], - "debuff": ["幡 然 醒 悟","这么阴间的地方真的会有魔女套吗?","不务正业火魔女","会匹配到3个卢姥爷"] - }, - "刷岩本":{ - "buff": ["悠久的磐岩伴你左右","岩神的庇护常在"], - "debuff": ["防御流星杯,你值得拥有"] - }, - "刷宗室":{ - "buff": ["物理伤害骑士道,元素精通宗室套"], - "debuff": ["贪生怕死骑士道,物理伤害宗室杯"] - }, - "刷冰本":{ - "buff": ["双暴词条概率up"], - "debuff": ["防御力船帽,无人可及"] - }, - "刷雷本":{ - "buff": ["愿雷鸟伴你左右"], - "debuff": ["来表演一个只掉平雷套的绝活","风神忽悠雷凶兆"] - }, - "锄大地":{ - "buff": ["会掉一大堆紫色材料"], - "debuff": ["深渊法师爱你哟","会被冰水法控到死"] - }, - "挖矿":{ - "buff": ["开矿出双材料"], - "debuff": ["去别人世界会被拒"] - }, - "刷天赋本":{ - "buff": ["金色!我看到了金色的书!"], - "debuff": ["2蓝2绿不会变"] - }, - "刷突破材料":{ - "buff": ["金色!我看到了金色的材料!"], - "debuff": ["2蓝2绿不会变"] - }, - "升级圣遗物":{ - "buff": ["稀有词条跳跳跳","会双爆拉满"], - "debuff": ["女 仆 狂 喜","无中生有防御力","生命拉满","完美避开双爆"] - }, - "打风魔龙":{ - "buff": ["看我一箭一个风魔鸡","今天特瓦林可以给想要的突破材料","5金加原胚!"], - "debuff": ["会不小心掉下平台","不小心被地板烫死了"] - }, - "打狼王":{ - "buff": ["今天安德琉斯的心情不错,可以py一下","5金加原胚!"], - "debuff": ["狼尾巴*1"] - }, - "打公子":{ - "buff": ["今天可以和公子py想要的突破材料","5金加原胚!"], - "debuff": ["要角没有!要命一条!"] - } -} - - - - diff --git a/almanac/assets/config.json b/almanac/assets/config.json deleted file mode 100644 index dd81179..0000000 --- a/almanac/assets/config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "10001": { - "pos": "二八", - "time": "2021-06-05" - } -} \ No newline at end of file diff --git a/almanac/assets/lots_list.json b/almanac/assets/lots_list.json deleted file mode 100644 index fcc0dd0..0000000 --- a/almanac/assets/lots_list.json +++ /dev/null @@ -1,1922 +0,0 @@ -{ - "一": { - "answer": "大吉,事业、财运、健康、婚姻均顺遂。见龙在田,利见大人。君子得之终日乾乾,夕愓若。以是自强不息,居上不骄、在下不忧,大吉也。", - "question": "天门一挂榜,预定夺标人,马嘶芳草地,秋高听鹿鸣。", - "rank": "上上签" - }, - "一○": { - "answer": "才气出众,无奈受制,去向宜北,可获佳遇。功名富贵勤苦方得,尽人事,皇天不负。若懒惰或始勤终息,而欲望飞达,无异南辕北辙。", - "question": "嘹呖征鸿独出群,高飞羽翼更纠纷,云程北进好音遂闻,朝云暮雨交加有凭。", - "rank": "上上签" - }, - "一○○": { - "answer": "得而复失之象,镜中花海底月,均虚而非实,此亦似之。然设能兢兢业业,克自保之,必不至失贻诮,妙手空空也,占此者只须善提防之。", - "question": "喜喜喜,终防否,获得骊龙颔下珠,忽然失却,还在水里。", - "rank": "中上签" - }, - "一○一": { - "answer": "太平盛世,家庭和乐。百事如意,大吉大利营谋得志,功名神助,行人已归,失物早还,六甲生男,婚姻成就,疾病即癒,占者必喜无疑。", - "question": "国有贤士,廷无佞臣,干戈不用,常享太平。", - "rank": "中签" - }, - "一○七": { - "answer": "好运瞬即逝,理想忽受阻碍,办事难有成就。", - "question": "红叶无颜色,凋零一夜风,邻鸡醒午梦,心事总成空。", - "rank": "中上签" - }, - "一○三": { - "answer": "得签者为首脑时,应立求属下各安其位,各部门主管廉洁公正。", - "question": "民乐业,官吏清,雍熙之世复见于今,告诸人千秋鸿业,仗此望明君。", - "rank": "中上签" - }, - "一○九": { - "answer": "慎防勿蹈前车之覆辙,宁可改弦更张,另作他图。", - "question": "勿上旧辙,甘驾新车,东西南北,稳步康衢。", - "rank": "下签" - }, - "一○二": { - "answer": "示人以心性修养,积功好义之道理。", - "question": "泰来否已极,诸事莫忧心,但须 养元福,做些好事,行些方便,一点丹灵独得真。", - "rank": "中下签" - }, - "一○五": { - "answer": "远大目标不易实现,如有匡助之力或引荐之人,也就获得成功机会。", - "question": "月中有丹桂,人终攀不着,云梯足下生,此际好落脚。", - "rank": "中上签" - }, - "一○八": { - "answer": "所问之事情况混乱,时运不佳,事多蹉跎,一无所成。", - "question": "事如麻,理多错,日掩云中,空成耽搁。", - "rank": "中上签" - }, - "一○六": { - "answer": "失意者之孤寂与无奈,得此签者,宜调整处世态度,以此为诫。", - "question": "天间一孤雁,嘹唳叹离群,试问知君者,而今有几人。", - "rank": "中上签" - }, - "一○四": { - "answer": "大吉大利。动作如意,谋为称心,吉人自有天佑,福禄永保安宁,故有泰山磐石之喻,中通外直言人品第一也,占之吉。", - "question": "安如泰山,稳如磐石,放胆前行,中通外直。", - "rank": "上上签" - }, - "一一": { - "answer": "诸事不利。此签有伤亡之患,哭泣之哀,凡事不利有名无实,非常之灾,占之宜戒谨恐惧,时时修省。", - "question": "无踪又无迹,远近均难觅,平地起风波,似笑还成泣。", - "rank": "下下签" - }, - "一一○": { - "answer": "不祥之兆,近时或有惊险之事,小心。可能应验于鼠年,鼠日或属鼠之人。", - "question": "夜梦被鼠惊,醒来不见人,终宵废寝,直到天明。", - "rank": "下签" - }, - "一一一": { - "answer": "凡事靠自己,依赖别人不可靠。", - "question": "秋霜肃,夏日炎,新花鲜了旧花淹,世情看冷暖,逢者不须言。", - "rank": "上签" - }, - "一一七": { - "answer": "努力必有代价,但须耐心等待。", - "question": "珠玉走盘中,田园定阜丰,休言谋未遂,此去便亨通。", - "rank": "中签" - }, - "一一三": { - "answer": "如问疾病,暂难痊愈,尚需时日,以得名医。", - "question": "屙染沈沈,终日昏昏,雷门一震,体健身轻。", - "rank": "中下签" - }, - "一一九": { - "answer": "命中有贵人相助,安份守己以待机运。", - "question": "朦胧秋月映朱门,林外鸟声远寺僧,自有贵人来接引,何须巧语似流莺。", - "rank": "中下签" - }, - "一一二": { - "answer": "不避劳苦,慎选致力方向。", - "question": "未展英雄志,驰驱不惮劳,敢将休咎卜,西北夺前标。", - "rank": "上签" - }, - "一一五": { - "answer": "不祥。绝门绝路诸事不利,含沙射影更防暗算,占得此者,速深居韬晦,矢志行善,庶几灾祸可解。", - "question": "路不通,门闭塞,谨慎提防,云藏月黑。", - "rank": "下下签" - }, - "一一八": { - "answer": "得此签者,所问诸事均处于最佳状态,事事称心如意。", - "question": "月已明,花再发,事悠悠,无不合。", - "rank": "中上签" - }, - "一一六": { - "answer": "贪图小利,成不了大事,即使想通而暂不斤斤计较,恐也有始无终,旧态复萌。", - "question": "蜗角蝇头利,而今已变通,草头人笑汝,宜始不宜终。", - "rank": "中签" - }, - "一一四": { - "answer": "所问之事,呈胶着状,惟会突起变化,所有问题迎刃而解。", - "question": "易非易,难非难,忽地起波澜,欢笑两三番。", - "rank": "下签" - }, - "一七": { - "answer": "处于蓄势欲发又迟疑难决者,宜下定决心,完成大业。宜谨慎,凡事色举翔集,审度而後进退。倘操切从事,必掷珠玉於泥沙,自暴自弃。", - "question": "欲行还止,徘徊不已,藏玉怀珠,寸心千里。", - "rank": "上签" - }, - "一七○": { - "answer": "得此签者,恐有失意事,惟转机已现。", - "question": "莫叹残花,花开枯树,屋头春意,喜笑嘻嘻。", - "rank": "中签" - }, - "一七一": { - "answer": "凡进行之事,均属得失互参,与人交往洽事,若得遇亲信可靠之人,方可心安。", - "question": "一事总成空,一事还成喜,若遇口边人,心下堪凭委。", - "rank": "下签" - }, - "一七七": { - "answer": "虽有才华却遭埋没,须待有心人来提拔重用。", - "question": "白玉蒙尘,黄金埋土,久久光辉,也须人举。", - "rank": "中上签" - }, - "一七三": { - "answer": "大吉,所问诸事均能如愿,且喜事连连。", - "question": "事遂勿忧煎,春风喜自然,更垂三尺钩,得意获鳞鲜。", - "rank": "中上签" - }, - "一七九": { - "answer": "心中所愿终可实现,何必愁眉深锁?", - "question": "背后笑嘻嘻,中行道最宜,所求终有望,不必皱双眉。", - "rank": "中下签" - }, - "一七二": { - "answer": "要得到不易到手之物,非借不凡之力。", - "question": "欲得月中兔,须凭桃李拂,高山来接引,双喜照双眉。", - "rank": "中签" - }, - "一七五": { - "answer": "屋漏又遭连夜雨,船破偏遇当头风,衰透至极。", - "question": "乘病马,上危坡,防失跌,见蹉跎。", - "rank": "下下签" - }, - "一七八": { - "answer": "无论在团体、在家庭或社会,上下皆不相容,经年纠葛不清。", - "question": "上接不稳,下接不和,相缠相扰,平地风波。", - "rank": "中签" - }, - "一七六": { - "answer": "得意勿忘形,忘形恐有灾。", - "question": "两事已和同,轻舟遇便风,道迷人得意,歌唱急流中。", - "rank": "下签" - }, - "一七四": { - "answer": "要求功德圆满,但凭个人造化,机缘如何,所问诸事均如此。", - "question": "圆又缺,缺又圆,低低密密要周旋,时来始见缘。", - "rank": "下下签" - }, - "一三": { - "answer": "吉,留意三、五有关月日,或有殊遇、喜事。此签谋为有成,凡事有缘,求妻者得佳妇。求事者得佳事,谈笑中立可成,所谓吉人天相也。", - "question": "得意宜逢妇,前程去有缘,利名终有望,三五月团圆。", - "rank": "中签" - }, - "一三○": { - "answer": "此签大吉,所问诸事都很圆满,得此签者财运奇佳,本利相滚,财货盈仓。", - "question": "事团圆,物周旋,一来一往,平步青天。", - "rank": "中上签" - }, - "一三一": { - "answer": "衰运当头,即便慎言亦惹是非,故应少言,甚至不言。", - "question": "浅水起风波,平地生荆棘,言语虑参商,犹恐无端的。", - "rank": "中下签" - }, - "一三七": { - "answer": "或有烦心之事来临,内心忧闷无人谅解。", - "question": "荆棘生平地,风波起四方,倚栏惆怅望,无语对斜阳。", - "rank": "下签" - }, - "一三三": { - "answer": "吉祥,所问诸事,心意已决,即可达成,同时功成名就。", - "question": "心已定,事何忧,金鳞已上钩,功名一网收。", - "rank": "中上签" - }, - "一三九": { - "answer": "所问诸事,成败在于天时与地利。", - "question": "奇奇奇,地利与天时,灯花传信后,动静总相宜。", - "rank": "上上签" - }, - "一三二": { - "answer": "如处平顺之境遇,如有他乡旧知求己引荐则可为之,否则如所求过奢者,宜多虑。", - "question": "秋月云开后,薰风雨过时,若逢楚国旧知己,等闲一荐不须疑。", - "rank": "上签" - }, - "一三五": { - "answer": "凡事仅看表面自有不足,阻碍或能排除,祸事亦能成福庇。", - "question": "笑中生不足,内外见愁哭,云散月光辉,转祸当成福。", - "rank": "上签" - }, - "一三八": { - "answer": "大局安排已定,不必多作考虑。", - "question": "谋已定,事何忧,照月上重楼,云中客点头。", - "rank": "中下签" - }, - "一三六": { - "answer": "事情已安排妥当,全无冲突,若问姻缘,即可结合。", - "question": "檐前鹊噪正翩翩,忧虑全消喜自然,一人进了一人退,下梢还有好姻缘。", - "rank": "上签" - }, - "一三四": { - "answer": "凡事未可乐观。清明之中,虽无不了悟处,营求之後大有堪虑处,欲知下回分解,目前犹非其时,占者只可强自抑制,到时方能了了。", - "question": "意迷己不迷,事宽心不宽,要知端的信,犹隔两重山。", - "rank": "中上签" - }, - "一九": { - "answer": "平平,成败利钝淡然处之。此签主一切疑难,不问远近难易,均须自作主张,但求渗透玄机,不难迎刃而解,云中带笑看,得意时也。", - "question": "不远不近,似易似难,等闲一事,云中笑看。", - "rank": "上上签" - }, - "一九○": { - "answer": "单办一项行业、活动或进行一件事,多力不从心,若有多人相助,则望可成。", - "question": "事迷心不迷,事宽心不宽,一场欢喜会,不久出重关。", - "rank": "中下签" - }, - "一九一": { - "answer": "得此签者,诸事不宜冒进,宜于天时、地利、人和俱备之后再行动。", - "question": "夜半渡无船,惊涛恐拍天,月斜云淡处,音信有人传。", - "rank": "中上签" - }, - "一九七": { - "answer": "所问诸事,处于进退两难之境,须相关诸人上下一心,始有成功之望。", - "question": "进不安,退不可,上下相从,明珠一颗。", - "rank": "中签" - }, - "一九三": { - "answer": "所问诸事一向稳妥顺利,日后扩展,更属定 胜券。", - "question": "万里片帆转,波平浪不惊,行行无阻滞,远处更通津。", - "rank": "上签" - }, - "一九九": { - "answer": "众说纷纭,莫衷一是,事情进行一半,成为日后愁苦之源。", - "question": "雀噪高枝上,行人古渡头,半途不了事,日暮转生愁。", - "rank": "中下签" - }, - "一九二": { - "answer": "从事任何事,以谨慎机敏为上。", - "question": "事若羁留,人不出头,往来闭塞,要见无有。", - "rank": "上签" - }, - "一九五": { - "answer": "吉祥,无所不利。云中鹤月下人均有翛然世外之象,含饴鼓腹盛世之民也,果何所忧虑而不欢乐乎,占之者吉。", - "question": "鹤自云中出,人从月下归,新欢盈脸上,不用皱双眉。", - "rank": "中下签" - }, - "一九八": { - "answer": "一向事事称心,如今却不再如意,但是非可免。", - "question": "着着占先机,其中路不迷,目前无合意,乍免是和非。", - "rank": "下签" - }, - "一九六": { - "answer": "具有耐心,任何事均可成,不必怀疑。", - "question": "深潭鱼可钓,幽谷鸟可罗,只用久长心,不用生疑惑。", - "rank": "中签" - }, - "一九四": { - "answer": "此签对告老退休者,颇合其解,如问他事,则属有惊无险之局,刻下尚难抽身。", - "question": "身历惊涛,东风便好,太平身退,目下还早。", - "rank": "中下签" - }, - "一二": { - "answer": "诸事暂且打住,免有失误,后悔莫及。此签不宜妄想,只可谨守避祸,以免惹事招非,否则动则得咎,悔之晚矣。", - "question": "神黯黯,意悠悠,收却线,莫下钩。", - "rank": "中下签" - }, - "一二○": { - "answer": "所问诸事处在急于解决却未能解决之状况,不过最后终能渡过难关。", - "question": "事未宽,心不安,疑虑久,始安然。", - "rank": "中上签" - }, - "一二一": { - "answer": "终年碌碌营钻,每得虚有其表之名位,但等秋后(或中年以后)将时来运转。", - "question": "虚名虚位久沈沈,禄马当求未见真,一片彩云秋后至,去年风物一时新。", - "rank": "中签" - }, - "一二七": { - "answer": "遇事小心仔细,否则有招致横祸之可能。", - "question": "虎伏在路途,行人莫乱呼,路旁须仔细,灾祸自然无。", - "rank": "中下签" - }, - "一二三": { - "answer": "大吉大利,所问诸事均得圆满达成,更能得锦上添花之美。", - "question": "明月全圆,颜色欣然,风云相送,和合万年。", - "rank": "下签" - }, - "一二九": { - "answer": "得此签者,所谋之事于闲散自在中,不期然而有所成。", - "question": "东边事,西边成,风物月华明,高楼弄笛声。", - "rank": "中下签" - }, - "一二二": { - "answer": "成败得失,莫不缘于因果回圈之定数,不必强求。", - "question": "止止止,有终有始,似月如花,守成而已。", - "rank": "上签" - }, - "一二五": { - "answer": "居上者倨傲、偏狭,居下者离心,最后关键时刻,招致失败。", - "question": "居下不亲上,人心易散离,事机终失一,凡百尽成灰。", - "rank": "中下签" - }, - "一二八": { - "answer": "不吉,如问事业,纠纷不断,如问亲情友情婚姻,则神离而貌亦不合,进退小心。", - "question": "和不和,同不同,翻云覆雨几成空,进退须防终少功。", - "rank": "中下签" - }, - "一二六": { - "answer": "得此签者,时运欠畅,有志未伸,须明提携之人,前途始有望。", - "question": "兀兀尘埃久待时,幽窗寂静有谁知,若逢青紫人相引,财利功名自可期。", - "rank": "中上签" - }, - "一二四": { - "answer": "得此签者,即将成婚,或已成婚,双方情投意合生活美满,如问合伙,亦可大发。", - "question": "宝镜新,照两人,心中结,合同心。", - "rank": "上上签" - }, - "一五": { - "answer": "一切期待,均有可得,但须再等待一段时间。此签沉滞已久,困而将亨之象。然亦必须梅花初放,始得好消息,占之者宜稍安勿躁。", - "question": "意在闲中信未来,故人千里自徘徊,天边雁足传消息,一点梅花春色回。", - "rank": "中下签" - }, - "一五○": { - "answer": "时机已逝,时光已老,欲图大事,已不可能。", - "question": "大事恐难图;残花不再鲜。", - "rank": "下下签" - }, - "一五一": { - "answer": "好事多磨。主谗人高张,贤士无名荣辱升沉,莫谓天道不公,须知人事靡定也,月既缺矣又灭怀光,占之者可以知所儆也。", - "question": "莫道事无讹,其中进退多,桂轮圆又缺,光彩更揩磨。", - "rank": "中下签" - }, - "一五七": { - "answer": "得此签者注定显达,但需注意积德,否则将很快失去一切。", - "question": "贵客自相亲,功名唾手成,获金须积德,仰望太阳升。", - "rank": "下签" - }, - "一五三": { - "answer": "不必操之过急,须仰人相助,或有所成。", - "question": "事称应有忌,未为恐先踬,欲往且迟迟,还须借势力。", - "rank": "中上签" - }, - "一五九": { - "answer": "所问之事或人,如天心之月,皎洁无垢,非黑云所能遮掩。", - "question": "狂风吹起墨云飞,月在天心遮不得,闲时无事暂相关,到底依然无克剥。", - "rank": "下签" - }, - "一五二": { - "answer": "有耐心、恒心,最后终能如愿。", - "question": "莫叹事迟留,休言不到头,长竿终入手,一钓上金钩。", - "rank": "中上签" - }, - "一五五": { - "answer": "所问诸事于开始非常不顺,命中有贵人相助,事情得以重整。", - "question": "鼎折足,车脱辐,有贵人,重整续。", - "rank": "中下签" - }, - "一五八": { - "answer": "目前机运欠佳,须与知心友朋共事,庶几无患。", - "question": "平地起波澜,所求事日难,笑谈终有忌,同心事觉欢。", - "rank": "中下签" - }, - "一五六": { - "answer": "得此签者,恐有诉讼,或与人订约始终无法谈拢,亦或与人长时间有口舌之辩。", - "question": "参详言语,波涛扬沸,事久无伤,时间不利。", - "rank": "下签" - }, - "一五四": { - "answer": "塞翁失马,焉知非福,有时这样也不对,那样也不对,合在一起却带来好运。", - "question": "足不安,舆不安,两两事相得,忧来却又欢。", - "rank": "中上签" - }, - "一八": { - "answer": "不利,结局恐难有望。此签主患得患失,如驽马恋栈豆,无果决之作为,故枉费心机,徒取烦恼也。", - "question": "心戚戚,口啾啾,一番思虑一番忧,说了休时又不休。", - "rank": "中签" - }, - "一八○": { - "answer": "此签指一对恋人,因云山相阻,相思成疾,或谓,一人命运孤苦,事多伤感。", - "question": "憔悴无人问,林间听杜鹃,一声山月笛,千里泪涓涓。", - "rank": "中签" - }, - "一八一": { - "answer": "此签如专就宦途而言,诚属上上大吉,可谓官运亨通,青云直上。", - "question": "菱荷香里受深恩,桂魄圆时印绶新,从此威名山岳重,光辉直上位丝纶。", - "rank": "中签" - }, - "一八七": { - "answer": "莫为意中人或原留之地恋恋不舍,而误未来大事,不如早去为妙,免生祸乱。", - "question": "休眷恋,误前程,终闹乱,出门庭。", - "rank": "中签" - }, - "一八三": { - "answer": "此签示人,若三心二意去做一件事,出于勉强,则一动不如一静。", - "question": "欲行还止,徘徊不已,动摇莫强,得止且止。", - "rank": "中下签" - }, - "一八九": { - "answer": "得此签者,恐有幻想之习,应即改之。", - "question": "渴望梅, 画饼,漫劳心,如捉影,遇虎龙,方可省。", - "rank": "上上签" - }, - "一八二": { - "answer": "任何事均不得其时,尤其最近一月内,须防有所阻碍,诸事稍慢,等待转机。", - "question": "花落正逢春,行人在半程,事成还不就,索绊两三旬。", - "rank": "上签" - }, - "一八五": { - "answer": "总想换个新环境或工作,然却却不知如何着手,日后或有机运,目下尚不乐观。", - "question": "梦里说关山,波深下钓难,利名终有望,目下未开颜。", - "rank": "下签" - }, - "一八八": { - "answer": "大吉。", - "question": "万里波涛静,一天风月闲,利名无阻隔,行路出重关。", - "rank": "中上签" - }, - "一八六": { - "answer": "此签属机运亨通之签,尤对谋事、创业者而言。", - "question": "三箭开云路,营求指日成,许多闲口语,翻作笑歌声。", - "rank": "中上签" - }, - "一八四": { - "answer": "所问诸事,虽未圆满解决,但必能安然无虞,若遇龙(龙年或属龙之人)自有吉兆。", - "question": "心下事安然,周旋尚未全,逢龙还有吉,人月永团圆。", - "rank": "中下签" - }, - "一六": { - "answer": "得此签者,不合者必复合。同舟共济,出门有功,占者不可损人利己,不可惟我独尊,否则虎头蛇尾无断金之利。", - "question": "心和同,事知同,门外好施功,交加事有终。", - "rank": "中上签" - }, - "一六○": { - "answer": "独处深思,总觉不悦,若能眼光放远,自然无忧。", - "question": "人倚楼,许多愁,澹然进步,事始无忧。", - "rank": "下签" - }, - "一六一": { - "answer": "心志专一始能受到重视,略得提携即可步入佳境。", - "question": "一点着阳春,枯枝朵朵新,志专方遇合,切忌二三心。", - "rank": "中下签" - }, - "一六七": { - "answer": "异人指点,凡事顺利,事成日在三秋后。三秋:三年,秋季三个月,或秋季三个月。", - "question": "大事可成功,有益还无咎,云中执鞭人,报在三秋后。", - "rank": "上上签" - }, - "一六三": { - "answer": "将得手之机会或财物,由于条件不济,力量不足,无法承受,须再加努力。", - "question": "鱼上钩,丝纶弱,收拾难,力再着。", - "rank": "中上签" - }, - "一六九": { - "answer": "所问之事颇难如愿,须待天时。", - "question": "遍书前后事,艰险往来难,若得清风便,扁舟过远山。", - "rank": "上签" - }, - "一六二": { - "answer": "主困而後亨,剥而始复,初为云雾所障忧患频仍,终乃天日重开,门路广大,人但自求多福,不患人之不己知,占者毋自懈亦无自馁。", - "question": "道路迢遥,门庭闭塞,雾拥去兮,云开见日。", - "rank": "中下签" - }, - "一六五": { - "answer": "凡猜疑之事,不可冒然尝试,须再三思考探求真相,方作决定,免乐极生悲。", - "question": "疑疑疑,一番笑罢一番悲,落红满地无人扫,独对西风怅黛眉。", - "rank": "中签" - }, - "一六八": { - "answer": "事情已到穷途末路,想有转机亦难,惟亦不必过于颓丧,能保性命即属庆幸。", - "question": "桑榆催暮景,缺月恐难圆,若遇刀锥客,方知喜自然。", - "rank": "中上签" - }, - "一六六": { - "answer": "与其在一个意见分歧不合之团体里,不如及早退出,另创局面。", - "question": "上下不和同,劳而未有功,出门通大道,从此保初终。", - "rank": "中签" - }, - "一六四": { - "answer": "得此签者,平时乐于助人,故人际关系良好,事事均如意。", - "question": "相引更相牵,殷勤喜自然,施为无不利,愁事转团圆。", - "rank": "上签" - }, - "一四": { - "answer": "趋吉避凶人之常情,若一旦遇变故,而巧於趋避非惟自问不安,即天人亦不容之。人事蹉跎故戒之者深矣,占者当不避艰险勉持危局。", - "question": "鼎沸起风波,孤舟要渡河,巧中却藏拙,人事转蹉跎。", - "rank": "下下签" - }, - "一四○": { - "answer": "所问诸事均在虚无飘渺中。", - "question": "遇不遇,逢不逢,月沈海底,人在梦中。", - "rank": "上签" - }, - "一四一": { - "answer": "所耽忧之事均属子虚乌有,很快就能真相大白。", - "question": "暗中防霹雳,猜虑浑无实,转眼黑云收,拥出扶桑日。", - "rank": "下下签" - }, - "一四七": { - "answer": "不可浪费,遇良机时始能大展鸿图。", - "question": "可蓄可储,片玉寸珠,停停稳稳,前遇良图。", - "rank": "中下签" - }, - "一四三": { - "answer": "不吉之兆,得此签者处于公私纷繁,困扰重重之境。", - "question": "堪叹外边忧,更嗟门里闹,意绪更牵缠,心神亦颠倒。", - "rank": "下下签" - }, - "一四九": { - "answer": "得此签者有心意不专,操之过急之毛病,未改之前难有成就。", - "question": "一心两事,一事两心,新花枯树,直待交春。", - "rank": "下下签" - }, - "一四二": { - "answer": "此签今人问卜,不易作作妥贴解述,大意为立功异邦,归享盛名。", - "question": "利在中邦出战时,一番获馈在王庭,凤衔丹诏归阳畔,得享佳名四海荣。", - "rank": "上签" - }, - "一四五": { - "answer": "吉祥,化险为夷,若遇贵人,将可发迹。(贵人或可注意姓名有草字头者)。", - "question": "遇险不须忧,风波何足忌,若遇草头人,咫尺青云路。", - "rank": "中签" - }, - "一四八": { - "answer": "早给子女适切教导,可望使其得到贵人相助,并实现愿望。", - "question": "小子早趋庭,青云久问程,贵人来助力,花谢子还成。", - "rank": "中上签" - }, - "一四六": { - "answer": "心情纷乱,办事虑深,时运犹待新春,旅外慎防不测,婚姻出现暗礁。", - "question": "船棹中流急,花开春又离,事宁心不静,惹起许多疑。", - "rank": "中下签" - }, - "一四四": { - "answer": "如问机构内之事,则虽风波重重,终能安然,问家务事,因妇女高妙,亦安。", - "question": "一重山一重水,风波道坦然,壶中有别天。", - "rank": "下签" - }, - "七": { - "answer": "应机警应变,始能左右逢源。人情险巇,世态炎凉,然能拿定方针随机应变,亦识时务之俊杰也,占得此签当无咎。", - "question": "君须悟,勿误疑,有平路,任驱驰,随时变易,件件碱宜。", - "rank": "中下签" - }, - "七○": { - "answer": "为人追求真善美方为正途,凡事必以始终一贯精神为之。", - "question": "美有堪,堪有美,始有终,终有始。", - "rank": "中下签" - }, - "七一": { - "answer": "所问诸事尚在虚无飘渺间,当前处境未开,心绪至为郁闷,情境苍茫。", - "question": "湖海悠悠,孤舟浪头,来人未渡,残照山楼。", - "rank": "中下签" - }, - "七七": { - "answer": "所问之事,自己心余力绌,无法独力完成,但会有外力来助,结果仍称圆满。", - "question": "心有余,力不足,倚仗春风,一歌一曲。", - "rank": "下下签" - }, - "七三": { - "answer": "此签大吉,凡谋事、创业必有望,且连获成功,尤其逢‘六’数,更具喜色也。", - "question": "江海悠悠,烟波下钩,六鳌连获,歌笑中流。", - "rank": "中上签" - }, - "七九": { - "answer": "人、事问题,均了断并圆满解决,有关物则否,得此签,恐有财务纠纷并涉讼。", - "question": "事了物未了,人圆物未圆,要知端的信,日影上琅。", - "rank": "中下签" - }, - "七二": { - "answer": "无事须当有事,有事更加防范,得此签者须注意门户以防窃,谨言慎行免招祸。", - "question": "深户要牢扃,提防暗里人,莫言无外事,纵好定遭。", - "rank": "中上签" - }, - "七五": { - "answer": "得意之时勿忘形,失败之后勿失志,不行歪路,心境自然安适。", - "question": "一得一虑,退后欲先,路通大道,心自安然。", - "rank": "中下签" - }, - "七八": { - "answer": "问健康,应多运动,问事业,则现危机,需多所奔走,问婚姻,处倦怠状,需努力。", - "question": "身不安,心不安,动静两三番,终朝事必叹。", - "rank": "中下签" - }, - "七六": { - "answer": "机遇欠佳时,人在家中坐,祸从天上来,行运转佳时,一切左右逢源,得心应手。", - "question": "难难难,忽然平地起波澜,易易易,谈笑寻常终有望。", - "rank": "下下签" - }, - "七四": { - "answer": "三心二意,有违常理,动弹不得,得此签者,所问诸事均呈胶着状态。", - "question": "欲济未济,欲求强求,心无一定,一车两头。", - "rank": "中上签" - }, - "三": { - "answer": "惕励不可好高骛远,目前情况不理想。切记吃得苦中苦,方为人上人。得此签者务须猛着粗鞭,力求上进。倘自为有恃无恐,则不进反退也。", - "question": "长安花,不可及,春风中,马蹄疾,急早加鞭,骤然生色。", - "rank": "中上签" - }, - "三○": { - "answer": "攀权附贵者宜回头,顶天立地重新做人,否则不得善终。力戒躁动勉守安静,毋贪非分毋逞妄想,君子占之以是福,小人占之以是祸。", - "question": "缘黄阁白了头,毕竟成何济,不如趁此精神,犹好买些真气。", - "rank": "中下签" - }, - "三○○": { - "answer": "大吉大利,凡事左右逢源,得心应手。", - "question": "三天曾结社,四海尽知名,长骑骏马,直入天庭。", - "rank": "中下签" - }, - "三○一": { - "answer": "命中有吉人相助。邂逅相逢,一见如故,倾心吐胆,古道照人,占者能於无意中获交良友。", - "question": "闲来夫子处,偶然遇一人,童颜鹤发,笑里生春。", - "rank": "中上签" - }, - "三○七": { - "answer": "感应签,求职谋事创业等,遇龙年生者可得其助,迁居进宅等,逢678之日期较顺。", - "question": "龙生头角,将沛甘霖,六七八早,好济苍生。", - "rank": "中签" - }, - "三○三": { - "answer": "浊者自浊,清者自清,吾人须洁身自好,以处混乱之险恶世道。", - "question": "汉水无情,蜀水澄清,黄河滚滚,四处烟尘。", - "rank": "中签" - }, - "三○九": { - "answer": "寓意有二:一分耕耘,一分收获,已为某事劳心尽力,但须待时机及人助方有成。", - "question": "曾把树栽,也要待春来,东风袅袅,开遍花街。", - "rank": "中签" - }, - "三○二": { - "answer": "悠闲自在态度追求理想者,际遇最佳,经过二三年之经营,即可有成。", - "question": "闲云野鹤望东行,惟有乡人便是知音,经营布置两三春,联街灯火后,锦帆前程。", - "rank": "中上签" - }, - "三○五": { - "answer": "好花不常开,一旦处于绝佳之境,宜淡然处之,并另谋良图。", - "question": "此处滋味浓,浓艳不耐久,何如谈笑生风,倒好东奔西走。", - "rank": "中下签" - }, - "三○八": { - "answer": "正不胜邪,理不胜数,一生三死,天道昭然,占之者正不必强自纷争也。", - "question": "太白现西南,龙蛇相竞逐,龙自飞上天,蛇却被刑戮。", - "rank": "中签" - }, - "三○六": { - "answer": "所问诸事可能受到小人干扰破坏,与其争论无益,避之则吉。", - "question": "这里有小人,切莫稍留停,忙打点,好起行,日月如逝勿久存。", - "rank": "中上签" - }, - "三○四": { - "answer": "求签者暂遇挫折,目前尚在守时待运阶段,待时机成熟。", - "question": "潜龙已受困,尚不见云兴,伫看云四合,飞去到天庭。", - "rank": "中上签" - }, - "三一": { - "answer": "平平,创业须结伴。此签谋为始难,不免阻滞,久後还得顺利,只须当机立断,切莫因循自误,致老大徒伤悲也。", - "question": "离别间,虽不易,同伴行,犹不滞,早早起程,免他失意。", - "rank": "中下签" - }, - "三一○": { - "answer": "此签劝人要能知足,并把握光阴享受人生。", - "question": "四十余年苦已深,而今汝乐度光阴,莫筹论,恩爱尚多欢喜事,惜甚青春,不减青春。", - "rank": "中签" - }, - "三一一": { - "answer": "所问诸事做法上恐有问题,应即改弦更张另作安排。", - "question": "三冬足,文艺精,到头处,亦成冰,急急回首,勿误前程。", - "rank": "中下签" - }, - "三一七": { - "answer": "不经意引发之灾难总有克制之法,刻意策划之事端,往往一发不可收拾。", - "question": "大火炎炎,宜水相济,宝鼎丹成,掀天揭地。", - "rank": "中下签" - }, - "三一三": { - "answer": "得此签者有以逸待劳,坐享其成之机运。", - "question": "耕牛伏 ,辟土开疆,坐看收获,黍稷稻梁。", - "rank": "中签" - }, - "三一九": { - "answer": "做任何事,均要抱着积极态度不懈不怠全力以赴,若稍有停顿,将难以收拾。", - "question": "十二时中,紧急炼着,一刻少延,无处下脚。", - "rank": "中上签" - }, - "三一二": { - "answer": "所问之事情况怪异,应提防生变,以免坏了大事。", - "question": "奇怪奇怪,前番来了,今番又来,谨慎提防,勿被弄坏。", - "rank": "中签" - }, - "三一五": { - "answer": "此签以雏鸟喻人学艺未精不知天高地厚,初入社会难免饱受波涛翻滚之苦。", - "question": "雏鸟飞高,出谷迁乔,龙神牙爪,变化海岛。", - "rank": "下签" - }, - "三一八": { - "answer": "所问之事宜以快刀斩乱麻方式处理,以杜后患。", - "question": "铁索一条,未把孤舟系,金刀一下,早把头落地。", - "rank": "中下签" - }, - "三一六": { - "answer": "得此签者恐有不吉事情临头,并因而尝到人情淡薄之滋味。", - "question": "吉吉吉,寻常一样窗前月,凶凶凶,有了梅花便不同,含笑向东风,人情不比旧时浓。", - "rank": "中上签" - }, - "三一四": { - "answer": "得此签者功勋卓着,必为行业中顶尖人物,所问诸事无不卓然有成。", - "question": "腰下佩青萍,步入金銮殿,覆护三山,千锤百链。", - "rank": "中上签" - }, - "三七": { - "answer": "须以德化人。此签主君子贤人,名望所归,即使众口铄金,终不能埋没其真材实学,归元朝洞,正以喻泰斗之足以令人景仰也。", - "question": "万马归元,千猿朝洞,虎伏龙降,道高德重。", - "rank": "中下签" - }, - "三七○": { - "answer": "历尽辛苦,而步入舒适称意之环境,须饮水思源不可忘本。", - "question": "过羊肠,入康庄,五陵裘马,当思故乡。", - "rank": "中下签" - }, - "三七一": { - "answer": "处理紧急情况,不能急切,须防后患。", - "question": "火遭水克,火灭其光,水势滔滔,源远流长。", - "rank": "中上签" - }, - "三七七": { - "answer": "天生万物必有用,寓意人万勿连猪狗都不如。", - "question": "一头猪,可祭天地,虽丧身,亦算好处。", - "rank": "中签" - }, - "三七三": { - "answer": "天下本无事,庸人自扰之,或谓‘苦恼皆因强出头’。", - "question": "世界似清宁,不知辞已休,打叠要小心,须防遭火 。", - "rank": "中上签" - }, - "三七九": { - "answer": "万事俱备,只欠东风,如今东风来了,自是令人开怀之事。", - "question": "东风来,花自开,大家喝采,畅饮三杯。", - "rank": "中上签" - }, - "三七二": { - "answer": "得签人已颇有名望,且乐于交际应酬,往来多为高雅之士。", - "question": "东阁筵开,佳客自来,高歌唱和,展挹舒怀。", - "rank": "上签" - }, - "三七五": { - "answer": "顺其自然,把握有利机运去求发展,才会有指望。", - "question": "山上有古松,亭亭冲汉斗,干老枝更长,天地生荣久。", - "rank": "中签" - }, - "三七八": { - "answer": "此签劳心不如劳力,劳心多愁思,劳力多好梦,占之者须熟读流水不腐、户枢不蠹二语。", - "question": "与其日营营,何如夜忖忖,日里多劳形,夜间却安稳。", - "rank": "中上签" - }, - "三七六": { - "answer": "对于挑拨离间之闲言杂语,不去理会,一切自有天数,冥冥之中报应不爽。", - "question": "诽谤言,勿计论,到头来,数已定,碌碌浮生,不如安分。", - "rank": "中上签" - }, - "三七四": { - "answer": "要达崇高目标,须有超人本事,并能借机乘势。", - "question": "跳龙门,须激浪,雷电轰轰,踊跃万丈。", - "rank": "中上签" - }, - "三三": { - "answer": "平平。苦未尽甘已来,风平浪静,直上青云。占此签者诸事利吉,不用忧虑。", - "question": "历过波涛三五重,谁知浪静又无风,须教明达青云路,用舍行藏不费功。", - "rank": "中签" - }, - "三三○": { - "answer": "名利与己与缘,不必在凶险世途上与人争夺,安份守己勤苦渡日最宜。", - "question": "世道多荆棘,人情每用嗟,利名如有路,勤苦逐生涯。", - "rank": "中上签" - }, - "三三一": { - "answer": "跋山涉水出门远行,均属不利,若违拗命运一意孤行,往往会遇怨怼非议事。", - "question": "山穷路转迷,水急舟难渡,万事莫强为,出处遭研妒。", - "rank": "中上签" - }, - "三三七": { - "answer": "谋事在人,成事在天。对一切事物,莫过于贪婪奢求。", - "question": "万事不由人计较,一生尽是命安排,莫疑猜,命里有时总有分,何须碌碌混尘埃,休哉!", - "rank": "中上签" - }, - "三三三": { - "answer": "得此签者如为女性,必美且慧,远近赞美,如为男性则以品德高贵而受颂扬。", - "question": "一朵花枝艳更芳,清香馥郁透兰房,时风吹送终成笑,好句筵前进几觞。", - "rank": "中下签" - }, - "三三九": { - "answer": "对女色之困惑,须加以警惕,不可贪恋也,否则将有耗虚之虞。", - "question": "两女一夫,上下相祛,阴气乘阳,用是耗虚。", - "rank": "中下签" - }, - "三三二": { - "answer": "时运不佳,未来日子风险更多,得此签者,须多加谨慎提防为宜。", - "question": "时边多艰,战战兢兢,戒谨恐惧,如履薄冰,须识前程危与险,一笼风里一枝灯。", - "rank": "中下签" - }, - "三三五": { - "answer": "此签甚佳,凡事亨通,如寻物得、谋事成、求偶佳、经商利、建屋吉。", - "question": "远涉波涛一叶舟,而今始得过滩头,年来心事才成就,屈指从前多可忧。", - "rank": "中上签" - }, - "三三八": { - "answer": "所问诸事均不顺遂,因而被重重烦忧困住,妇女得此签者宜防情感生活有变。", - "question": "一片忧心未肯休,花逢春雨艳难留,得意归休,失意归休,仙家只此一筹谋。", - "rank": "中下签" - }, - "三三六": { - "answer": "得签者久受重用,生活富裕,如起异心或心生骄怠,则可能失去一切。", - "question": "受君之禄,久降祯祥,盈而不覆,守之乃昌,毋怠毋骄,永保安康。", - "rank": "上上签" - }, - "三三四": { - "answer": "一人做任何事,具有恒心、毅力,则其成功机会较大。", - "question": "自从持守定,功在众人先,别有非常喜,随龙到九天。", - "rank": "上签" - }, - "三九": { - "answer": "此签有大觉大悟,普渡众生之义。引人登彼岸,自身入仙班。言为人谋忠,己必不沉沦在下,行善事者,自获善报,百不失一。", - "question": "大肆放灵丹,救人行万千,到头登彼岸,渡过入仙班。", - "rank": "中上签" - }, - "三二": { - "answer": "不祥。顺利之来无永久,横逆之加难幸免,天在上为吉,水在下为凶,当逆来顺受,届以求伸,目下黑暗,久後亦当能光返照。", - "question": "乐之极忧将至,巽兑分明吉与凶,未能光大终幽暗,日落西山返照中。", - "rank": "中上签" - }, - "三二○": { - "answer": "当时机成熟,谜题即可轻易揭开,所有疑难均会得到答案。", - "question": "风起西南,红日当天,奇门妙诀,一掌能着。", - "rank": "中签" - }, - "三二一": { - "answer": "谨慎维护形象,以突破谣言扭曲,得此签者有招人忌怨、暗算之危。", - "question": "万籁无声际,一月正当空,忽被云遮掩,皓魄反朦胧。", - "rank": "中下签" - }, - "三二七": { - "answer": "得此签者将获佳婿,并因而使生命改观,荣华富贵享用不尽。", - "question": "豹变成文采,乘龙福自臻,赤身成富贵,事事得振新。", - "rank": "中上签" - }, - "三二三": { - "answer": "此签示人勿为小人群聚时之假像欺骗。", - "question": "众犬相聚,砺齿咬牙,摇头摆尾,只顾看家。", - "rank": "中下签" - }, - "三二九": { - "answer": "此签示人:家道富裕,宜安于现状,不必另起为官或经商之念。", - "question": "晓雨初晴映碧溪,重重春色上柴扉,黄金不尽家殷富,何必区区羡锦衣?", - "rank": "上签" - }, - "三二二": { - "answer": "得签者为人处事有‘曲过高和太寡’之情形,宜检讨修正。", - "question": "一个知音,却在天边等,切勿因循,静夜当思省。", - "rank": "中签" - }, - "三二五": { - "answer": "凡事一动不如一静,坚守本份相安无事,或寓有应严守机密勿使泄露意思。", - "question": "鼠伏穴,本自宁,一露首,猫即跟,扬威伸爪,鼠丧残生。", - "rank": "中下签" - }, - "三二八": { - "answer": "此签寓有‘道消魔长’之意,处此情况唯有谨慎或可保全。", - "question": "孤阳微兮,群阴溢兮,力既殚兮,将不可耄兮,真谨慎兮,宜可保兮。", - "rank": "中签" - }, - "三二六": { - "answer": "得此签者应切记斯言,不再忧心忡忡,终年劳碌而不读书。", - "question": "书中有女颜如玉,书中自有黄金屋,读尽五车书,志愿自能足,何必焦劳心中忙碌。", - "rank": "中上签" - }, - "三二四": { - "answer": "有的夫妻,妻强夫弱,得此签者有娶这种妻室之可能,婚后应重视恩义。", - "question": "妻前夫后一同行,好比先机兆已明,君若有情须切记,十年恩义莫忘心。", - "rank": "下签" - }, - "三五": { - "answer": "一向平顺,今突生险,惟必可过关。诸事迟滞,赖有智识定力,涉险济深,始得同登彼岸。", - "question": "行路难行路难,今日方知行路难,前程广大何足虑,琼力今朝度此滩。", - "rank": "上上签" - }, - "三五○": { - "answer": "历尽千辛万苦,如今终入佳境。", - "question": "巴到平安地,江山万里程,绿杨芳草处,风快马蹄轻。", - "rank": "上上签" - }, - "三五一": { - "answer": "时来运转,气势甚雄,做任何事均能顺利无比。", - "question": "雕鹗当秋势转雄,乘风分翼到蟾宫,荣华若问将来事,先后名声达九重。", - "rank": "上上签" - }, - "三五七": { - "answer": "此签临事须有决断,不可狐疑又须认准路径,不可分歧,如或不然,後患难免。", - "question": "思量一夜,不如打干一番,若还错,烦恼及肺肝。", - "rank": "中上签" - }, - "三五三": { - "answer": "举头三尺有神明,与人相处莫欺心,是非到头自分明。", - "question": "两人在旁,太阳在上,照汝一寸心,仙机曾否明。", - "rank": "中下签" - }, - "三五九": { - "answer": "对某件事能专心致志去做,收获必不同凡响。", - "question": "天念苦修人,终不落红尘,清心能见道,扰扰丧真灵。", - "rank": "中上签" - }, - "三五二": { - "answer": "小人得志,嚣张狂妄,但为时不长。", - "question": "鼠为患终宵不得宁,猫儿一叫几夜太平,人岂识如兽,其理甚分明。", - "rank": "中下签" - }, - "三五五": { - "answer": "未明,视所问事而定。行人走失,欲寻觅之,须依所指引处前去,自有下落,问失物亦然,占之者切莫迟徊。", - "question": "去到长安,东北转角,逢着天门,便有下落。", - "rank": "中上签" - }, - "三五八": { - "answer": "此签小挫不足虑,还须再接再厉如前坚守,若因而退缩,不惟前功尽弃,且为敌人所乘矣,占者须明此理。", - "question": "心细胆粗,可胜上将之任,勇往前行成败何必在心,胸中把持得定,敌人自能受困。", - "rank": "中签" - }, - "三五六": { - "answer": "机运不能坐等,要亲自向可能之处探寻,寻必有所得。", - "question": "徐步入天台,为听好消息,采药有仙童,洞府列春色。", - "rank": "上上签" - }, - "三五四": { - "answer": "若大丈夫怀才不遇,则深藏不露乃为上策。", - "question": "君子道消,小人道长,阴气郁郁,阳气不扬,如何如何,良贾深藏。", - "rank": "上上签" - }, - "三八": { - "answer": "般乐怠敖,失业之源。宴安耽毒,失时之本。行事须早,切莫因循。急起直追,攸往咸利。占得此签者飞黄腾达可为预贺。", - "question": "黄鹂报上林,春色鲜明,提鞭快着,马上速行程。", - "rank": "中签" - }, - "三八○": { - "answer": "知足常乐。此签主奉身俭约,心宽身宽,挥霍奢侈,神为之乱,占者以安贫为贵。", - "question": "疏食饮水,乐在其中,膏梁美味,反使心朦。", - "rank": "中下签" - }, - "三八一": { - "answer": "一分耕耘,一分收获。能勤苦在先,自得安乐於後,占之者遇事着着争先,勿步步落後,庶不负平生矣。", - "question": "黄牛辟土,大力开疆,西成时候,谷米盈仓。", - "rank": "上签" - }, - "三八三": { - "answer": "得签者可望取得通达之机缘,从此一帆风顺。", - "question": "九华山顶,紫气腾腾,异尽一舟,取去前行。", - "rank": "上上签" - }, - "三八二": { - "answer": "得此签者在平凡中力求不凡,即将有所成就。", - "question": "蛇可化龙,头角将出,平地一声雷,方显龙蛇力。", - "rank": "中上签" - }, - "三八四": { - "answer": "有错要知悔改,做事务必落实,心胸宽大,人生才有意义。", - "question": "人非孔颜鲜能无过,过而能改仍复无过,开花不足凭,结果方为准,放开怀抱意欣欣。", - "rank": "中上签" - }, - "三六": { - "answer": "春为万物更新之始,人得春气自有发旺景象,春曰无限好,言励志贵乘时也,曰宴琼林言结果必佳美也。占之者亟宜奋勉。", - "question": "春景明,春色新,春意傍水生,春天无限好,好去宴琼林。", - "rank": "上签" - }, - "三六○": { - "answer": "走错方向,用错方法,难望有成,应改弦更张,另设他法,或有成就一天。", - "question": "捕兕于渊,求鱼于山,从朝至暮,功负力捐,改弦易辙,庶可图全。", - "rank": "中上签" - }, - "三六一": { - "answer": "所问之事恐徒劳无功。", - "question": "手持一木鱼,沿街去化缘,不见徐公来,却遇一鸟去。", - "rank": "中签" - }, - "三六七": { - "answer": "做任何事要能适当其时,才会处处逢源,事事顺心。", - "question": "寻芳春日,适见花开,朵朵堪摘,枝枝可栽。", - "rank": "中上签" - }, - "三六三": { - "answer": "得此签者机缘奇佳,得遇贵人,因而飞黄腾达事事遂心,如问姻缘,可得佳人。", - "question": "骑玉兔,到广寒,遇嫦娥,将桂攀,满身馥郁,两袖馨香。", - "rank": "中上签" - }, - "三六九": { - "answer": "若干情况出乎常情之外,不能以常理处之,此时须求助于专门人才。", - "question": "虎出金榜,有勇亦何济,怎似山翁,非富犹有趣。", - "rank": "中下签" - }, - "三六二": { - "answer": "所有冲突已化解,障碍亦撤除,环境无比和谐,适宜做任何事。", - "question": "水火既济,阴阳相契,育物新民,参天赞地。", - "rank": "中上签" - }, - "三六五": { - "answer": "功夫到了,任何事均可以做成。", - "question": "炉中火,沙里金,功力到,丹鼎成。", - "rank": "上上签" - }, - "三六八": { - "answer": "所问之事,已出现祥瑞之兆,很快就有和谐局面出现。", - "question": "龙一吟,云便兴,冲霄直上,快睹太平,为文为武,君君臣臣。", - "rank": "中签" - }, - "三六六": { - "answer": "得此签者将有远行,并在当地遇知音,成家立业,赢得声名。", - "question": "此去万里程,却遇见知音,同心共济,大立勋名。", - "rank": "上上签" - }, - "三六四": { - "answer": "得此签者手法高明,待人处事八面玲珑,如有神道随行。", - "question": "一个神道,随尔去行,逢人说法,到处显灵。", - "rank": "上上签" - }, - "三四": { - "answer": "吉昌。暂时偃蹇终得大伸,宛如枯木逢春,又如山行忽得康庄,示人以偶然落魄,但居仁由义不患人之不知也。", - "question": "缺月又重圆,枯枝色更鲜,一条夷坦路,翘首望青天。", - "rank": "上上签" - }, - "三四○": { - "answer": "倦游归来,景物全非。旧主重逢衣食有恃,因人成事独立为难,占之者勿遽自立一帜也。", - "question": "双燕归南国,来寻王谢家,华堂春尽静,进此托生涯。", - "rank": "中下签" - }, - "三四一": { - "answer": "不吉,诸事不宜。诸事绝望灾戾重重,占病沉重占讼必凶,若求吉庆杳杳无期,惟修德可转危为安。", - "question": "命运蹇兮时违,灾殃及兮身疲,望皇天兮不我顾,嗟我亲兮病斯危。", - "rank": "下签" - }, - "三四七": { - "answer": "目前机运欠佳,事情进行缓慢,日夜 劳,来日运转,情况即可完全改观。", - "question": "马进徐行似有程,月沈西海日东升,运来何必劳心力,风送江湖万里清。", - "rank": "上签" - }, - "三四三": { - "answer": "因时运不济及自己过错,使得处境至为孤寂无助,应借助信仰力量以求自救。", - "question": "出温入寒,被薄衣单,去我慈航,难解横愆。", - "rank": "中签" - }, - "三四九": { - "answer": "一切纷争已息,今后行程应平稳无险,刻下经营多顺利,虽慢了些又何妨?", - "question": "风波今已息,舟楫遇安流,自此功名遂,何须叹白头。", - "rank": "上签" - }, - "三四二": { - "answer": "在他乡工作时意外得遇知音,事事顺遂,暂且不宜返乡。", - "question": "采药天台路转迷,桃花流水赋佳期,春风啼鸟多情思,寄语刘郎且莫归。", - "rank": "中下签" - }, - "三四五": { - "answer": "得此签者,恐终年在外奔波,受尽寂寥之苦,常起思乡之念。", - "question": "谁说故乡无滋味,飘零湖海在天涯,任咨嗟,中秋月隐春雨淋花,多少征人长忆家。", - "rank": "中上签" - }, - "三四八": { - "answer": "困厄之事临身,一时难以解除,惆怅难免,怨恨则不必。", - "question": "云横山际水茫茫,千里长途望故乡,蹇厄事来君莫恨,倚门惆怅立斜阳。", - "rank": "中下签" - }, - "三四六": { - "answer": "鼠年及羊年会有一举成功机会。", - "question": "云散月当空,牛前马后逢,张弓方抵御,一箭定全功。", - "rank": "上签" - }, - "三四四": { - "answer": "示人不可削足适屦,亦寓有‘满招损’之意。", - "question": "三升三石放在一斗,满而溢,子自得。", - "rank": "中签" - }, - "九": { - "answer": "命中得遇贵人相助,未婚男子可得佳侣,商人则应有主见,始能获利。然非积德修持,无此希望也。君子占吉,小人占凶。", - "question": "贵客相逢更可期,庭前枯木凤来仪,好将短事求长事,休听旁人说是非。", - "rank": "上签" - }, - "九○": { - "answer": "转机交运之兆,时下机运甚佳,所问大吉大利。", - "question": "云尽月当中,光辉到处通,路途逢水顺,千里快如风。", - "rank": "中下签" - }, - "九一": { - "answer": "激烈竞争中,需料敌如神,妥为布置以待敌来,赢得胜利后尚需妥善收拾战果。", - "question": "剑戟列山林,盗贼必来侵,败走擒搜定,封侯荫子孙。", - "rank": "下下签" - }, - "九七": { - "answer": "勉人及锋而试,毋自玩愒岁月,果能勇敢任事,艰难赴功,佳遇只在目前,占此者知机缘之失,间不容发,而各自策励也。", - "question": "报导上林,春色鲜明,提鞭快着,马上行程。", - "rank": "下下签" - }, - "九三": { - "answer": "人事变迁世情难测,可喜之中亦覆可惧,若有人暗中指点,始可扶摇直上,显其身手,惹勾连戒招摇也,其垂象微矣。", - "question": "拟欲迁而未可迁,提防喜处惹勾连,前途若得阴人引,变化鱼龙出大渊。", - "rank": "中上签" - }, - "九九": { - "answer": "得此签者,已功成名就,或者,目前从事者志趣不合,如今财力已丰,可以从已趣。", - "question": "打起平生志,西南好去游,腰缠十万贯,骑鹤上扬州。", - "rank": "上上签" - }, - "九二": { - "answer": "所问诸事宜向宽处打算,向远途作想,最后必能成功。", - "question": "岸阔水深舟易落,路遥山险步难行,蛇行自有通津日,月上天空分外明。", - "rank": "中上签" - }, - "九五": { - "answer": "世间悲欢无常,且悲事往往比喜事严重,常能将人击倒。", - "question": "喜未稳,悲已遭,大雨狂风吹古木,人人尽道不坚牢。", - "rank": "中上签" - }, - "九八": { - "answer": "人各有其不同安身立命之所及最适当行动时机,选择其他恐大不利。", - "question": "鼠入土穴,最可安身,日中不见,静夜巡行。", - "rank": "下下签" - }, - "九六": { - "answer": "得此签者,可望遇知音,交至友,得生死相许之配偶。", - "question": "可以寄百里之命,可以托六尺之孤,钟期既遇毋迟误。笑呼呼,他乡聚首,各自乐康和。", - "rank": "中下签" - }, - "九四": { - "answer": "二人合作成功前互疑,惟风度尚在,问婚姻状况,求嗣不得而猜疑,后喜获一女而解。", - "question": "一人去,一人入,清风明月两相猜,获得金鳞下钓台。", - "rank": "中上签" - }, - "二": { - "answer": "神护签,言行循规蹈矩,事业上必有贵人相助,婚姻得人,健康亦佳。谋望一切必可顺遂。官吏占之,有远迁之喜。士人占之,有功名之庆。", - "question": "地有神,甚威灵,兴邦辅国,尊主庇民。", - "rank": "上上签" - }, - "二○": { - "answer": "栽种不得其时,去向漂流不定,远行旅程不顺,家庭亦有风波。此签占事业不利,疾病不定,婚姻无望,出行所如軗阻,讼事凶多吉少。", - "question": "桃李谢春风,西飞又复东,家中无意绪,船在浪涛中。", - "rank": "中上签" - }, - "二○○": { - "answer": "得此签者,时运特佳,做任何事都会有意外之收获。", - "question": "凿石得玉,淘沙得珠,眼前目下,何用踌躇。", - "rank": "中签" - }, - "二○一": { - "answer": "好景不长,好花不再,避免小人挑拨坏事,幸灾乐祸。", - "question": "无端风雨催春去,落尽枝头桃李花,桃畔有人歌且笑,知君心事乱如麻。", - "rank": "中下签" - }, - "二○七": { - "answer": "吉,婚事笑谈中说定,高升喜讯已在半途,双喜临门人生至乐。", - "question": "和合事,笑谈成,喜音在半程,平步踏青云。", - "rank": "中上签" - }, - "二○三": { - "answer": "问卜之人处于小人当道,所负责之事又非内行,虽有贤女子相助,依然难成。", - "question": "门外事重叠,阴人多遇合,贤女虽助巧,渺渺终难洽。", - "rank": "中签" - }, - "二○九": { - "answer": "此签前段昌吉喜庆,事多有成,   末句寓有兄弟 墙之意,或兄弟中,恐有折损。", - "question": "门外好音来,生涯应有庆,名利有更迁,雁行终折阵。", - "rank": "中签" - }, - "二○二": { - "answer": "谋望有成,欣然色喜,名利所在无不遂也,一如木得春气,有发生长养之机,占之者吉。", - "question": "阆苑一时春,庭前花柳新,声传好信息,草木尽欣欣。", - "rank": "中上签" - }, - "二○五": { - "answer": "暗去明来,明去暗来,冥冥之中自有定数。", - "question": "暗去有明来,忧心事可谐,终须成一笑,目下莫疑猜。", - "rank": "下签" - }, - "二○八": { - "answer": "大不吉祥,诸事不宜,诸对婚姻论断,则尤不相宜,恐有劳燕分飞之虞。", - "question": "花残月缺,镜破钗分,休来休往,事始安宁。", - "rank": "中上签" - }, - "二○六": { - "answer": "好事成双,得此签者,正直、高贵,受天之恩宠,事事如意。", - "question": "宝镜无尘染,金貂已剪裁,也逢天意合,终不惹尘埃。", - "rank": "中签" - }, - "二○四": { - "answer": "此签主得贤妻,家庭和谐,生活幸福,亦主妇女有喜。", - "question": "事有喜,面有光,终始好商量,壶中日月长。", - "rank": "下签" - }, - "二一": { - "answer": "须费尽九牛二虎之力始克有成。此签主历尽难险,方能告成,绝地逢生。毕竟柳暗花明又一村,故贫困所以玉汝,忍性所以有为。", - "question": "一水远一水,一山旋一山,水穷山尽处,名利不为难。", - "rank": "上上签" - }, - "二一○": { - "answer": "变起仓悴,即将达成之希望亦被预料不到之状况破坏无遗。", - "question": "万里好江山,风沙尽日间,已吞钩上饵,何必遇波澜。", - "rank": "中上签" - }, - "二一一": { - "answer": "所期盼之事或人,已指日可待。", - "question": "双燕衔书舞,指日一齐来,寂寞淹留客,从兹下钓台。", - "rank": "中下签" - }, - "二一七": { - "answer": "所问事必成,但须防后患,如得财富将有人强分,得配偶则三者纠缠不放。", - "question": "有一人,获一鹿,事团圆,门外索。", - "rank": "中上签" - }, - "二一三": { - "answer": "用人应用有志节及才干之人,并放手让他施展,很快即有成就。", - "question": "用之则行,舍之则藏,一骑出重关,佳音咫尺间。", - "rank": "中签" - }, - "二一九": { - "answer": "佳,月钩风线君子而隐於渔者也,举网烟波锦鳞易见,随遇而安也,占此者宜退居,不利见大人。", - "question": "新月为钩,清风作线,举网烟波,锦鳞易见。", - "rank": "上签" - }, - "二一二": { - "answer": "所问诸事看似高深莫测,只要不畏惧,终有明白一天。", - "question": "望去几重山,高深渐可攀,举头天上看,明月在人间。", - "rank": "中上签" - }, - "二一五": { - "answer": "此签若对男女间相恋、婚姻、结 等,恐属大不利,如问他事,亦波折重重。", - "question": "安坦路平夷,云中一雁飞,桃花逢骤雨,水畔女频啼。", - "rank": "上签" - }, - "二一八": { - "answer": "不祥。主出不利,诸事不顺交易折本,家业凋零,作速退守,尚恐不保妄意进行,更生不测占者戒之。", - "question": "汝往无攸利,花开又及秋,严霜物荐至,退步不存留。", - "rank": "下签" - }, - "二一六": { - "answer": "谨防家人失和,手足互残,并防身边亲人成仇家,小心翼翼,终可有成。", - "question": "门内起干戈,亲仇两不和,朱衣临日月,始觉笑呵呵。", - "rank": "中上签" - }, - "二一四": { - "answer": "行善积德,泽被乡里,将来必有好报。", - "question": "积德施功有子孙, 牛祭神及西邻,功名两字成全日,回首山河万物新。", - "rank": "中签" - }, - "二七": { - "answer": "不可固执己见。而若智珠在抱,成竹在胸,不受他人愚,不遭世人迷,见错自不错,真人自有真,占此签者,自决则吉,从人则凶。", - "question": "莫怪我见错,心性自成屙,偏僻不通心,真人却不魔。", - "rank": "中上签" - }, - "二七○": { - "answer": "过不求人之生活,身体虽劳,精神却愉快。", - "question": "躬耕陇亩,形神似劳,无拘无系,其乐陶陶。", - "rank": "中上签" - }, - "二七一": { - "answer": "大祸临头,心被鬼怪的病淹没而纠缠不放,除非有‘金、羊’有关事物来救。", - "question": "祸来见鬼,鬼病淹缠,金羊得路,身脱灾殃。", - "rank": "中下签" - }, - "二七七": { - "answer": "世事难以尽如人意,不是太过就是不及,为此伤神忧虑,毫无意义。", - "question": "有子长,成水局,时遇火反发福,不必过忧煎,人心苦不足。", - "rank": "下签" - }, - "二七三": { - "answer": "雄壮威严,果敢勇往始可折服众人。", - "question": "深山据猛虎,虎啸出山窝,扬威抖擞,何怕人多。", - "rank": "中下签" - }, - "二七九": { - "answer": "大吉大利,所问之事,困局即将突破,从此可入坦途。", - "question": "蛰龙已出世,头角首生成,云兴雨泽,得济苍生。", - "rank": "中上签" - }, - "二七二": { - "answer": "得此签者可能于仓猝间受命,代表所属协调重大事务,并获圆满成功。", - "question": "急起行,急起行,前途去,结同盟,只手擎天柱,史册好标名。", - "rank": "中签" - }, - "二七五": { - "answer": "知足常乐。此签人弃我取人浊我清,自甘恬淡脑杀繁华,真世外人也。", - "question": "山山山,山上建茅 ,不比人间栋宇,却如天上云昙。", - "rank": "中下签" - }, - "二七八": { - "answer": "陌生环境未了解前,勿冒然前往,如果必须前往,应结伴而行。", - "question": "黑夜里,勿前往,一有值,要着慌,牢牢记,须结党。", - "rank": "下签" - }, - "二七六": { - "answer": "得此签者一生劳碌,谋生之处屡易,好在住宿有着落,奔波途中亦安全。", - "question": "来去原无定处,时来时去安身,跋涉无虑,荣辱不计。", - "rank": "中上签" - }, - "二七四": { - "answer": "吾人行事,宜先制定良策,方可致胜可能。", - "question": "三天门,四地户,布阵成,明聚路,军马齐奔,鸣鼓进步。", - "rank": "中上签" - }, - "二三": { - "answer": "喜讯已到,故人安然无恙,健康痊愈在即。此签否极泰来,由困而复。千里外故人自尽力援手。令凡百顺遂也,若强忧煎足自寻苦趣也。", - "question": "喜喜喜,春风生桃李,不用强忧煎,明月人千里。", - "rank": "中上签" - }, - "二三○": { - "answer": "某事或某人之底细即可水落石出,做抉择不会有困难。", - "question": "玉出昆冈石,舟离古渡滩,行藏终有望,用舍不为难。", - "rank": "上签" - }, - "二三一": { - "answer": "阁下心事纠结不开,待客访友迟延难遇,日后处境将留怅恨。", - "question": "目下意难舒,有客来徐徐,金车虽历险,吝必有终与。", - "rank": "下签" - }, - "二三七": { - "answer": "平平,示人须以‘浮云散,明月照人来’之心情,进行心中之事。", - "question": "无中应有直,心事还成戚,云散月重圆,千里风帆急。", - "rank": "上签" - }, - "二三三": { - "answer": "所问诸事忧患深重,若得人指点迷津,或可化险为夷。", - "question": "恐惧忧煎,皆在目前,若逢明鉴,指破空传。", - "rank": "中签" - }, - "二三九": { - "answer": "援引外力助达目的后,要对外力有适当控制,以免外力从此将已束缚,如举债。", - "question": "大仗神威,群魔消灭,灭了又须威,神威亦极力,牢牢记取,免致久后失跌。", - "rank": "下签" - }, - "二三二": { - "answer": "所问之事可以托付他人去办,不过进行缓慢,好在尚不至出错。", - "question": "可以寄,可以托,事迟迟,无舛错。", - "rank": "上签" - }, - "二三五": { - "answer": "一切条件对已有利,亦无风险,奈合时运见拙而心烦意乱,唯有待贵人援手。", - "question": "道路狂招呼,风波一点无,时乖心绪乱,全仗贵人扶。", - "rank": "中上签" - }, - "二三八": { - "answer": "大吉,人生有些际遇必靠福份及神佑,事情只要含有蛇、兔因素,必有变迁。", - "question": "造化生来信自然,师征千里福绵绵,功名得就神明助,蛇兔相逢定变迁。", - "rank": "下签" - }, - "二三六": { - "answer": "要致富须走险路,做了抉择之后就应耐心以待,不必患得患失。", - "question": "临渊放钩,清绝点埃,巨鳌随得,不用疑猜。", - "rank": "上签" - }, - "二三四": { - "answer": "所问之事一时遭遇困阻,不辨路径,须排除障碍后,则再行进展可也。", - "question": "月掩云间,昏迷道路,云散月明,渐宜进步。", - "rank": "中下签" - }, - "二九": { - "answer": "大吉大利,此签为己即是为人,故致身青云,香闻十里。毋系三生之缘,亦即自食其报。占此签者宜益自策励,以期上苍天心。", - "question": "了却心头事,三生夙有缘,香开十里桂,移步入天边。", - "rank": "中上签" - }, - "二九○": { - "answer": "处理事情上不宜忽略小节,要特别注意突生之状况,并推想其缘由方可无事。", - "question": "走走走,遇一狗,急思寻,可长久。", - "rank": "上签" - }, - "二九一": { - "answer": "来得仓促之消息,不可轻信,变化 忽或反覆无常事情,少管为妙。", - "question": "不知真消息,消息蓦地来,月圆月缺夜,不许把门开。", - "rank": "中签" - }, - "二九七": { - "answer": "先经挫折磨练,然后其生命力必更坚强。", - "question": "木长春天根干老,子实三秋枝叶凋,不凋不谢,不见根牢。", - "rank": "中上签" - }, - "二九三": { - "answer": "见好就收。功成身退后,勿再插身名利场中,致求荣而辱,为乐而兴悲,占者当明出处之道。", - "question": "宾雁 湖地成陆,行建功勋早回程,贪恋终非世人福,莫教鸡鹜会相争。", - "rank": "中签" - }, - "二九九": { - "answer": "任何事物,真即真假即假,一经多方考验,底细便明。", - "question": "药饵真,服了宁,三剂后,足分明,神中神,清中清,固得紧,可长生。", - "rank": "下签" - }, - "二九二": { - "answer": "事情进行到最重要关头应慎思斟酌,方不致带来灾害。", - "question": "火旺处要不疲,水深处要不呆,到头当酌量,毋得惹他灾。", - "rank": "下签" - }, - "二九五": { - "answer": "万物生长、代谢均循一定之自然趋势,人类亦然,能悟其理,自必长寿无灾。", - "question": "叶归根,长立天地,水清源长流河海,人得金丹长生渊涯。", - "rank": "上签" - }, - "二九八": { - "answer": "早起三光,晏起三荒,应及时努力,遇事不可因循不振。", - "question": "叫道叫道,天将明了,何不伸首舒眉,反做蓬蒿到老。", - "rank": "中上签" - }, - "二九六": { - "answer": "花无百日娇,无千日好,得意常想失意时,诸般顺心时,应防突来失意或灾殃。", - "question": "乘马去长安,看花花正发,一日雨来淋,香色尽凋零。", - "rank": "中签" - }, - "二九四": { - "answer": "时运正佳,故凡求职、求偶、求学、求财等均有吉利。", - "question": "天上风,天边月,月白风清,两两相当。", - "rank": "中上签" - }, - "二二": { - "answer": "目前不顺,惟亦不致有风险。此签主彼此相助事茂不济,正人君子诚信相孚,无翻云覆雨之虑,用能一帆风顺也。", - "question": "事相扶,在半途,翻覆终可免,风波一点无。", - "rank": "下下签" - }, - "二二○": { - "answer": "因小失大,不怕一万,只怕万一,星星之火,亦可燎原。", - "question": "先关锁,续提防,小节不知戒,因循成大殃。", - "rank": "中下签" - }, - "二二一": { - "answer": "时运已转,凡事可以顺利进行无阻。", - "question": "燕语莺啼,花开满院,倚栏春睡觉,无语 愁颜。", - "rank": "中上签" - }, - "二二七": { - "answer": "不祥,应加谨防,困窘之境依旧,且有风雨飘摇之险。", - "question": "青毡空守旧,枝上巢生风,莫为一时喜,还疑此象凶。", - "rank": "中签" - }, - "二二三": { - "answer": "凡事求其循序渐进足矣,往往事将有成时又遭外来因素之阻扰。", - "question": "进步且徘徊,春风柳絮吹,水边行客倦,枕畔有忧怀。", - "rank": "中上签" - }, - "二二九": { - "answer": "和则无忧,决之为言诀也,与人诀别也,云还於岫月明於空,廊清翳障独显皎洁之义,占者须实行人和两字。", - "question": "上下和,忧愁决,千嶂云,一轮月。", - "rank": "下签" - }, - "二二二": { - "answer": "随时留心、深思,自必于事有补,前途开朗。", - "question": "劳心劳心,劳心有成,清风借力,欢笑前程。", - "rank": "中下签" - }, - "二二五": { - "answer": "狼狈脱逃一时,免却一场灾祸,在经过一番折腾后,终将回到安适生活中。", - "question": "垂翼遥天去,皆因避难行,一途经济意,又是满园春。", - "rank": "中上签" - }, - "二二八": { - "answer": "虽有阻碍,终将鸾凤合鸣,如问他事,则亦好事多磨,但终将如愿。", - "question": "莫言荆棘恶,终为鸾凤栖,目前应有待,何用早踌躇。", - "rank": "下签" - }, - "二二六": { - "answer": "大吉大利之上上签,已有喜讯佳音,机运一到,即可平步青云,直上九重。", - "question": "佳信至,开笑颜,飞腾一去,拨云上天。", - "rank": "中上签" - }, - "二二四": { - "answer": "所问诸事由于当事人之昏昧,小错很多,但并无大碍。", - "question": "玉石犹终昧,那堪小悔多,终无咎,笑呵呵。", - "rank": "中上签" - }, - "二五": { - "answer": "应防来自西方之暗箭,所问之事尚无征候。此签命骞时乖,群阴插弄,带物难寻,六甲欠安,规行矩步可免祸。", - "question": "见不见,也防人背面,遇不遇,到底无凭据。", - "rank": "下下签" - }, - "二五○": { - "answer": "吉祥,对儿女婚嫁、男女友谊、家室人丁等,更为称庆。", - "question": "女儿大,喜临门,嫁良人,添子孙,同拜受,感皇恩。", - "rank": "中下签" - }, - "二五一": { - "answer": "大不利,应谨言慎行,以防不测,免遭横事,此签于人为病痛,于事亦然。", - "question": "木生火,口不噤,疯癫作症,寒热相侵。", - "rank": "下下签" - }, - "二五七": { - "answer": "人生一切莫不有定数,对事不必过于计较。", - "question": "死有日,生有时,何事慢踌躇,飘然一往,心上无疑。", - "rank": "中签" - }, - "二五三": { - "answer": "凡事先防范于未然,才能安全无虑。", - "question": "槛栏起火,孽畜遭殃,预防得力,灭火成康。", - "rank": "中上签" - }, - "二五九": { - "answer": "此签恐系诸葛当年用兵制敌之策略,所卜之事可能双方实力相当。", - "question": "八门分八位,九星布九方,青赤黄白黑,五色卷锦装,交锋对垒,两两相当。", - "rank": "上签" - }, - "二五二": { - "answer": "在近三年半左右,尽量减少兴革异动,对过去所为加以反省,如此或可避祸。", - "question": "休休休,过了三年又六周,不猛省,祸到头。", - "rank": "中签" - }, - "二五五": { - "answer": "大吉大利,命中注定有神明护佑,逢秋八月或有贵人相助。", - "question": "福星照映,桂子香闻,满天星斗,光耀 人。", - "rank": "上签" - }, - "二五八": { - "answer": "进行之事突遇凶险,须拿勇气排除,事情方可顺利,得此签者恐有受惊吓之事。", - "question": "往来行僻处,猝然着一惊,豺狼若当道,斩灭方称心。", - "rank": "中签" - }, - "二五六": { - "answer": "环境至为险恶,既有近忧,又有远患,如想绝地求生,应先求取活命水源。", - "question": "东南北将来成故墟,燕蓟地苍生无存济,若要大奋雄心,水源不知何处?", - "rank": "下签" - }, - "二五四": { - "answer": "事情办成后,仍应持谨慎戒惧之心,否则恐出差错,使前功尽弃。", - "question": "已遂心头愿,始知志气伸,三山须把握,频频定太平。", - "rank": "中签" - }, - "二八": { - "answer": "吉祥,若卜仕途宦海之事,尤称合适。此签勉人时来运至,宜闻鸡起舞,勿坐失时机,他日衣锦荣归,耄年清福,系於当日遭际时决之。", - "question": "禄马交驰,男儿得志时,行程早办,荣归乐期颐。", - "rank": "上上签" - }, - "二八○": { - "answer": "一旦发生意外灾祸,事发就不可收拾,应有克制对策,庶几解除困难。", - "question": "火势薰天,天边尽赤,遇际水源,庶乎成格。", - "rank": "中下签" - }, - "二八一": { - "answer": "含下列寓意:工作地点以南方为宜,寻访可能得遇,交游虽不广,可获知己。", - "question": "向南有大道,乘马入杭城,不知吴人唱,更有一知音。", - "rank": "上签" - }, - "二八七": { - "answer": "进行一事,必先穷理探源,把握其中要领,方能得心应手。", - "question": "人不识仙,那有真诀,一入玄门,津津有益。", - "rank": "上签" - }, - "二八三": { - "answer": "此签寓意难明,或指形貌才智虽有缺陷,但天生万物,必有所长。", - "question": "勿嫌儿无唇,疾足追不及,纳入猿穴中,走狗何处觅。", - "rank": "上签" - }, - "二八九": { - "answer": "与其汲汲于追求功名,不如修身养性。", - "question": "功名虽多实际,何如修炼成真,真身不朽,万载长春。", - "rank": "中上签" - }, - "二八二": { - "answer": "家有恒产,虽说不多,若能认真经营终必有成。得此签者似不易离家另谋他业。", - "question": "有田一亩,尽可耕耘,无穷收获,都在西成。", - "rank": "中签" - }, - "二八五": { - "answer": "成大事者应志在四方,勿囿于一角,把握时机及早行动。七八或与时日机运有关。", - "question": "大奋冲天志,勿苦恋家乡,七八君行早,扬武在沙场。", - "rank": "中下签" - }, - "二八八": { - "answer": "所问之事,面貌并不清朗,须用心去探求其内蕴。", - "question": "勿谓说话太沈,泥了就不成真,悟出千般奥妙,方识仙道最神。", - "rank": "上上签" - }, - "二八六": { - "answer": "得此签者深受部属爱戴,都能为其赤诚工作,使其事业鸿图大展。", - "question": "葵花向日,忠赤倾心,大开广厦,乐享太平。", - "rank": "上签" - }, - "二八四": { - "answer": "一分耕耘,一分收获,天下无侥幸而成之事。", - "question": "六牛耕地,垦开无疆,收成结实,盈禀盈仓。", - "rank": "下签" - }, - "二六": { - "answer": "此签进不如退,行不如藏,富不如贫,达不如穷,能处处恬淡,即是处处保守,渔樵农圈,转可安居,富贵尊荣,今非昔比。", - "question": "一番桃李一番春,谁识当初气象新,林下水边寻活计,见山了了称心意。", - "rank": "上上签" - }, - "二六○": { - "answer": "此签有力争上游恶居下流之象,後两句警人尤深,坑堑地狱也,占之者速宜回头猛省,以此语为座右铭。", - "question": "终身不习上,在世却枉然,轮回不能免,永落深坑堑。", - "rank": "中签" - }, - "二六一": { - "answer": "得此签者可望得一子一女,亦可能一举得男女各一之双胞胎,凡事求阴阳调和。", - "question": "两个子女,同到齐行,阴阳和合,谋作欢欣。", - "rank": "下签" - }, - "二六七": { - "answer": "全力以赴,必有所成。占者慎勿甘自暴弃,坠青云之志也。", - "question": "滴漏声催鸡唱,趱行人逐队放,晚渡关津,前程无量。", - "rank": "中签" - }, - "二六三": { - "answer": "意外之好运,有时不是福气反成负担。", - "question": "数尾金鱼吞饵,丝竿钓了回头,家食翻嫌太贵,五湖四海遨游。", - "rank": "中签" - }, - "二六九": { - "answer": "寓意有二: 凡命运亨通者,即或居于枯树古井旁,福泽依增 勿营华屋。", - "question": "这颗树下,一穴生成,若迁此土,福禄骈臻。", - "rank": "上签" - }, - "二六二": { - "answer": "所问诸事疑难未解,但很快就能悟出解决之道。", - "question": "中有玄机赋,鸡鸣方显露,猛然悟禅关,打破君门路。", - "rank": "上签" - }, - "二六五": { - "answer": "所问事一两日内尚难定,日子到了事情自明朗,应为三个人合力办成之好事。", - "question": "日中不决,日到方明,一场好事,六耳同成。", - "rank": "下签" - }, - "二六八": { - "answer": "所念之人,远在他乡,久无讯息,对其怀念殷切。", - "question": "人在天涯外,久乏信音来,家人频望眼,草木畅胸怀。", - "rank": "上签" - }, - "二六六": { - "answer": "此签主群阴播弄淆乱心,故交友不可不慎,立意不可不定,断事不可不快,悟性不可不佳,占者终以远之为是。", - "question": "孤宿是妖星,猿猴及树精,入山遇此曜,迷了性和心。", - "rank": "下下签" - }, - "二六四": { - "answer": "天时依一定顺序运转,做任何事不能违背自然法则。", - "question": "卯日儿出林,午时正福临,卯生于寅,方见天心。", - "rank": "中签" - }, - "二四": { - "answer": "谨言慎行,始得平安。安分守己,谨防出入,商贾勿大斗小秤。士子勿诬圣蔑贤,在朝勿贪诈,在野勿争斗,占此签者宜深味之。", - "question": "意孜孜,心戚戚,要平安,防出入。", - "rank": "中下签" - }, - "二四○": { - "answer": "勉人立身修业,勿图官宦之奢望,勿为功禄所贪恋。", - "question": "道必坚心,坚心必道成,建功勋,早回程,造茅庵,修真身,一日飞升,仙班列名。", - "rank": "中上签" - }, - "二四一": { - "answer": "荣耀或羞辱取决人之一念之间,人云亦云,昏庸一生岂不可惜?", - "question": "一念上天堂,一念入地狱,地狱天堂,   便分荣辱,自立念头要真,不可随人碌碌。", - "rank": "中签" - }, - "二四七": { - "answer": "横逆之来出於意外,惊魄丧魂几濒於危,幸根本未摇,所损枝叶略加培植依然生气勃勃,有惊无险。", - "question": "蓦地狂风起,大树尽掀扬,枝叶未凋零,培植终无恙。", - "rank": "下签" - }, - "二四三": { - "answer": "所问事已步入歧途,是否及时省悟回头,视问卜者是否有缘及个性是否执拗。", - "question": "若是有缘人,一指便回首,执迷不悟者,屡引也不走。", - "rank": "下签" - }, - "二四九": { - "answer": "荣枯天定,不要为失意伤情,应乐天知命,得此签者恐刻下时运不佳。", - "question": "荣枯早定莫嗟伤,辛苦他邦安享家乡,为他人作嫁衣裳,今日君尝,他年改调别人尝。", - "rank": "中下签" - }, - "二四二": { - "answer": "所显诗句近乎玄虚,不适用现代,不妨再卜一]。", - "question": "羊逸群,日对民,逢牛口,便咬人,一个君一个臣,君臣有些惊,须仗真神拯救苍生。", - "rank": "中上签" - }, - "二四五": { - "answer": "大功告成之后,自可封侯或退隐山林,而选择后者才是大丈夫行径。", - "question": "男儿若得封侯印,不负人间走一遭,功成身退烟霞啸傲,脱却紫罗袍,方是男儿道。", - "rank": "上签" - }, - "二四八": { - "answer": "勿为假相所欺,应多方深入探讨真相。", - "question": "虚日旺相,法要推寻,四围旋绕,对敌冲营。", - "rank": "中签" - }, - "二四六": { - "answer": "世间有若干危害人体之嗜好,智者应以‘妖狐’迷人为鉴。", - "question": "心月狐狸,迷惑世人,世人不察,延久倾身。", - "rank": "上签" - }, - "二四四": { - "answer": "有好机运来,可以大放异彩,凡事均无阻塞,今后环境更趋有利。", - "question": "月儿升东,清光可挹,万里无云,海天一碧。", - "rank": "上上签" - }, - "五": { - "answer": "否极泰来,外旱逢甘雨,此乃待时而动之义。占得者必潜蓄精神,为奋发地。却不可轻举妄动,致转取戾。顺之者吉,逆之者否。", - "question": "春雷震,夏风巽,卧龙起,猛虎惊,风云会合,救济苍生。", - "rank": "中下签" - }, - "五○": { - "answer": "顺其自然。此签主官运亨通,财星高照,富贵尊荣,造物安排已定,占之者吉。", - "question": "财马两匆忙,官禄有定方,猪羊牛犬,自去主张。", - "rank": "中下签" - }, - "五一": { - "answer": "大器晚成,若问财运,得此签不祥,若问诉讼,则于缠讼多日可获胜诉。", - "question": "空空空,空里得成功,蟠桃千载熟,不怕五更风。", - "rank": "中下签" - }, - "五七": { - "answer": "此签主人只须正直,切不可随波逐流,与世浮沈,能如此名成利就,可操左券。叶落花开者,理之自然也,占此者务以存心正直为要。", - "question": "正直宜守,妄动生灾,利通名达,叶落花开。", - "rank": "中签" - }, - "五三": { - "answer": "惕之签,凡事须全力以赴,不可贪玩疏忽,时运来临,愿望自然可成。", - "question": "须着力,莫远游,长竿钓向蟾蜍窟,直欲云中得巨鳌。", - "rank": "中上签" - }, - "五九": { - "answer": "须守时耐运,待机而行,不可强求。妇人求得此签,恐有夫妻失和情事。", - "question": "纷纷复纷纷,欷 独掩门, 眉望灯火,伴我坐黄昏。", - "rank": "中下签" - }, - "五二": { - "answer": "吉祥,心境渐渐开朗,环境已转佳境,寻人定然相遇,其他亦有转机。", - "question": "愁脸放,笑颜开,秋月挂高台,人从千里来。", - "rank": "中签" - }, - "五五": { - "answer": "时运欠佳,一切难望有成,惟有依靠仅有之一线生机。", - "question": "细雨蒙蒙湿,江边路不通,道途音信远,凭仗借东风。", - "rank": "中下签" - }, - "五八": { - "answer": "所问之事波折连连,有人玉成,有人破坏,无地利之便,须稳妥安排为宜。", - "question": "君子升,小人阻,征战生离苦,前有吉人逢,信在马牛人在楚,事要营求妥。", - "rank": "中上签" - }, - "五六": { - "answer": "所问之事现时现地均难有成,如问姻缘,须向显赫人家去求,如问事业,波折重重。", - "question": "平地起云烟,时下未能安,高处觅姻缘。", - "rank": "中下签" - }, - "五四": { - "answer": "诸事难成。此签诸事不吉,占病不利,名财两空,胎孕有惊,行人不至,谋事不遂,能自猛省亦可挽回天心。", - "question": "无踪无迹,远近难觅,旱海行舟,空劳费力。", - "rank": "中上签" - }, - "八": { - "answer": "目前无人能识,日后必受众人赞颂,怀才不遇者得此签,日后必发达。绦老辱在泥涂,意在静观时机,一旦运至自亨通。", - "question": "虎恋高山别有机,众人目下尚狐疑,雁来嘹呖黄花发,此际声名达帝畿。", - "rank": "中上签" - }, - "八○": { - "answer": "不可暴殄天物,对事物体认不够,任意扔弃滥用,岂不可惜。", - "question": "木向阳春发,三阴又伏根,樵夫不知道,砍去作柴薪。", - "rank": "中下签" - }, - "八一": { - "answer": "此签不吉,月既缺镜又损,所问诸事自属不圆满,恐亦无转机。", - "question": "一月缺,一镜缺,不团圆,无可说。", - "rank": "下下签" - }, - "八七": { - "answer": "此签主功名成遂,财利丰收十全五福萃於一门,是惟忠孝之家,方克获兹善报,占者无不利也。", - "question": "福星照,吉宿临,青天有日见天真,龙飞下载到明庭。", - "rank": "上上签" - }, - "八三": { - "answer": "选择努力方向,如能吸取前贤经验,必能事半功倍,如得神助。", - "question": "我何宿,我何宿,海东河北成名录,一段神光,直冲天渎。", - "rank": "中签" - }, - "八九": { - "answer": "所问诸事意见纷陈,头绪杂乱,如不借助有力者,恐要白费心力。", - "question": "不归一,劳心力,贵人旁,宜借力。", - "rank": "中上签" - }, - "八二": { - "answer": "此签如问战略戎事大吉,问事业则大发,问考试则高中。", - "question": "车马到临,旌旗隐隐月分明,招安讨叛,永大前程。", - "rank": "中上签" - }, - "八五": { - "answer": "愁闷事在杯酒中尽释,夫妻间之不合应尽快化解。", - "question": "倾一 ,展愁眉,天地合,好思为。", - "rank": "中下签" - }, - "八八": { - "answer": "这一签所预示的结局是很差的,劳心劳力,没有收获,所幸的是自己身体方面、家人方面没有大碍,该说是不幸中的大幸。", - "question": "独钓寒潭,中途兴阑,水寒鱼不饵,空载月明还。", - "rank": "中上签" - }, - "八六": { - "answer": "得此签者如为主管,恐有欺害下属之事,结果遭到致命之报复。", - "question": "野鬼张弧射主人,暗中一箭鬼魂惊,忽然红日沈江海,难破空中事不明。", - "rank": "下下签" - }, - "八四": { - "answer": "金鳞影射钱财,警惕吾人谨言少语,如遇友人金钱周转,须防上当受骗。", - "question": "金鳞入手,得还防走,若论周旋,谨言缄口。", - "rank": "中上签" - }, - "六": { - "answer": "心性勿急切,着意搜寻,必能如愿。自来少参透事情之人,此签在使搜寻妙道,而妙道实亦并不奇妙,在人之自悟耳。", - "question": "非玄非奥,非浅非深,一个妙道,着意搜寻。", - "rank": "中下签" - }, - "六○": { - "answer": "戒妄想非分,只宜守身安命,若驰鹜远,徒乱人意,终仍无一成就。占之者切勿轻举妄动,就像美人在车,看自己则在船里,不相关也。", - "question": "红颜美,休挂怀,人在车中,舟行水里。", - "rank": "上上签" - }, - "六一": { - "answer": "桥断路绝,舟破风狂,命运可知矣,占此者能积德修身,广种福田自可转危为安,逢凶化吉,若仍诛求无厌,势必灾祸临身。", - "question": "桥已断,路不通,登舟理楫,又遇狂风。", - "rank": "下下签" - }, - "六七": { - "answer": "一鼓作气,勇往直前,即使往昔曾犯缺失,如今亦可重获振作之机。", - "question": "乘马前进,所求吉贞,随时谐美,缺月重明。", - "rank": "中上签" - }, - "六三": { - "answer": "此签主交卯辰流年,名利双收又逢卯辰生年之人,亦得提拔扶助之德,占者细思量遵行之。", - "question": "湖海意悠悠,烟波下钓钩,若逢龙与兔,名利一齐周。", - "rank": "中上签" - }, - "六九": { - "answer": "知足常乐,随遇而安,否则梦境难圆之慨,妇女得此签,宜勉力抛虚荣之心。", - "question": "不足不足,难伸心曲,野塘雨过月如钩,梦断邯郸眉黛愁。", - "rank": "中下签" - }, - "六二": { - "answer": "有财不招,家口多病,六甲无望,婚姻不成,功名蹭蹬,行人无信,官司口舌均属难免。占此者省些精神,勿为无益之事。", - "question": "深潭月,照镜影,一场空,安报信。", - "rank": "下下签" - }, - "六五": { - "answer": "请神容易送神难。易进难退,鸟脱樊笼而不得,鱼离网钩而不能,淹滞久久难望跳出火坑,占者有扰攘不宁,意绪纷如之象。", - "question": "入而易,出而难,恹恹到再三,交加意不堪。", - "rank": "中下签" - }, - "六八": { - "answer": "此签主外,出远行有利,得此签者,所问之事难题已解,难关已破,从此坦途。", - "question": "舟离古渡月离云,人出潼关好问津,且向前行去求住,何须疑虑两三心。", - "rank": "中签" - }, - "六六": { - "answer": "若时机未熟,但凭己力,尚难成就。妇女得此签,显示心意不足,青春蹉跎。", - "question": "事迟志速,而且反覆,直待岁寒,花残果熟。", - "rank": "中下签" - }, - "六四": { - "answer": "所问之事应重新来过,如以笃实之态度为之,或有可成。", - "question": "物不牢,人断桥,重整理,慢心高。", - "rank": "中下签" - }, - "四": { - "answer": "勉惕类,诸事无法顺利,踏实或有可望。大器晚成,得意必在暮年。若青年得志,必如秦之甘罗,唐之王勃,雨打风飘示警也。", - "question": "春花娇媚,不禁雨打风飘,秋菊幽芳,反耐霜雪傲。", - "rank": "中上签" - }, - "四○": { - "answer": "塞翁失马,焉知非福,诸事均欠顺遂,惟尚未铸下大错,还能全身而退。切勿轻信人言,优柔寡断,坐井观天。", - "question": "一带水,碧澄澄,舟住江上,月到天心;稳步其中,玄妙不闲,非人误己,几丧生身。", - "rank": "中下签" - }, - "四一": { - "answer": "此签示人既凡百称心遂意,便当即时行乐,不可不知足,今日因某事许愿,明日又为某事求祷,以致干渎神明也。惟修身以行善可已。", - "question": "桃李舒姘,春光鲜丽,良辰美景君须记,随心所往事事相宜,无用多疑干渎神祗。", - "rank": "中签" - }, - "四七": { - "answer": "此签主真为美德,人虽不知而神知也,故一念真诚,鬼神可格,金石为开。占得此签务当摒斥虚伪,力求真实,勿欺人以自欺也。", - "question": "真真真,人不识,真真真,神有灵,归宗返本,方是元精。", - "rank": "上上签" - }, - "四三": { - "answer": "所问之事可能走错方向,即改弦易辙,另觅可行之路。古来明哲保身,决不专走死路,悬崖勒马,别作他图,贵独具只眼。", - "question": "无上去,在前头,回头一悟,绳缰好收,千条万线路常在,自好搜求。", - "rank": "中上签" - }, - "四九": { - "answer": "久病者突逢良医,立即恢复健康,经营事业不佳者,可望获良才,兴隆有望。", - "question": "沈沈屙染,不见天心,雷门一震,体健身轻。", - "rank": "中下签" - }, - "四二": { - "answer": "玄机不玄,道本中庸,圣贤仙佛只是行中庸之道,遂为千百世所景仰。常人欲上仙梯何难之有,慎勿谓玄机隐微,甘居人後也。", - "question": "隐中显,显中微,个中有玄机,参得透了,直上仙梯。", - "rank": "上上签" - }, - "四五": { - "answer": "做事沈着稳定,自有容身之地,多热心公益,门庭自逢佳运。概须脚踏实地,不必行险侥幸,自有安身立命之所。", - "question": "不用忙,不用慌,自有驻足乡,鸣鼓响钟地,三宝见门墙。", - "rank": "中下签" - }, - "四八": { - "answer": "此签主舍近求远,一事无成 ,徒自劳苦,益时运不济,强求无益也。占此者须明心见性,尽可安贫乐道,毋庸逆天而行也。", - "question": "走尽天涯,风霜历遍,不如问人三天,渐渐有回首见。", - "rank": "中签" - }, - "四六": { - "answer": "一生争名夺利,最后化为乌有,回头是岸。此签言人一饮一食莫非前定,要为名利作马牛。", - "question": "奔波一世,总是虚浮,无常一到万事休,急早回头。", - "rank": "下下签" - }, - "四四": { - "answer": "签主福祸无门,惟人自招,放下屠刀,立地成佛。苦心修炼,必不自落凡庸,占此者当知荣辱之机,己实操之,不必怨天尤人也。", - "question": "四顾无门路,桃源路可通,修炼成正果,万岁寿如松。", - "rank": "上上签" - } -} \ No newline at end of file diff --git a/artifact_collect/artifact_list.json b/artifact_collect/artifact_list.json deleted file mode 100644 index 9e6ce50..0000000 --- a/artifact_collect/artifact_list.json +++ /dev/null @@ -1,165 +0,0 @@ -{ - "角斗士的终幕礼": { - "element":["角斗士的留恋","角斗士的归宿","角斗士的希冀","角斗士的酣醉","角斗士的凯旋"], - "abbreviation": ["角斗士","角斗士套"], - "obtain": "龙狼", - "number": "15001", - "注释":"这个文件记录圣遗物的套装名,element表示包含的部件名,必须按照花羽毛沙漏杯头冠的顺序填写,abbreviation表示简称,obtain表示哪个副本掉落,number表示图标的编号" - }, - "流浪大地的乐团": { - "element":["乐团的晨光","琴师的箭羽","终幕的时计","吟游者之壶","指挥的礼帽"], - "abbreviation": ["流浪"], - "obtain": "龙狼", - "number": "15003" - }, - "平息鸣雷的尊者": { - "element":["平雷之心","平雷之羽","平雷之刻","平雷之器","平雷之冠"], - "abbreviation": [], - "obtain": "雷本", - "number": "14002" - }, - "如雷的盛怒": { - "element":["雷鸟的怜悯","雷灾的孑遗","雷霆的时计","降雷的凶兆","唤雷的头冠"], - "abbreviation": [], - "obtain": "雷本", - "number": "15005" - }, - "渡过烈火的贤人": { - "element":["渡火者的决绝","渡火者的解脱","渡火者的煎熬","渡火者的醒悟","渡火者的智慧"], - "abbreviation": [], - "obtain": "火本", - "number": "14003" - }, - "被怜爱的少女": { - "element":["远方的少女之心","少女飘摇的思念","少女苦短的良辰","少女片刻的闲暇","少女易逝的芳颜"], - "abbreviation": [], - "obtain": "风本", - "number": "14004" - }, - "染血的骑士道": { - "element":["染血的铁之心","染血的黑之羽","染血骑士之时","染血的骑士之杯","染血的铁假面"], - "abbreviation": [], - "obtain": "宗室本", - "number": "15008" - }, - "炽烈的炎之魔女": { - "element":["魔女的炎之花","魔女的常燃之羽","魔女的破灭之时","魔女的心之火","焦灼的魔女帽"], - "abbreviation": [], - "obtain": "火本", - "number": "15006" - }, - "昔日宗室之仪": { - "element":["宗室之花","宗室之翎","宗室时计","宗室银瓮","宗室面具"], - "abbreviation": [], - "obtain": "宗室本", - "number": "15007" - }, - "翠绿之影": { - "element":["野花记忆的绿野","猎人青翠的箭羽","翠绿猎人的笃定","翠绿猎人的容器","翠绿的猎人之冠"], - "abbreviation": [], - "obtain": "风本", - "number": "15002" - }, - "冰风迷途的勇士": { - "element":["历经风雪的思念","摧冰而行的执望","冰雪故园的终期","遍结寒霜的傲骨","破冰踏雪的回音"], - "abbreviation": [], - "obtain": "冰本", - "number": "14001" - }, - "沉沦之心": { - "element":["饰金胸花","追忆之风","坚铜罗盘","沉波之盏","酒渍船帽"], - "abbreviation": [], - "obtain": "冰本", - "number": "15004" - }, - - "悠古的磐岩": { - "element":["磐陀裂生之花","嵯峨群峰之翼","星罗圭璧之晷","巉岩琢塑之樽","不动玄石之相"], - "abbreviation": [], - "obtain": "岩本", - "number": "14005" - }, - - "逆飞的流星": { - "element":["夏祭之花","夏祭终末","夏祭之刻","夏祭水玉","夏祭之面"], - "abbreviation": [], - "obtain": "岩本", - "number": "14006" - }, - - "千岩牢固": { - "element":["勋绩之花","昭武翎羽","金铜时晷","盟誓金爵","将帅兜鍪"], - "abbreviation": [], - "obtain": "苍白", - "number": "15017" - }, - - "苍白之火": { - "element":["无垢之花","贤医之羽","停摆之刻","超越之盏","嗤笑之面"], - "abbreviation": [], - "obtain": "苍白", - "number": "15018" - }, - - "追忆之注连": { - "element":["羁缠之花","思忆之矢","朝露之时","祈望之心","无常之面"], - "abbreviation": [], - "obtain": "充能", - "number": "15019" - }, - - "绝缘之旗印": { - "element":["明威之镡","切落之羽","雷云之笼","绯花之壶","华饰之兜"], - "abbreviation": [], - "obtain": "充能", - "number": "15020" - }, - "华馆梦醒形骸记": { - "element": [ - "荣花之期", - "华馆之羽", - "众生之谣", - "梦醒之瓢", - "形骸之笠" - ], - "abbreviation": [], - "obtain": "华馆", - "number": "15021" - }, - "海染砗磲": { - "element": [ - "海染之花", - "渊宫之羽", - "离别之贝", - "真珠之笼", - "海祇之冠" - ], - "abbreviation": [], - "obtain": "华馆", - "number": "15022" - }, - "辰砂往生录": { - "element": [ - "生灵之华", - "潜光片羽", - "阳辔之遗", - "结契之刻", - "虺雷之姿" - ], - "abbreviation": [], - "obtain": "余响", - "number": "15023" - }, - "来歆余响": { - "element": [ - "魂香之花", - "垂玉之叶", - "祝祀之凭", - "涌泉之盏", - "浮溯之珏" - ], - "abbreviation": [], - "obtain": "余响", - "number": "15024" - } -} \ No newline at end of file diff --git a/artifact_collect/artifact_property.json b/artifact_collect/artifact_property.json deleted file mode 100644 index 28e6cdd..0000000 --- a/artifact_collect/artifact_property.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - {"name": "生之花", "property_list": ["生命数值加成"]}, - {"name": "死之羽", "property_list": ["攻击数值加成"]}, - {"name": "时之沙", "property_list": ["生命百分比加成","攻击百分比加成","防御百分比加成","元素精通","元素充能效率"]}, - {"name": "空之杯", "property_list": ["生命百分比加成","攻击百分比加成","防御百分比加成","元素精通", - "风元素伤害加成","火元素伤害加成","水元素伤害加成","冰元素伤害加成","岩元素伤害加成", - "雷元素伤害加成","草元素伤害加成","物理伤害百分比加成"]}, - {"name": "理之冠", "property_list": ["生命百分比加成","攻击百分比加成","防御百分比加成","元素精通", - "暴击率百分比加成","暴击伤害百分比加成","治疗百分比加成"]}, - {"name": "副词条", "property_list": ["生命数值加成","生命百分比加成","攻击数值加成","攻击百分比加成","防御数值加成","防御百分比加成", - "元素精通","元素充能效率","暴击率百分比加成","暴击伤害百分比加成"]} -] \ No newline at end of file diff --git a/artifact_collect/property_list.json b/artifact_collect/property_list.json deleted file mode 100644 index 0702f5a..0000000 --- a/artifact_collect/property_list.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "main": { - "生命数值加成": {"txt":"生命值","initial_value": 717,"growth_value": 203.15,"max": 4780}, - "生命百分比加成": {"txt":"生命值","initial_value": 0.07,"growth_value": 0.0198,"max": 0.466}, - "攻击数值加成": {"txt":"攻击力","initial_value": 47,"growth_value": 13.2,"max": 311}, - "攻击百分比加成": {"txt":"攻击力","initial_value": 0.07,"growth_value": 0.0198,"max": 0.466}, - "防御百分比加成": {"txt":"防御力","initial_value": 0.087,"growth_value": 0.0248,"max": 0.583}, - "元素精通": {"txt":"元素精通","initial_value": 28,"growth_value": 7.95,"max": 187}, - "元素充能效率": {"txt":"元素充能效率","initial_value": 0.087,"growth_value": 0.02155,"max": 0.518}, - "暴击率百分比加成": {"txt":"暴击率","initial_value": 0.047,"growth_value": 0.0112,"max": 0.311}, - "暴击伤害百分比加成": {"txt":"暴击伤害","initial_value": 0.093,"growth_value": 0.02845,"max": 0.622}, - "治疗百分比加成": {"txt":"治疗加成","initial_value": 0.054,"growth_value": 0.01525,"max": 0.359}, - "物理伤害百分比加成": {"txt":"物理伤害加成","initial_value": 0.087,"growth_value": 0.0248,"max": 0.583}, - "风元素伤害加成": {"txt":"风元素伤害加成","initial_value": 0.07,"growth_value": 0.0198,"max": 0.466}, - "火元素伤害加成": {"txt":"火元素伤害加成","initial_value": 0.07,"growth_value": 0.0198,"max": 0.466}, - "水元素伤害加成": {"txt":"水元素伤害加成","initial_value": 0.07,"growth_value": 0.0198,"max": 0.466}, - "冰元素伤害加成": {"txt":"冰元素伤害加成","initial_value": 0.07,"growth_value": 0.0198,"max": 0.466}, - "雷元素伤害加成": {"txt":"雷元素伤害加成","initial_value": 0.07,"growth_value": 0.0198,"max": 0.466}, - "草元素伤害加成": {"txt":"草元素伤害加成","initial_value": 0.07,"growth_value": 0.0198,"max": 0.466}, - "岩元素伤害加成": {"txt":"岩元素伤害加成","initial_value": 0.07,"growth_value": 0.0198,"max": 0.466} - }, - "secondary": { - "生命数值加成": {"txt": "生命值","level": [209,239,269,299]}, - "生命百分比加成": {"txt": "生命值","level": [0.041,0.047,0.053,0.058]}, - "攻击数值加成": {"txt": "攻击力","level": [14,16,18,19]}, - "攻击百分比加成": {"txt": "攻击力","level": [0.041,0.047,0.053,0.058]}, - "防御数值加成": {"txt": "防御力","level": [16,19,21,23]}, - "防御百分比加成": {"txt": "防御力","level": [0.051,0.058,0.066,0.073]}, - "元素精通": {"txt": "元素精通","level": [16,19,21,23]}, - "元素充能效率": {"txt": "元素充能效率","level": [0.045,0.052,0.058,0.065]}, - "暴击率百分比加成": {"txt": "暴击率","level": [0.027,0.031,0.035,0.039]}, - "暴击伤害百分比加成": {"txt": "暴击伤害","level": [0.054,0.062,0.070,0.078]} - } -} \ No newline at end of file diff --git a/config.py b/config.py deleted file mode 100644 index 54d66ce..0000000 --- a/config.py +++ /dev/null @@ -1,42 +0,0 @@ - -# 插件的配置文件 - - -# 原神抽卡 - -Gacha10Limit = 100 # 10连每天可以抽的次数 -Gacha90Limit = 100 # 90连每天可以抽的次数 -Gacha180Limit = 100 # 180连每天可以抽的次数 - - - - -# 神瞳信息查询 - -# 这个参数设置是否允许私聊获取神瞳信息,默认为False,表示不允许私聊,你可以改为True,来设置允许私聊 -# 注意,机器人短时间内大量私聊有可能会被腾讯风控 -# 这个效果还没实现,先不要管 -# ALLOW_PRIVATE_CHAT = False - - - - - - - -# 圣遗物收集 - -# 用户的体力值上限,默认160 -MAX_STAMINA = 160 - -# 体力值多长时间回复1点,默认是8分钟 -STAMINA_RESTORE = 8 - -# 圣遗物副属性有4个级别,这里设置强化时4个级别出现的概率,默认是40% 30% 20% 10% -SECONDARY_LEVEL_PROBABILITY = [0.4,0.3,0.2,0.1] - -# 强化圣遗物需要的强化点数,第一个值是0级自带的点数,第二个是0级到1级消耗的点数,第3个是1级到2级消耗的点数 -CONSUME_STRENGTHEN_POINTS = [3780,3000,3725,4425,5150,5900,6675,7500,8350,9225,10125,11050,12025,13025,15150,17600,20375,23500,27050,31050,35575] - - - diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..35aac47 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,174 @@ +[[package]] +name = "aiofiles" +version = "22.1.0" +description = "File support for asyncio." +category = "main" +optional = false +python-versions = ">=3.7,<4.0" + +[[package]] +name = "anyio" +version = "3.6.2" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +category = "main" +optional = false +python-versions = ">=3.6.2" + +[package.dependencies] +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] +test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] +trio = ["trio (>=0.16,<0.22)"] + +[[package]] +name = "certifi" +version = "2022.12.7" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "httpcore" +version = "0.16.3" +description = "A minimal low-level HTTP client." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +anyio = ">=3.0,<5.0" +certifi = "*" +h11 = ">=0.13,<0.15" +sniffio = ">=1.0.0,<2.0.0" + +[package.extras] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] + +[[package]] +name = "httpx" +version = "0.23.3" +description = "The next generation HTTP client." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +certifi = "*" +httpcore = ">=0.15.0,<0.17.0" +rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} +sniffio = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<13)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "loguru" +version = "0.6.0" +description = "Python logging made (stupidly) simple" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} +win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} + +[package.extras] +dev = ["colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "tox (>=3.9.0)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "black (>=19.10b0)", "isort (>=5.1.1)", "Sphinx (>=4.1.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)"] + +[[package]] +name = "pillow" +version = "9.4.0" +description = "Python Imaging Library (Fork)" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "rfc3986" +version = "1.5.0" +description = "Validating URI References per RFC 3986" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} + +[package.extras] +idna2008 = ["idna"] + +[[package]] +name = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "win32-setctime" +version = "1.1.0" +description = "A small Python utility to set file creation time on Windows" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.extras] +dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.8" +content-hash = "51d9849d8e9541bbfbacbba5a71851c01cf34722c5fc0cfe70e57ba3dfadf5cb" + +[metadata.files] +aiofiles = [] +anyio = [] +certifi = [] +colorama = [] +h11 = [] +httpcore = [] +httpx = [] +idna = [] +loguru = [] +pillow = [] +rfc3986 = [] +sniffio = [] +win32-setctime = [] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c1d267d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,19 @@ +[tool.poetry] +name = "GIBotCore" +version = "0.1.0" +description = "Core of Genshin_Impact_Bot." +authors = ["HKY", "Wansn"] +license = "GNU General Public License v3.0" + +[tool.poetry.dependencies] +python = "^3.8" +loguru = "^0.6.0" +Pillow = "^9.4.0" +httpx = "^0.23.3" +aiofiles = "^22.1.0" + +[tool.poetry.dev-dependencies] + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/qiu_qiu_translation/__init__.py b/qiu_qiu_translation/__init__.py deleted file mode 100644 index 5d9e833..0000000 --- a/qiu_qiu_translation/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -from hoshino import Service -from .qiu_qiu_translation import qiu_qiu_word_translation,qiu_qiu_phrase_translation - - -sv = Service("原神丘丘语翻译") - -suffix = "\n※ 这个插件只能从丘丘语翻译为中文,不能反向翻译\n※ 发送词语时请注意空格位置是否正确,词语不区分大小写,不要加入任何标点符号\n※ 翻译数据来源于 米游社论坛 https://bbs.mihoyo.com/ys/article/2286805 \n※ 如果你有更好的翻译欢迎来提出 issues" - - - -@sv.on_prefix("丘丘一下") -async def qiu_qiu(bot, ev): - txt = ev.message.extract_plain_text().strip().lower() - if txt == "": - return - mes = qiu_qiu_word_translation(txt) - mes += suffix - await bot.send(ev, mes,at_sender=True) - - - -@sv.on_prefix("丘丘词典") -async def qiu_qiu(bot, ev): - txt = ev.message.extract_plain_text().strip().lower() - if txt == "": - return - mes = qiu_qiu_phrase_translation(txt) - mes += suffix - await bot.send(ev, mes,at_sender=True) - - - - - - - diff --git a/qiu_qiu_translation/qiu_qiu_translation.py b/qiu_qiu_translation/qiu_qiu_translation.py deleted file mode 100644 index c399c50..0000000 --- a/qiu_qiu_translation/qiu_qiu_translation.py +++ /dev/null @@ -1,85 +0,0 @@ - -import json -import os - - -FILE_PATH = os.path.dirname(__file__) - -QIU_QIU_WORD = {} -QIU_QIU_PHRASE = {} - - -with open(os.path.join(FILE_PATH,'qiu_qiu_dictionary.json'),'r',encoding='UTF-8') as f: - data = json.load(f) - QIU_QIU_WORD = data["word"] - QIU_QIU_PHRASE = data["phrase"] - - -def compare_words(word): - # 比对word库是否有匹配的单词,有的话返回翻译,没有返回原词 - if word in QIU_QIU_WORD: - return QIU_QIU_WORD[word] - - return word - -def compare_phrase(phrase): - # 比对phrase库是否有匹配的单词,有的话返回翻译,没有的话匹配word库,都没有返回原词 - if phrase in QIU_QIU_PHRASE: - return QIU_QIU_PHRASE[phrase] - if phrase in QIU_QIU_WORD: - return QIU_QIU_WORD[phrase] - - return phrase - - - - -def qiu_qiu_word_translation(txt:str): - # 对语句按空格分隔替换单词翻译 - txt_list = txt.split(" ") - mes = "你查询的的丘丘语意思为:\n" - - for word in txt_list: - tra_word = compare_words(word) - - if tra_word == word: - # 如果是原词表示没有翻译,前后加空格接回语句里 - if not mes[-1] == " ": - mes += " " - mes += tra_word - mes += " " - else: - mes += tra_word - mes += "\n" - return mes - - - -def qiu_qiu_phrase_translation(phrase): - # 语句翻译,先看phrase库是不是有匹配的语句 - # 没有的话把单词拆开返回单词的意思 - tra_phrase = compare_phrase(phrase) - if tra_phrase != phrase: - return f"你查询的的丘丘语意思为:\n{tra_phrase}\n" - - txt_list = phrase.split(" ") - mes = "没有查到这句丘丘语,以下是单词的翻译\n" - for word in txt_list: - if word == " ": - continue - tra_word = compare_phrase(word) - if tra_word == word: - mes += f"{word} : 没有这个词的翻译\n" - else: - mes += f"{word} : {tra_word}\n" - - return mes - - - - - - - - - diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/almanac/__init__.py b/src/almanac/__init__.py similarity index 99% rename from almanac/__init__.py rename to src/almanac/__init__.py index 237b727..cf9f97c 100644 --- a/almanac/__init__.py +++ b/src/almanac/__init__.py @@ -1,9 +1,8 @@ from hoshino import Service, priv, get_bot + from .almanac import get_almanac_base64_str, load_data -from .tweaks import * from .draw_lots import get_pic, draw_info, gen_pic -import os -import json +from .tweaks import * FILE_PATH = os.path.dirname(__file__) DB_PATH = os.path.join(FILE_PATH, "assets", "config.json") diff --git a/almanac/almanac.py b/src/almanac/almanac.py similarity index 100% rename from almanac/almanac.py rename to src/almanac/almanac.py index 872ed74..8ff422e 100644 --- a/almanac/almanac.py +++ b/src/almanac/almanac.py @@ -1,11 +1,11 @@ -from PIL import Image, ImageDraw, ImageFont -from io import BytesIO - -import os +import base64 import json +import os import random -import base64 import time +from io import BytesIO + +from PIL import Image, ImageDraw, ImageFont FILE_PATH = os.path.dirname(__file__) FONT_PATH = os.path.join(FILE_PATH, "assets", "汉仪文黑.ttf") diff --git a/src/almanac/assets/almanac_list.json b/src/almanac/assets/almanac_list.json new file mode 100644 index 0000000..7f9c5e0 --- /dev/null +++ b/src/almanac/assets/almanac_list.json @@ -0,0 +1,159 @@ +{ + "抽卡": { + "buff": [ + "欧气满满,十连出金", + "出金不歪" + ], + "debuff": [ + "武器大师", + "保底出金", + "金色会是痛苦大剑" + ] + }, + "刷世界boss": { + "buff": [ + "双攻双爆角斗士" + ], + "debuff": [ + "只有保底材料", + "贪生怕死角斗士" + ] + }, + "刷风本": { + "buff": [ + "会有极品猎人套", + "会掉真正的少女心", + "治疗加成少女头" + ], + "debuff": [ + "勇往直前少女心", + "少女飘摇的杀意", + "少女暴怒的容颜" + ] + }, + "刷火本": { + "buff": [ + "魔女帽子火伤杯", + "暴伤魔女帽!", + "火伤魔女心!" + ], + "debuff": [ + "幡 然 醒 悟", + "这么阴间的地方真的会有魔女套吗?", + "不务正业火魔女", + "会匹配到3个卢姥爷" + ] + }, + "刷岩本": { + "buff": [ + "悠久的磐岩伴你左右", + "岩神的庇护常在" + ], + "debuff": [ + "防御流星杯,你值得拥有" + ] + }, + "刷宗室": { + "buff": [ + "物理伤害骑士道,元素精通宗室套" + ], + "debuff": [ + "贪生怕死骑士道,物理伤害宗室杯" + ] + }, + "刷冰本": { + "buff": [ + "双暴词条概率up" + ], + "debuff": [ + "防御力船帽,无人可及" + ] + }, + "刷雷本": { + "buff": [ + "愿雷鸟伴你左右" + ], + "debuff": [ + "来表演一个只掉平雷套的绝活", + "风神忽悠雷凶兆" + ] + }, + "锄大地": { + "buff": [ + "会掉一大堆紫色材料" + ], + "debuff": [ + "深渊法师爱你哟", + "会被冰水法控到死" + ] + }, + "挖矿": { + "buff": [ + "开矿出双材料" + ], + "debuff": [ + "去别人世界会被拒" + ] + }, + "刷天赋本": { + "buff": [ + "金色!我看到了金色的书!" + ], + "debuff": [ + "2蓝2绿不会变" + ] + }, + "刷突破材料": { + "buff": [ + "金色!我看到了金色的材料!" + ], + "debuff": [ + "2蓝2绿不会变" + ] + }, + "升级圣遗物": { + "buff": [ + "稀有词条跳跳跳", + "会双爆拉满" + ], + "debuff": [ + "女 仆 狂 喜", + "无中生有防御力", + "生命拉满", + "完美避开双爆" + ] + }, + "打风魔龙": { + "buff": [ + "看我一箭一个风魔鸡", + "今天特瓦林可以给想要的突破材料", + "5金加原胚!" + ], + "debuff": [ + "会不小心掉下平台", + "不小心被地板烫死了" + ] + }, + "打狼王": { + "buff": [ + "今天安德琉斯的心情不错,可以py一下", + "5金加原胚!" + ], + "debuff": [ + "狼尾巴*1" + ] + }, + "打公子": { + "buff": [ + "今天可以和公子py想要的突破材料", + "5金加原胚!" + ], + "debuff": [ + "要角没有!要命一条!" + ] + } +} + + + + diff --git a/almanac/assets/back.png b/src/almanac/assets/back.png similarity index 100% rename from almanac/assets/back.png rename to src/almanac/assets/back.png diff --git a/src/almanac/assets/config.json b/src/almanac/assets/config.json new file mode 100644 index 0000000..6c7fc62 --- /dev/null +++ b/src/almanac/assets/config.json @@ -0,0 +1,6 @@ +{ + "10001": { + "pos": "二八", + "time": "2021-06-05" + } +} \ No newline at end of file diff --git a/almanac/assets/lots_bg.png b/src/almanac/assets/lots_bg.png similarity index 100% rename from almanac/assets/lots_bg.png rename to src/almanac/assets/lots_bg.png diff --git a/src/almanac/assets/lots_list.json b/src/almanac/assets/lots_list.json new file mode 100644 index 0000000..7f5917b --- /dev/null +++ b/src/almanac/assets/lots_list.json @@ -0,0 +1,1922 @@ +{ + "一": { + "answer": "大吉,事业、财运、健康、婚姻均顺遂。见龙在田,利见大人。君子得之终日乾乾,夕愓若。以是自强不息,居上不骄、在下不忧,大吉也。", + "question": "天门一挂榜,预定夺标人,马嘶芳草地,秋高听鹿鸣。", + "rank": "上上签" + }, + "一○": { + "answer": "才气出众,无奈受制,去向宜北,可获佳遇。功名富贵勤苦方得,尽人事,皇天不负。若懒惰或始勤终息,而欲望飞达,无异南辕北辙。", + "question": "嘹呖征鸿独出群,高飞羽翼更纠纷,云程北进好音遂闻,朝云暮雨交加有凭。", + "rank": "上上签" + }, + "一○○": { + "answer": "得而复失之象,镜中花海底月,均虚而非实,此亦似之。然设能兢兢业业,克自保之,必不至失贻诮,妙手空空也,占此者只须善提防之。", + "question": "喜喜喜,终防否,获得骊龙颔下珠,忽然失却,还在水里。", + "rank": "中上签" + }, + "一○一": { + "answer": "太平盛世,家庭和乐。百事如意,大吉大利营谋得志,功名神助,行人已归,失物早还,六甲生男,婚姻成就,疾病即癒,占者必喜无疑。", + "question": "国有贤士,廷无佞臣,干戈不用,常享太平。", + "rank": "中签" + }, + "一○七": { + "answer": "好运瞬即逝,理想忽受阻碍,办事难有成就。", + "question": "红叶无颜色,凋零一夜风,邻鸡醒午梦,心事总成空。", + "rank": "中上签" + }, + "一○三": { + "answer": "得签者为首脑时,应立求属下各安其位,各部门主管廉洁公正。", + "question": "民乐业,官吏清,雍熙之世复见于今,告诸人千秋鸿业,仗此望明君。", + "rank": "中上签" + }, + "一○九": { + "answer": "慎防勿蹈前车之覆辙,宁可改弦更张,另作他图。", + "question": "勿上旧辙,甘驾新车,东西南北,稳步康衢。", + "rank": "下签" + }, + "一○二": { + "answer": "示人以心性修养,积功好义之道理。", + "question": "泰来否已极,诸事莫忧心,但须 养元福,做些好事,行些方便,一点丹灵独得真。", + "rank": "中下签" + }, + "一○五": { + "answer": "远大目标不易实现,如有匡助之力或引荐之人,也就获得成功机会。", + "question": "月中有丹桂,人终攀不着,云梯足下生,此际好落脚。", + "rank": "中上签" + }, + "一○八": { + "answer": "所问之事情况混乱,时运不佳,事多蹉跎,一无所成。", + "question": "事如麻,理多错,日掩云中,空成耽搁。", + "rank": "中上签" + }, + "一○六": { + "answer": "失意者之孤寂与无奈,得此签者,宜调整处世态度,以此为诫。", + "question": "天间一孤雁,嘹唳叹离群,试问知君者,而今有几人。", + "rank": "中上签" + }, + "一○四": { + "answer": "大吉大利。动作如意,谋为称心,吉人自有天佑,福禄永保安宁,故有泰山磐石之喻,中通外直言人品第一也,占之吉。", + "question": "安如泰山,稳如磐石,放胆前行,中通外直。", + "rank": "上上签" + }, + "一一": { + "answer": "诸事不利。此签有伤亡之患,哭泣之哀,凡事不利有名无实,非常之灾,占之宜戒谨恐惧,时时修省。", + "question": "无踪又无迹,远近均难觅,平地起风波,似笑还成泣。", + "rank": "下下签" + }, + "一一○": { + "answer": "不祥之兆,近时或有惊险之事,小心。可能应验于鼠年,鼠日或属鼠之人。", + "question": "夜梦被鼠惊,醒来不见人,终宵废寝,直到天明。", + "rank": "下签" + }, + "一一一": { + "answer": "凡事靠自己,依赖别人不可靠。", + "question": "秋霜肃,夏日炎,新花鲜了旧花淹,世情看冷暖,逢者不须言。", + "rank": "上签" + }, + "一一七": { + "answer": "努力必有代价,但须耐心等待。", + "question": "珠玉走盘中,田园定阜丰,休言谋未遂,此去便亨通。", + "rank": "中签" + }, + "一一三": { + "answer": "如问疾病,暂难痊愈,尚需时日,以得名医。", + "question": "屙染沈沈,终日昏昏,雷门一震,体健身轻。", + "rank": "中下签" + }, + "一一九": { + "answer": "命中有贵人相助,安份守己以待机运。", + "question": "朦胧秋月映朱门,林外鸟声远寺僧,自有贵人来接引,何须巧语似流莺。", + "rank": "中下签" + }, + "一一二": { + "answer": "不避劳苦,慎选致力方向。", + "question": "未展英雄志,驰驱不惮劳,敢将休咎卜,西北夺前标。", + "rank": "上签" + }, + "一一五": { + "answer": "不祥。绝门绝路诸事不利,含沙射影更防暗算,占得此者,速深居韬晦,矢志行善,庶几灾祸可解。", + "question": "路不通,门闭塞,谨慎提防,云藏月黑。", + "rank": "下下签" + }, + "一一八": { + "answer": "得此签者,所问诸事均处于最佳状态,事事称心如意。", + "question": "月已明,花再发,事悠悠,无不合。", + "rank": "中上签" + }, + "一一六": { + "answer": "贪图小利,成不了大事,即使想通而暂不斤斤计较,恐也有始无终,旧态复萌。", + "question": "蜗角蝇头利,而今已变通,草头人笑汝,宜始不宜终。", + "rank": "中签" + }, + "一一四": { + "answer": "所问之事,呈胶着状,惟会突起变化,所有问题迎刃而解。", + "question": "易非易,难非难,忽地起波澜,欢笑两三番。", + "rank": "下签" + }, + "一七": { + "answer": "处于蓄势欲发又迟疑难决者,宜下定决心,完成大业。宜谨慎,凡事色举翔集,审度而後进退。倘操切从事,必掷珠玉於泥沙,自暴自弃。", + "question": "欲行还止,徘徊不已,藏玉怀珠,寸心千里。", + "rank": "上签" + }, + "一七○": { + "answer": "得此签者,恐有失意事,惟转机已现。", + "question": "莫叹残花,花开枯树,屋头春意,喜笑嘻嘻。", + "rank": "中签" + }, + "一七一": { + "answer": "凡进行之事,均属得失互参,与人交往洽事,若得遇亲信可靠之人,方可心安。", + "question": "一事总成空,一事还成喜,若遇口边人,心下堪凭委。", + "rank": "下签" + }, + "一七七": { + "answer": "虽有才华却遭埋没,须待有心人来提拔重用。", + "question": "白玉蒙尘,黄金埋土,久久光辉,也须人举。", + "rank": "中上签" + }, + "一七三": { + "answer": "大吉,所问诸事均能如愿,且喜事连连。", + "question": "事遂勿忧煎,春风喜自然,更垂三尺钩,得意获鳞鲜。", + "rank": "中上签" + }, + "一七九": { + "answer": "心中所愿终可实现,何必愁眉深锁?", + "question": "背后笑嘻嘻,中行道最宜,所求终有望,不必皱双眉。", + "rank": "中下签" + }, + "一七二": { + "answer": "要得到不易到手之物,非借不凡之力。", + "question": "欲得月中兔,须凭桃李拂,高山来接引,双喜照双眉。", + "rank": "中签" + }, + "一七五": { + "answer": "屋漏又遭连夜雨,船破偏遇当头风,衰透至极。", + "question": "乘病马,上危坡,防失跌,见蹉跎。", + "rank": "下下签" + }, + "一七八": { + "answer": "无论在团体、在家庭或社会,上下皆不相容,经年纠葛不清。", + "question": "上接不稳,下接不和,相缠相扰,平地风波。", + "rank": "中签" + }, + "一七六": { + "answer": "得意勿忘形,忘形恐有灾。", + "question": "两事已和同,轻舟遇便风,道迷人得意,歌唱急流中。", + "rank": "下签" + }, + "一七四": { + "answer": "要求功德圆满,但凭个人造化,机缘如何,所问诸事均如此。", + "question": "圆又缺,缺又圆,低低密密要周旋,时来始见缘。", + "rank": "下下签" + }, + "一三": { + "answer": "吉,留意三、五有关月日,或有殊遇、喜事。此签谋为有成,凡事有缘,求妻者得佳妇。求事者得佳事,谈笑中立可成,所谓吉人天相也。", + "question": "得意宜逢妇,前程去有缘,利名终有望,三五月团圆。", + "rank": "中签" + }, + "一三○": { + "answer": "此签大吉,所问诸事都很圆满,得此签者财运奇佳,本利相滚,财货盈仓。", + "question": "事团圆,物周旋,一来一往,平步青天。", + "rank": "中上签" + }, + "一三一": { + "answer": "衰运当头,即便慎言亦惹是非,故应少言,甚至不言。", + "question": "浅水起风波,平地生荆棘,言语虑参商,犹恐无端的。", + "rank": "中下签" + }, + "一三七": { + "answer": "或有烦心之事来临,内心忧闷无人谅解。", + "question": "荆棘生平地,风波起四方,倚栏惆怅望,无语对斜阳。", + "rank": "下签" + }, + "一三三": { + "answer": "吉祥,所问诸事,心意已决,即可达成,同时功成名就。", + "question": "心已定,事何忧,金鳞已上钩,功名一网收。", + "rank": "中上签" + }, + "一三九": { + "answer": "所问诸事,成败在于天时与地利。", + "question": "奇奇奇,地利与天时,灯花传信后,动静总相宜。", + "rank": "上上签" + }, + "一三二": { + "answer": "如处平顺之境遇,如有他乡旧知求己引荐则可为之,否则如所求过奢者,宜多虑。", + "question": "秋月云开后,薰风雨过时,若逢楚国旧知己,等闲一荐不须疑。", + "rank": "上签" + }, + "一三五": { + "answer": "凡事仅看表面自有不足,阻碍或能排除,祸事亦能成福庇。", + "question": "笑中生不足,内外见愁哭,云散月光辉,转祸当成福。", + "rank": "上签" + }, + "一三八": { + "answer": "大局安排已定,不必多作考虑。", + "question": "谋已定,事何忧,照月上重楼,云中客点头。", + "rank": "中下签" + }, + "一三六": { + "answer": "事情已安排妥当,全无冲突,若问姻缘,即可结合。", + "question": "檐前鹊噪正翩翩,忧虑全消喜自然,一人进了一人退,下梢还有好姻缘。", + "rank": "上签" + }, + "一三四": { + "answer": "凡事未可乐观。清明之中,虽无不了悟处,营求之後大有堪虑处,欲知下回分解,目前犹非其时,占者只可强自抑制,到时方能了了。", + "question": "意迷己不迷,事宽心不宽,要知端的信,犹隔两重山。", + "rank": "中上签" + }, + "一九": { + "answer": "平平,成败利钝淡然处之。此签主一切疑难,不问远近难易,均须自作主张,但求渗透玄机,不难迎刃而解,云中带笑看,得意时也。", + "question": "不远不近,似易似难,等闲一事,云中笑看。", + "rank": "上上签" + }, + "一九○": { + "answer": "单办一项行业、活动或进行一件事,多力不从心,若有多人相助,则望可成。", + "question": "事迷心不迷,事宽心不宽,一场欢喜会,不久出重关。", + "rank": "中下签" + }, + "一九一": { + "answer": "得此签者,诸事不宜冒进,宜于天时、地利、人和俱备之后再行动。", + "question": "夜半渡无船,惊涛恐拍天,月斜云淡处,音信有人传。", + "rank": "中上签" + }, + "一九七": { + "answer": "所问诸事,处于进退两难之境,须相关诸人上下一心,始有成功之望。", + "question": "进不安,退不可,上下相从,明珠一颗。", + "rank": "中签" + }, + "一九三": { + "answer": "所问诸事一向稳妥顺利,日后扩展,更属定 胜券。", + "question": "万里片帆转,波平浪不惊,行行无阻滞,远处更通津。", + "rank": "上签" + }, + "一九九": { + "answer": "众说纷纭,莫衷一是,事情进行一半,成为日后愁苦之源。", + "question": "雀噪高枝上,行人古渡头,半途不了事,日暮转生愁。", + "rank": "中下签" + }, + "一九二": { + "answer": "从事任何事,以谨慎机敏为上。", + "question": "事若羁留,人不出头,往来闭塞,要见无有。", + "rank": "上签" + }, + "一九五": { + "answer": "吉祥,无所不利。云中鹤月下人均有翛然世外之象,含饴鼓腹盛世之民也,果何所忧虑而不欢乐乎,占之者吉。", + "question": "鹤自云中出,人从月下归,新欢盈脸上,不用皱双眉。", + "rank": "中下签" + }, + "一九八": { + "answer": "一向事事称心,如今却不再如意,但是非可免。", + "question": "着着占先机,其中路不迷,目前无合意,乍免是和非。", + "rank": "下签" + }, + "一九六": { + "answer": "具有耐心,任何事均可成,不必怀疑。", + "question": "深潭鱼可钓,幽谷鸟可罗,只用久长心,不用生疑惑。", + "rank": "中签" + }, + "一九四": { + "answer": "此签对告老退休者,颇合其解,如问他事,则属有惊无险之局,刻下尚难抽身。", + "question": "身历惊涛,东风便好,太平身退,目下还早。", + "rank": "中下签" + }, + "一二": { + "answer": "诸事暂且打住,免有失误,后悔莫及。此签不宜妄想,只可谨守避祸,以免惹事招非,否则动则得咎,悔之晚矣。", + "question": "神黯黯,意悠悠,收却线,莫下钩。", + "rank": "中下签" + }, + "一二○": { + "answer": "所问诸事处在急于解决却未能解决之状况,不过最后终能渡过难关。", + "question": "事未宽,心不安,疑虑久,始安然。", + "rank": "中上签" + }, + "一二一": { + "answer": "终年碌碌营钻,每得虚有其表之名位,但等秋后(或中年以后)将时来运转。", + "question": "虚名虚位久沈沈,禄马当求未见真,一片彩云秋后至,去年风物一时新。", + "rank": "中签" + }, + "一二七": { + "answer": "遇事小心仔细,否则有招致横祸之可能。", + "question": "虎伏在路途,行人莫乱呼,路旁须仔细,灾祸自然无。", + "rank": "中下签" + }, + "一二三": { + "answer": "大吉大利,所问诸事均得圆满达成,更能得锦上添花之美。", + "question": "明月全圆,颜色欣然,风云相送,和合万年。", + "rank": "下签" + }, + "一二九": { + "answer": "得此签者,所谋之事于闲散自在中,不期然而有所成。", + "question": "东边事,西边成,风物月华明,高楼弄笛声。", + "rank": "中下签" + }, + "一二二": { + "answer": "成败得失,莫不缘于因果回圈之定数,不必强求。", + "question": "止止止,有终有始,似月如花,守成而已。", + "rank": "上签" + }, + "一二五": { + "answer": "居上者倨傲、偏狭,居下者离心,最后关键时刻,招致失败。", + "question": "居下不亲上,人心易散离,事机终失一,凡百尽成灰。", + "rank": "中下签" + }, + "一二八": { + "answer": "不吉,如问事业,纠纷不断,如问亲情友情婚姻,则神离而貌亦不合,进退小心。", + "question": "和不和,同不同,翻云覆雨几成空,进退须防终少功。", + "rank": "中下签" + }, + "一二六": { + "answer": "得此签者,时运欠畅,有志未伸,须明提携之人,前途始有望。", + "question": "兀兀尘埃久待时,幽窗寂静有谁知,若逢青紫人相引,财利功名自可期。", + "rank": "中上签" + }, + "一二四": { + "answer": "得此签者,即将成婚,或已成婚,双方情投意合生活美满,如问合伙,亦可大发。", + "question": "宝镜新,照两人,心中结,合同心。", + "rank": "上上签" + }, + "一五": { + "answer": "一切期待,均有可得,但须再等待一段时间。此签沉滞已久,困而将亨之象。然亦必须梅花初放,始得好消息,占之者宜稍安勿躁。", + "question": "意在闲中信未来,故人千里自徘徊,天边雁足传消息,一点梅花春色回。", + "rank": "中下签" + }, + "一五○": { + "answer": "时机已逝,时光已老,欲图大事,已不可能。", + "question": "大事恐难图;残花不再鲜。", + "rank": "下下签" + }, + "一五一": { + "answer": "好事多磨。主谗人高张,贤士无名荣辱升沉,莫谓天道不公,须知人事靡定也,月既缺矣又灭怀光,占之者可以知所儆也。", + "question": "莫道事无讹,其中进退多,桂轮圆又缺,光彩更揩磨。", + "rank": "中下签" + }, + "一五七": { + "answer": "得此签者注定显达,但需注意积德,否则将很快失去一切。", + "question": "贵客自相亲,功名唾手成,获金须积德,仰望太阳升。", + "rank": "下签" + }, + "一五三": { + "answer": "不必操之过急,须仰人相助,或有所成。", + "question": "事称应有忌,未为恐先踬,欲往且迟迟,还须借势力。", + "rank": "中上签" + }, + "一五九": { + "answer": "所问之事或人,如天心之月,皎洁无垢,非黑云所能遮掩。", + "question": "狂风吹起墨云飞,月在天心遮不得,闲时无事暂相关,到底依然无克剥。", + "rank": "下签" + }, + "一五二": { + "answer": "有耐心、恒心,最后终能如愿。", + "question": "莫叹事迟留,休言不到头,长竿终入手,一钓上金钩。", + "rank": "中上签" + }, + "一五五": { + "answer": "所问诸事于开始非常不顺,命中有贵人相助,事情得以重整。", + "question": "鼎折足,车脱辐,有贵人,重整续。", + "rank": "中下签" + }, + "一五八": { + "answer": "目前机运欠佳,须与知心友朋共事,庶几无患。", + "question": "平地起波澜,所求事日难,笑谈终有忌,同心事觉欢。", + "rank": "中下签" + }, + "一五六": { + "answer": "得此签者,恐有诉讼,或与人订约始终无法谈拢,亦或与人长时间有口舌之辩。", + "question": "参详言语,波涛扬沸,事久无伤,时间不利。", + "rank": "下签" + }, + "一五四": { + "answer": "塞翁失马,焉知非福,有时这样也不对,那样也不对,合在一起却带来好运。", + "question": "足不安,舆不安,两两事相得,忧来却又欢。", + "rank": "中上签" + }, + "一八": { + "answer": "不利,结局恐难有望。此签主患得患失,如驽马恋栈豆,无果决之作为,故枉费心机,徒取烦恼也。", + "question": "心戚戚,口啾啾,一番思虑一番忧,说了休时又不休。", + "rank": "中签" + }, + "一八○": { + "answer": "此签指一对恋人,因云山相阻,相思成疾,或谓,一人命运孤苦,事多伤感。", + "question": "憔悴无人问,林间听杜鹃,一声山月笛,千里泪涓涓。", + "rank": "中签" + }, + "一八一": { + "answer": "此签如专就宦途而言,诚属上上大吉,可谓官运亨通,青云直上。", + "question": "菱荷香里受深恩,桂魄圆时印绶新,从此威名山岳重,光辉直上位丝纶。", + "rank": "中签" + }, + "一八七": { + "answer": "莫为意中人或原留之地恋恋不舍,而误未来大事,不如早去为妙,免生祸乱。", + "question": "休眷恋,误前程,终闹乱,出门庭。", + "rank": "中签" + }, + "一八三": { + "answer": "此签示人,若三心二意去做一件事,出于勉强,则一动不如一静。", + "question": "欲行还止,徘徊不已,动摇莫强,得止且止。", + "rank": "中下签" + }, + "一八九": { + "answer": "得此签者,恐有幻想之习,应即改之。", + "question": "渴望梅, 画饼,漫劳心,如捉影,遇虎龙,方可省。", + "rank": "上上签" + }, + "一八二": { + "answer": "任何事均不得其时,尤其最近一月内,须防有所阻碍,诸事稍慢,等待转机。", + "question": "花落正逢春,行人在半程,事成还不就,索绊两三旬。", + "rank": "上签" + }, + "一八五": { + "answer": "总想换个新环境或工作,然却却不知如何着手,日后或有机运,目下尚不乐观。", + "question": "梦里说关山,波深下钓难,利名终有望,目下未开颜。", + "rank": "下签" + }, + "一八八": { + "answer": "大吉。", + "question": "万里波涛静,一天风月闲,利名无阻隔,行路出重关。", + "rank": "中上签" + }, + "一八六": { + "answer": "此签属机运亨通之签,尤对谋事、创业者而言。", + "question": "三箭开云路,营求指日成,许多闲口语,翻作笑歌声。", + "rank": "中上签" + }, + "一八四": { + "answer": "所问诸事,虽未圆满解决,但必能安然无虞,若遇龙(龙年或属龙之人)自有吉兆。", + "question": "心下事安然,周旋尚未全,逢龙还有吉,人月永团圆。", + "rank": "中下签" + }, + "一六": { + "answer": "得此签者,不合者必复合。同舟共济,出门有功,占者不可损人利己,不可惟我独尊,否则虎头蛇尾无断金之利。", + "question": "心和同,事知同,门外好施功,交加事有终。", + "rank": "中上签" + }, + "一六○": { + "answer": "独处深思,总觉不悦,若能眼光放远,自然无忧。", + "question": "人倚楼,许多愁,澹然进步,事始无忧。", + "rank": "下签" + }, + "一六一": { + "answer": "心志专一始能受到重视,略得提携即可步入佳境。", + "question": "一点着阳春,枯枝朵朵新,志专方遇合,切忌二三心。", + "rank": "中下签" + }, + "一六七": { + "answer": "异人指点,凡事顺利,事成日在三秋后。三秋:三年,秋季三个月,或秋季三个月。", + "question": "大事可成功,有益还无咎,云中执鞭人,报在三秋后。", + "rank": "上上签" + }, + "一六三": { + "answer": "将得手之机会或财物,由于条件不济,力量不足,无法承受,须再加努力。", + "question": "鱼上钩,丝纶弱,收拾难,力再着。", + "rank": "中上签" + }, + "一六九": { + "answer": "所问之事颇难如愿,须待天时。", + "question": "遍书前后事,艰险往来难,若得清风便,扁舟过远山。", + "rank": "上签" + }, + "一六二": { + "answer": "主困而後亨,剥而始复,初为云雾所障忧患频仍,终乃天日重开,门路广大,人但自求多福,不患人之不己知,占者毋自懈亦无自馁。", + "question": "道路迢遥,门庭闭塞,雾拥去兮,云开见日。", + "rank": "中下签" + }, + "一六五": { + "answer": "凡猜疑之事,不可冒然尝试,须再三思考探求真相,方作决定,免乐极生悲。", + "question": "疑疑疑,一番笑罢一番悲,落红满地无人扫,独对西风怅黛眉。", + "rank": "中签" + }, + "一六八": { + "answer": "事情已到穷途末路,想有转机亦难,惟亦不必过于颓丧,能保性命即属庆幸。", + "question": "桑榆催暮景,缺月恐难圆,若遇刀锥客,方知喜自然。", + "rank": "中上签" + }, + "一六六": { + "answer": "与其在一个意见分歧不合之团体里,不如及早退出,另创局面。", + "question": "上下不和同,劳而未有功,出门通大道,从此保初终。", + "rank": "中签" + }, + "一六四": { + "answer": "得此签者,平时乐于助人,故人际关系良好,事事均如意。", + "question": "相引更相牵,殷勤喜自然,施为无不利,愁事转团圆。", + "rank": "上签" + }, + "一四": { + "answer": "趋吉避凶人之常情,若一旦遇变故,而巧於趋避非惟自问不安,即天人亦不容之。人事蹉跎故戒之者深矣,占者当不避艰险勉持危局。", + "question": "鼎沸起风波,孤舟要渡河,巧中却藏拙,人事转蹉跎。", + "rank": "下下签" + }, + "一四○": { + "answer": "所问诸事均在虚无飘渺中。", + "question": "遇不遇,逢不逢,月沈海底,人在梦中。", + "rank": "上签" + }, + "一四一": { + "answer": "所耽忧之事均属子虚乌有,很快就能真相大白。", + "question": "暗中防霹雳,猜虑浑无实,转眼黑云收,拥出扶桑日。", + "rank": "下下签" + }, + "一四七": { + "answer": "不可浪费,遇良机时始能大展鸿图。", + "question": "可蓄可储,片玉寸珠,停停稳稳,前遇良图。", + "rank": "中下签" + }, + "一四三": { + "answer": "不吉之兆,得此签者处于公私纷繁,困扰重重之境。", + "question": "堪叹外边忧,更嗟门里闹,意绪更牵缠,心神亦颠倒。", + "rank": "下下签" + }, + "一四九": { + "answer": "得此签者有心意不专,操之过急之毛病,未改之前难有成就。", + "question": "一心两事,一事两心,新花枯树,直待交春。", + "rank": "下下签" + }, + "一四二": { + "answer": "此签今人问卜,不易作作妥贴解述,大意为立功异邦,归享盛名。", + "question": "利在中邦出战时,一番获馈在王庭,凤衔丹诏归阳畔,得享佳名四海荣。", + "rank": "上签" + }, + "一四五": { + "answer": "吉祥,化险为夷,若遇贵人,将可发迹。(贵人或可注意姓名有草字头者)。", + "question": "遇险不须忧,风波何足忌,若遇草头人,咫尺青云路。", + "rank": "中签" + }, + "一四八": { + "answer": "早给子女适切教导,可望使其得到贵人相助,并实现愿望。", + "question": "小子早趋庭,青云久问程,贵人来助力,花谢子还成。", + "rank": "中上签" + }, + "一四六": { + "answer": "心情纷乱,办事虑深,时运犹待新春,旅外慎防不测,婚姻出现暗礁。", + "question": "船棹中流急,花开春又离,事宁心不静,惹起许多疑。", + "rank": "中下签" + }, + "一四四": { + "answer": "如问机构内之事,则虽风波重重,终能安然,问家务事,因妇女高妙,亦安。", + "question": "一重山一重水,风波道坦然,壶中有别天。", + "rank": "下签" + }, + "七": { + "answer": "应机警应变,始能左右逢源。人情险巇,世态炎凉,然能拿定方针随机应变,亦识时务之俊杰也,占得此签当无咎。", + "question": "君须悟,勿误疑,有平路,任驱驰,随时变易,件件碱宜。", + "rank": "中下签" + }, + "七○": { + "answer": "为人追求真善美方为正途,凡事必以始终一贯精神为之。", + "question": "美有堪,堪有美,始有终,终有始。", + "rank": "中下签" + }, + "七一": { + "answer": "所问诸事尚在虚无飘渺间,当前处境未开,心绪至为郁闷,情境苍茫。", + "question": "湖海悠悠,孤舟浪头,来人未渡,残照山楼。", + "rank": "中下签" + }, + "七七": { + "answer": "所问之事,自己心余力绌,无法独力完成,但会有外力来助,结果仍称圆满。", + "question": "心有余,力不足,倚仗春风,一歌一曲。", + "rank": "下下签" + }, + "七三": { + "answer": "此签大吉,凡谋事、创业必有望,且连获成功,尤其逢‘六’数,更具喜色也。", + "question": "江海悠悠,烟波下钩,六鳌连获,歌笑中流。", + "rank": "中上签" + }, + "七九": { + "answer": "人、事问题,均了断并圆满解决,有关物则否,得此签,恐有财务纠纷并涉讼。", + "question": "事了物未了,人圆物未圆,要知端的信,日影上琅。", + "rank": "中下签" + }, + "七二": { + "answer": "无事须当有事,有事更加防范,得此签者须注意门户以防窃,谨言慎行免招祸。", + "question": "深户要牢扃,提防暗里人,莫言无外事,纵好定遭。", + "rank": "中上签" + }, + "七五": { + "answer": "得意之时勿忘形,失败之后勿失志,不行歪路,心境自然安适。", + "question": "一得一虑,退后欲先,路通大道,心自安然。", + "rank": "中下签" + }, + "七八": { + "answer": "问健康,应多运动,问事业,则现危机,需多所奔走,问婚姻,处倦怠状,需努力。", + "question": "身不安,心不安,动静两三番,终朝事必叹。", + "rank": "中下签" + }, + "七六": { + "answer": "机遇欠佳时,人在家中坐,祸从天上来,行运转佳时,一切左右逢源,得心应手。", + "question": "难难难,忽然平地起波澜,易易易,谈笑寻常终有望。", + "rank": "下下签" + }, + "七四": { + "answer": "三心二意,有违常理,动弹不得,得此签者,所问诸事均呈胶着状态。", + "question": "欲济未济,欲求强求,心无一定,一车两头。", + "rank": "中上签" + }, + "三": { + "answer": "惕励不可好高骛远,目前情况不理想。切记吃得苦中苦,方为人上人。得此签者务须猛着粗鞭,力求上进。倘自为有恃无恐,则不进反退也。", + "question": "长安花,不可及,春风中,马蹄疾,急早加鞭,骤然生色。", + "rank": "中上签" + }, + "三○": { + "answer": "攀权附贵者宜回头,顶天立地重新做人,否则不得善终。力戒躁动勉守安静,毋贪非分毋逞妄想,君子占之以是福,小人占之以是祸。", + "question": "缘黄阁白了头,毕竟成何济,不如趁此精神,犹好买些真气。", + "rank": "中下签" + }, + "三○○": { + "answer": "大吉大利,凡事左右逢源,得心应手。", + "question": "三天曾结社,四海尽知名,长骑骏马,直入天庭。", + "rank": "中下签" + }, + "三○一": { + "answer": "命中有吉人相助。邂逅相逢,一见如故,倾心吐胆,古道照人,占者能於无意中获交良友。", + "question": "闲来夫子处,偶然遇一人,童颜鹤发,笑里生春。", + "rank": "中上签" + }, + "三○七": { + "answer": "感应签,求职谋事创业等,遇龙年生者可得其助,迁居进宅等,逢678之日期较顺。", + "question": "龙生头角,将沛甘霖,六七八早,好济苍生。", + "rank": "中签" + }, + "三○三": { + "answer": "浊者自浊,清者自清,吾人须洁身自好,以处混乱之险恶世道。", + "question": "汉水无情,蜀水澄清,黄河滚滚,四处烟尘。", + "rank": "中签" + }, + "三○九": { + "answer": "寓意有二:一分耕耘,一分收获,已为某事劳心尽力,但须待时机及人助方有成。", + "question": "曾把树栽,也要待春来,东风袅袅,开遍花街。", + "rank": "中签" + }, + "三○二": { + "answer": "悠闲自在态度追求理想者,际遇最佳,经过二三年之经营,即可有成。", + "question": "闲云野鹤望东行,惟有乡人便是知音,经营布置两三春,联街灯火后,锦帆前程。", + "rank": "中上签" + }, + "三○五": { + "answer": "好花不常开,一旦处于绝佳之境,宜淡然处之,并另谋良图。", + "question": "此处滋味浓,浓艳不耐久,何如谈笑生风,倒好东奔西走。", + "rank": "中下签" + }, + "三○八": { + "answer": "正不胜邪,理不胜数,一生三死,天道昭然,占之者正不必强自纷争也。", + "question": "太白现西南,龙蛇相竞逐,龙自飞上天,蛇却被刑戮。", + "rank": "中签" + }, + "三○六": { + "answer": "所问诸事可能受到小人干扰破坏,与其争论无益,避之则吉。", + "question": "这里有小人,切莫稍留停,忙打点,好起行,日月如逝勿久存。", + "rank": "中上签" + }, + "三○四": { + "answer": "求签者暂遇挫折,目前尚在守时待运阶段,待时机成熟。", + "question": "潜龙已受困,尚不见云兴,伫看云四合,飞去到天庭。", + "rank": "中上签" + }, + "三一": { + "answer": "平平,创业须结伴。此签谋为始难,不免阻滞,久後还得顺利,只须当机立断,切莫因循自误,致老大徒伤悲也。", + "question": "离别间,虽不易,同伴行,犹不滞,早早起程,免他失意。", + "rank": "中下签" + }, + "三一○": { + "answer": "此签劝人要能知足,并把握光阴享受人生。", + "question": "四十余年苦已深,而今汝乐度光阴,莫筹论,恩爱尚多欢喜事,惜甚青春,不减青春。", + "rank": "中签" + }, + "三一一": { + "answer": "所问诸事做法上恐有问题,应即改弦更张另作安排。", + "question": "三冬足,文艺精,到头处,亦成冰,急急回首,勿误前程。", + "rank": "中下签" + }, + "三一七": { + "answer": "不经意引发之灾难总有克制之法,刻意策划之事端,往往一发不可收拾。", + "question": "大火炎炎,宜水相济,宝鼎丹成,掀天揭地。", + "rank": "中下签" + }, + "三一三": { + "answer": "得此签者有以逸待劳,坐享其成之机运。", + "question": "耕牛伏 ,辟土开疆,坐看收获,黍稷稻梁。", + "rank": "中签" + }, + "三一九": { + "answer": "做任何事,均要抱着积极态度不懈不怠全力以赴,若稍有停顿,将难以收拾。", + "question": "十二时中,紧急炼着,一刻少延,无处下脚。", + "rank": "中上签" + }, + "三一二": { + "answer": "所问之事情况怪异,应提防生变,以免坏了大事。", + "question": "奇怪奇怪,前番来了,今番又来,谨慎提防,勿被弄坏。", + "rank": "中签" + }, + "三一五": { + "answer": "此签以雏鸟喻人学艺未精不知天高地厚,初入社会难免饱受波涛翻滚之苦。", + "question": "雏鸟飞高,出谷迁乔,龙神牙爪,变化海岛。", + "rank": "下签" + }, + "三一八": { + "answer": "所问之事宜以快刀斩乱麻方式处理,以杜后患。", + "question": "铁索一条,未把孤舟系,金刀一下,早把头落地。", + "rank": "中下签" + }, + "三一六": { + "answer": "得此签者恐有不吉事情临头,并因而尝到人情淡薄之滋味。", + "question": "吉吉吉,寻常一样窗前月,凶凶凶,有了梅花便不同,含笑向东风,人情不比旧时浓。", + "rank": "中上签" + }, + "三一四": { + "answer": "得此签者功勋卓着,必为行业中顶尖人物,所问诸事无不卓然有成。", + "question": "腰下佩青萍,步入金銮殿,覆护三山,千锤百链。", + "rank": "中上签" + }, + "三七": { + "answer": "须以德化人。此签主君子贤人,名望所归,即使众口铄金,终不能埋没其真材实学,归元朝洞,正以喻泰斗之足以令人景仰也。", + "question": "万马归元,千猿朝洞,虎伏龙降,道高德重。", + "rank": "中下签" + }, + "三七○": { + "answer": "历尽辛苦,而步入舒适称意之环境,须饮水思源不可忘本。", + "question": "过羊肠,入康庄,五陵裘马,当思故乡。", + "rank": "中下签" + }, + "三七一": { + "answer": "处理紧急情况,不能急切,须防后患。", + "question": "火遭水克,火灭其光,水势滔滔,源远流长。", + "rank": "中上签" + }, + "三七七": { + "answer": "天生万物必有用,寓意人万勿连猪狗都不如。", + "question": "一头猪,可祭天地,虽丧身,亦算好处。", + "rank": "中签" + }, + "三七三": { + "answer": "天下本无事,庸人自扰之,或谓‘苦恼皆因强出头’。", + "question": "世界似清宁,不知辞已休,打叠要小心,须防遭火 。", + "rank": "中上签" + }, + "三七九": { + "answer": "万事俱备,只欠东风,如今东风来了,自是令人开怀之事。", + "question": "东风来,花自开,大家喝采,畅饮三杯。", + "rank": "中上签" + }, + "三七二": { + "answer": "得签人已颇有名望,且乐于交际应酬,往来多为高雅之士。", + "question": "东阁筵开,佳客自来,高歌唱和,展挹舒怀。", + "rank": "上签" + }, + "三七五": { + "answer": "顺其自然,把握有利机运去求发展,才会有指望。", + "question": "山上有古松,亭亭冲汉斗,干老枝更长,天地生荣久。", + "rank": "中签" + }, + "三七八": { + "answer": "此签劳心不如劳力,劳心多愁思,劳力多好梦,占之者须熟读流水不腐、户枢不蠹二语。", + "question": "与其日营营,何如夜忖忖,日里多劳形,夜间却安稳。", + "rank": "中上签" + }, + "三七六": { + "answer": "对于挑拨离间之闲言杂语,不去理会,一切自有天数,冥冥之中报应不爽。", + "question": "诽谤言,勿计论,到头来,数已定,碌碌浮生,不如安分。", + "rank": "中上签" + }, + "三七四": { + "answer": "要达崇高目标,须有超人本事,并能借机乘势。", + "question": "跳龙门,须激浪,雷电轰轰,踊跃万丈。", + "rank": "中上签" + }, + "三三": { + "answer": "平平。苦未尽甘已来,风平浪静,直上青云。占此签者诸事利吉,不用忧虑。", + "question": "历过波涛三五重,谁知浪静又无风,须教明达青云路,用舍行藏不费功。", + "rank": "中签" + }, + "三三○": { + "answer": "名利与己与缘,不必在凶险世途上与人争夺,安份守己勤苦渡日最宜。", + "question": "世道多荆棘,人情每用嗟,利名如有路,勤苦逐生涯。", + "rank": "中上签" + }, + "三三一": { + "answer": "跋山涉水出门远行,均属不利,若违拗命运一意孤行,往往会遇怨怼非议事。", + "question": "山穷路转迷,水急舟难渡,万事莫强为,出处遭研妒。", + "rank": "中上签" + }, + "三三七": { + "answer": "谋事在人,成事在天。对一切事物,莫过于贪婪奢求。", + "question": "万事不由人计较,一生尽是命安排,莫疑猜,命里有时总有分,何须碌碌混尘埃,休哉!", + "rank": "中上签" + }, + "三三三": { + "answer": "得此签者如为女性,必美且慧,远近赞美,如为男性则以品德高贵而受颂扬。", + "question": "一朵花枝艳更芳,清香馥郁透兰房,时风吹送终成笑,好句筵前进几觞。", + "rank": "中下签" + }, + "三三九": { + "answer": "对女色之困惑,须加以警惕,不可贪恋也,否则将有耗虚之虞。", + "question": "两女一夫,上下相祛,阴气乘阳,用是耗虚。", + "rank": "中下签" + }, + "三三二": { + "answer": "时运不佳,未来日子风险更多,得此签者,须多加谨慎提防为宜。", + "question": "时边多艰,战战兢兢,戒谨恐惧,如履薄冰,须识前程危与险,一笼风里一枝灯。", + "rank": "中下签" + }, + "三三五": { + "answer": "此签甚佳,凡事亨通,如寻物得、谋事成、求偶佳、经商利、建屋吉。", + "question": "远涉波涛一叶舟,而今始得过滩头,年来心事才成就,屈指从前多可忧。", + "rank": "中上签" + }, + "三三八": { + "answer": "所问诸事均不顺遂,因而被重重烦忧困住,妇女得此签者宜防情感生活有变。", + "question": "一片忧心未肯休,花逢春雨艳难留,得意归休,失意归休,仙家只此一筹谋。", + "rank": "中下签" + }, + "三三六": { + "answer": "得签者久受重用,生活富裕,如起异心或心生骄怠,则可能失去一切。", + "question": "受君之禄,久降祯祥,盈而不覆,守之乃昌,毋怠毋骄,永保安康。", + "rank": "上上签" + }, + "三三四": { + "answer": "一人做任何事,具有恒心、毅力,则其成功机会较大。", + "question": "自从持守定,功在众人先,别有非常喜,随龙到九天。", + "rank": "上签" + }, + "三九": { + "answer": "此签有大觉大悟,普渡众生之义。引人登彼岸,自身入仙班。言为人谋忠,己必不沉沦在下,行善事者,自获善报,百不失一。", + "question": "大肆放灵丹,救人行万千,到头登彼岸,渡过入仙班。", + "rank": "中上签" + }, + "三二": { + "answer": "不祥。顺利之来无永久,横逆之加难幸免,天在上为吉,水在下为凶,当逆来顺受,届以求伸,目下黑暗,久後亦当能光返照。", + "question": "乐之极忧将至,巽兑分明吉与凶,未能光大终幽暗,日落西山返照中。", + "rank": "中上签" + }, + "三二○": { + "answer": "当时机成熟,谜题即可轻易揭开,所有疑难均会得到答案。", + "question": "风起西南,红日当天,奇门妙诀,一掌能着。", + "rank": "中签" + }, + "三二一": { + "answer": "谨慎维护形象,以突破谣言扭曲,得此签者有招人忌怨、暗算之危。", + "question": "万籁无声际,一月正当空,忽被云遮掩,皓魄反朦胧。", + "rank": "中下签" + }, + "三二七": { + "answer": "得此签者将获佳婿,并因而使生命改观,荣华富贵享用不尽。", + "question": "豹变成文采,乘龙福自臻,赤身成富贵,事事得振新。", + "rank": "中上签" + }, + "三二三": { + "answer": "此签示人勿为小人群聚时之假像欺骗。", + "question": "众犬相聚,砺齿咬牙,摇头摆尾,只顾看家。", + "rank": "中下签" + }, + "三二九": { + "answer": "此签示人:家道富裕,宜安于现状,不必另起为官或经商之念。", + "question": "晓雨初晴映碧溪,重重春色上柴扉,黄金不尽家殷富,何必区区羡锦衣?", + "rank": "上签" + }, + "三二二": { + "answer": "得签者为人处事有‘曲过高和太寡’之情形,宜检讨修正。", + "question": "一个知音,却在天边等,切勿因循,静夜当思省。", + "rank": "中签" + }, + "三二五": { + "answer": "凡事一动不如一静,坚守本份相安无事,或寓有应严守机密勿使泄露意思。", + "question": "鼠伏穴,本自宁,一露首,猫即跟,扬威伸爪,鼠丧残生。", + "rank": "中下签" + }, + "三二八": { + "answer": "此签寓有‘道消魔长’之意,处此情况唯有谨慎或可保全。", + "question": "孤阳微兮,群阴溢兮,力既殚兮,将不可耄兮,真谨慎兮,宜可保兮。", + "rank": "中签" + }, + "三二六": { + "answer": "得此签者应切记斯言,不再忧心忡忡,终年劳碌而不读书。", + "question": "书中有女颜如玉,书中自有黄金屋,读尽五车书,志愿自能足,何必焦劳心中忙碌。", + "rank": "中上签" + }, + "三二四": { + "answer": "有的夫妻,妻强夫弱,得此签者有娶这种妻室之可能,婚后应重视恩义。", + "question": "妻前夫后一同行,好比先机兆已明,君若有情须切记,十年恩义莫忘心。", + "rank": "下签" + }, + "三五": { + "answer": "一向平顺,今突生险,惟必可过关。诸事迟滞,赖有智识定力,涉险济深,始得同登彼岸。", + "question": "行路难行路难,今日方知行路难,前程广大何足虑,琼力今朝度此滩。", + "rank": "上上签" + }, + "三五○": { + "answer": "历尽千辛万苦,如今终入佳境。", + "question": "巴到平安地,江山万里程,绿杨芳草处,风快马蹄轻。", + "rank": "上上签" + }, + "三五一": { + "answer": "时来运转,气势甚雄,做任何事均能顺利无比。", + "question": "雕鹗当秋势转雄,乘风分翼到蟾宫,荣华若问将来事,先后名声达九重。", + "rank": "上上签" + }, + "三五七": { + "answer": "此签临事须有决断,不可狐疑又须认准路径,不可分歧,如或不然,後患难免。", + "question": "思量一夜,不如打干一番,若还错,烦恼及肺肝。", + "rank": "中上签" + }, + "三五三": { + "answer": "举头三尺有神明,与人相处莫欺心,是非到头自分明。", + "question": "两人在旁,太阳在上,照汝一寸心,仙机曾否明。", + "rank": "中下签" + }, + "三五九": { + "answer": "对某件事能专心致志去做,收获必不同凡响。", + "question": "天念苦修人,终不落红尘,清心能见道,扰扰丧真灵。", + "rank": "中上签" + }, + "三五二": { + "answer": "小人得志,嚣张狂妄,但为时不长。", + "question": "鼠为患终宵不得宁,猫儿一叫几夜太平,人岂识如兽,其理甚分明。", + "rank": "中下签" + }, + "三五五": { + "answer": "未明,视所问事而定。行人走失,欲寻觅之,须依所指引处前去,自有下落,问失物亦然,占之者切莫迟徊。", + "question": "去到长安,东北转角,逢着天门,便有下落。", + "rank": "中上签" + }, + "三五八": { + "answer": "此签小挫不足虑,还须再接再厉如前坚守,若因而退缩,不惟前功尽弃,且为敌人所乘矣,占者须明此理。", + "question": "心细胆粗,可胜上将之任,勇往前行成败何必在心,胸中把持得定,敌人自能受困。", + "rank": "中签" + }, + "三五六": { + "answer": "机运不能坐等,要亲自向可能之处探寻,寻必有所得。", + "question": "徐步入天台,为听好消息,采药有仙童,洞府列春色。", + "rank": "上上签" + }, + "三五四": { + "answer": "若大丈夫怀才不遇,则深藏不露乃为上策。", + "question": "君子道消,小人道长,阴气郁郁,阳气不扬,如何如何,良贾深藏。", + "rank": "上上签" + }, + "三八": { + "answer": "般乐怠敖,失业之源。宴安耽毒,失时之本。行事须早,切莫因循。急起直追,攸往咸利。占得此签者飞黄腾达可为预贺。", + "question": "黄鹂报上林,春色鲜明,提鞭快着,马上速行程。", + "rank": "中签" + }, + "三八○": { + "answer": "知足常乐。此签主奉身俭约,心宽身宽,挥霍奢侈,神为之乱,占者以安贫为贵。", + "question": "疏食饮水,乐在其中,膏梁美味,反使心朦。", + "rank": "中下签" + }, + "三八一": { + "answer": "一分耕耘,一分收获。能勤苦在先,自得安乐於後,占之者遇事着着争先,勿步步落後,庶不负平生矣。", + "question": "黄牛辟土,大力开疆,西成时候,谷米盈仓。", + "rank": "上签" + }, + "三八三": { + "answer": "得签者可望取得通达之机缘,从此一帆风顺。", + "question": "九华山顶,紫气腾腾,异尽一舟,取去前行。", + "rank": "上上签" + }, + "三八二": { + "answer": "得此签者在平凡中力求不凡,即将有所成就。", + "question": "蛇可化龙,头角将出,平地一声雷,方显龙蛇力。", + "rank": "中上签" + }, + "三八四": { + "answer": "有错要知悔改,做事务必落实,心胸宽大,人生才有意义。", + "question": "人非孔颜鲜能无过,过而能改仍复无过,开花不足凭,结果方为准,放开怀抱意欣欣。", + "rank": "中上签" + }, + "三六": { + "answer": "春为万物更新之始,人得春气自有发旺景象,春曰无限好,言励志贵乘时也,曰宴琼林言结果必佳美也。占之者亟宜奋勉。", + "question": "春景明,春色新,春意傍水生,春天无限好,好去宴琼林。", + "rank": "上签" + }, + "三六○": { + "answer": "走错方向,用错方法,难望有成,应改弦更张,另设他法,或有成就一天。", + "question": "捕兕于渊,求鱼于山,从朝至暮,功负力捐,改弦易辙,庶可图全。", + "rank": "中上签" + }, + "三六一": { + "answer": "所问之事恐徒劳无功。", + "question": "手持一木鱼,沿街去化缘,不见徐公来,却遇一鸟去。", + "rank": "中签" + }, + "三六七": { + "answer": "做任何事要能适当其时,才会处处逢源,事事顺心。", + "question": "寻芳春日,适见花开,朵朵堪摘,枝枝可栽。", + "rank": "中上签" + }, + "三六三": { + "answer": "得此签者机缘奇佳,得遇贵人,因而飞黄腾达事事遂心,如问姻缘,可得佳人。", + "question": "骑玉兔,到广寒,遇嫦娥,将桂攀,满身馥郁,两袖馨香。", + "rank": "中上签" + }, + "三六九": { + "answer": "若干情况出乎常情之外,不能以常理处之,此时须求助于专门人才。", + "question": "虎出金榜,有勇亦何济,怎似山翁,非富犹有趣。", + "rank": "中下签" + }, + "三六二": { + "answer": "所有冲突已化解,障碍亦撤除,环境无比和谐,适宜做任何事。", + "question": "水火既济,阴阳相契,育物新民,参天赞地。", + "rank": "中上签" + }, + "三六五": { + "answer": "功夫到了,任何事均可以做成。", + "question": "炉中火,沙里金,功力到,丹鼎成。", + "rank": "上上签" + }, + "三六八": { + "answer": "所问之事,已出现祥瑞之兆,很快就有和谐局面出现。", + "question": "龙一吟,云便兴,冲霄直上,快睹太平,为文为武,君君臣臣。", + "rank": "中签" + }, + "三六六": { + "answer": "得此签者将有远行,并在当地遇知音,成家立业,赢得声名。", + "question": "此去万里程,却遇见知音,同心共济,大立勋名。", + "rank": "上上签" + }, + "三六四": { + "answer": "得此签者手法高明,待人处事八面玲珑,如有神道随行。", + "question": "一个神道,随尔去行,逢人说法,到处显灵。", + "rank": "上上签" + }, + "三四": { + "answer": "吉昌。暂时偃蹇终得大伸,宛如枯木逢春,又如山行忽得康庄,示人以偶然落魄,但居仁由义不患人之不知也。", + "question": "缺月又重圆,枯枝色更鲜,一条夷坦路,翘首望青天。", + "rank": "上上签" + }, + "三四○": { + "answer": "倦游归来,景物全非。旧主重逢衣食有恃,因人成事独立为难,占之者勿遽自立一帜也。", + "question": "双燕归南国,来寻王谢家,华堂春尽静,进此托生涯。", + "rank": "中下签" + }, + "三四一": { + "answer": "不吉,诸事不宜。诸事绝望灾戾重重,占病沉重占讼必凶,若求吉庆杳杳无期,惟修德可转危为安。", + "question": "命运蹇兮时违,灾殃及兮身疲,望皇天兮不我顾,嗟我亲兮病斯危。", + "rank": "下签" + }, + "三四七": { + "answer": "目前机运欠佳,事情进行缓慢,日夜 劳,来日运转,情况即可完全改观。", + "question": "马进徐行似有程,月沈西海日东升,运来何必劳心力,风送江湖万里清。", + "rank": "上签" + }, + "三四三": { + "answer": "因时运不济及自己过错,使得处境至为孤寂无助,应借助信仰力量以求自救。", + "question": "出温入寒,被薄衣单,去我慈航,难解横愆。", + "rank": "中签" + }, + "三四九": { + "answer": "一切纷争已息,今后行程应平稳无险,刻下经营多顺利,虽慢了些又何妨?", + "question": "风波今已息,舟楫遇安流,自此功名遂,何须叹白头。", + "rank": "上签" + }, + "三四二": { + "answer": "在他乡工作时意外得遇知音,事事顺遂,暂且不宜返乡。", + "question": "采药天台路转迷,桃花流水赋佳期,春风啼鸟多情思,寄语刘郎且莫归。", + "rank": "中下签" + }, + "三四五": { + "answer": "得此签者,恐终年在外奔波,受尽寂寥之苦,常起思乡之念。", + "question": "谁说故乡无滋味,飘零湖海在天涯,任咨嗟,中秋月隐春雨淋花,多少征人长忆家。", + "rank": "中上签" + }, + "三四八": { + "answer": "困厄之事临身,一时难以解除,惆怅难免,怨恨则不必。", + "question": "云横山际水茫茫,千里长途望故乡,蹇厄事来君莫恨,倚门惆怅立斜阳。", + "rank": "中下签" + }, + "三四六": { + "answer": "鼠年及羊年会有一举成功机会。", + "question": "云散月当空,牛前马后逢,张弓方抵御,一箭定全功。", + "rank": "上签" + }, + "三四四": { + "answer": "示人不可削足适屦,亦寓有‘满招损’之意。", + "question": "三升三石放在一斗,满而溢,子自得。", + "rank": "中签" + }, + "九": { + "answer": "命中得遇贵人相助,未婚男子可得佳侣,商人则应有主见,始能获利。然非积德修持,无此希望也。君子占吉,小人占凶。", + "question": "贵客相逢更可期,庭前枯木凤来仪,好将短事求长事,休听旁人说是非。", + "rank": "上签" + }, + "九○": { + "answer": "转机交运之兆,时下机运甚佳,所问大吉大利。", + "question": "云尽月当中,光辉到处通,路途逢水顺,千里快如风。", + "rank": "中下签" + }, + "九一": { + "answer": "激烈竞争中,需料敌如神,妥为布置以待敌来,赢得胜利后尚需妥善收拾战果。", + "question": "剑戟列山林,盗贼必来侵,败走擒搜定,封侯荫子孙。", + "rank": "下下签" + }, + "九七": { + "answer": "勉人及锋而试,毋自玩愒岁月,果能勇敢任事,艰难赴功,佳遇只在目前,占此者知机缘之失,间不容发,而各自策励也。", + "question": "报导上林,春色鲜明,提鞭快着,马上行程。", + "rank": "下下签" + }, + "九三": { + "answer": "人事变迁世情难测,可喜之中亦覆可惧,若有人暗中指点,始可扶摇直上,显其身手,惹勾连戒招摇也,其垂象微矣。", + "question": "拟欲迁而未可迁,提防喜处惹勾连,前途若得阴人引,变化鱼龙出大渊。", + "rank": "中上签" + }, + "九九": { + "answer": "得此签者,已功成名就,或者,目前从事者志趣不合,如今财力已丰,可以从已趣。", + "question": "打起平生志,西南好去游,腰缠十万贯,骑鹤上扬州。", + "rank": "上上签" + }, + "九二": { + "answer": "所问诸事宜向宽处打算,向远途作想,最后必能成功。", + "question": "岸阔水深舟易落,路遥山险步难行,蛇行自有通津日,月上天空分外明。", + "rank": "中上签" + }, + "九五": { + "answer": "世间悲欢无常,且悲事往往比喜事严重,常能将人击倒。", + "question": "喜未稳,悲已遭,大雨狂风吹古木,人人尽道不坚牢。", + "rank": "中上签" + }, + "九八": { + "answer": "人各有其不同安身立命之所及最适当行动时机,选择其他恐大不利。", + "question": "鼠入土穴,最可安身,日中不见,静夜巡行。", + "rank": "下下签" + }, + "九六": { + "answer": "得此签者,可望遇知音,交至友,得生死相许之配偶。", + "question": "可以寄百里之命,可以托六尺之孤,钟期既遇毋迟误。笑呼呼,他乡聚首,各自乐康和。", + "rank": "中下签" + }, + "九四": { + "answer": "二人合作成功前互疑,惟风度尚在,问婚姻状况,求嗣不得而猜疑,后喜获一女而解。", + "question": "一人去,一人入,清风明月两相猜,获得金鳞下钓台。", + "rank": "中上签" + }, + "二": { + "answer": "神护签,言行循规蹈矩,事业上必有贵人相助,婚姻得人,健康亦佳。谋望一切必可顺遂。官吏占之,有远迁之喜。士人占之,有功名之庆。", + "question": "地有神,甚威灵,兴邦辅国,尊主庇民。", + "rank": "上上签" + }, + "二○": { + "answer": "栽种不得其时,去向漂流不定,远行旅程不顺,家庭亦有风波。此签占事业不利,疾病不定,婚姻无望,出行所如軗阻,讼事凶多吉少。", + "question": "桃李谢春风,西飞又复东,家中无意绪,船在浪涛中。", + "rank": "中上签" + }, + "二○○": { + "answer": "得此签者,时运特佳,做任何事都会有意外之收获。", + "question": "凿石得玉,淘沙得珠,眼前目下,何用踌躇。", + "rank": "中签" + }, + "二○一": { + "answer": "好景不长,好花不再,避免小人挑拨坏事,幸灾乐祸。", + "question": "无端风雨催春去,落尽枝头桃李花,桃畔有人歌且笑,知君心事乱如麻。", + "rank": "中下签" + }, + "二○七": { + "answer": "吉,婚事笑谈中说定,高升喜讯已在半途,双喜临门人生至乐。", + "question": "和合事,笑谈成,喜音在半程,平步踏青云。", + "rank": "中上签" + }, + "二○三": { + "answer": "问卜之人处于小人当道,所负责之事又非内行,虽有贤女子相助,依然难成。", + "question": "门外事重叠,阴人多遇合,贤女虽助巧,渺渺终难洽。", + "rank": "中签" + }, + "二○九": { + "answer": "此签前段昌吉喜庆,事多有成,   末句寓有兄弟 墙之意,或兄弟中,恐有折损。", + "question": "门外好音来,生涯应有庆,名利有更迁,雁行终折阵。", + "rank": "中签" + }, + "二○二": { + "answer": "谋望有成,欣然色喜,名利所在无不遂也,一如木得春气,有发生长养之机,占之者吉。", + "question": "阆苑一时春,庭前花柳新,声传好信息,草木尽欣欣。", + "rank": "中上签" + }, + "二○五": { + "answer": "暗去明来,明去暗来,冥冥之中自有定数。", + "question": "暗去有明来,忧心事可谐,终须成一笑,目下莫疑猜。", + "rank": "下签" + }, + "二○八": { + "answer": "大不吉祥,诸事不宜,诸对婚姻论断,则尤不相宜,恐有劳燕分飞之虞。", + "question": "花残月缺,镜破钗分,休来休往,事始安宁。", + "rank": "中上签" + }, + "二○六": { + "answer": "好事成双,得此签者,正直、高贵,受天之恩宠,事事如意。", + "question": "宝镜无尘染,金貂已剪裁,也逢天意合,终不惹尘埃。", + "rank": "中签" + }, + "二○四": { + "answer": "此签主得贤妻,家庭和谐,生活幸福,亦主妇女有喜。", + "question": "事有喜,面有光,终始好商量,壶中日月长。", + "rank": "下签" + }, + "二一": { + "answer": "须费尽九牛二虎之力始克有成。此签主历尽难险,方能告成,绝地逢生。毕竟柳暗花明又一村,故贫困所以玉汝,忍性所以有为。", + "question": "一水远一水,一山旋一山,水穷山尽处,名利不为难。", + "rank": "上上签" + }, + "二一○": { + "answer": "变起仓悴,即将达成之希望亦被预料不到之状况破坏无遗。", + "question": "万里好江山,风沙尽日间,已吞钩上饵,何必遇波澜。", + "rank": "中上签" + }, + "二一一": { + "answer": "所期盼之事或人,已指日可待。", + "question": "双燕衔书舞,指日一齐来,寂寞淹留客,从兹下钓台。", + "rank": "中下签" + }, + "二一七": { + "answer": "所问事必成,但须防后患,如得财富将有人强分,得配偶则三者纠缠不放。", + "question": "有一人,获一鹿,事团圆,门外索。", + "rank": "中上签" + }, + "二一三": { + "answer": "用人应用有志节及才干之人,并放手让他施展,很快即有成就。", + "question": "用之则行,舍之则藏,一骑出重关,佳音咫尺间。", + "rank": "中签" + }, + "二一九": { + "answer": "佳,月钩风线君子而隐於渔者也,举网烟波锦鳞易见,随遇而安也,占此者宜退居,不利见大人。", + "question": "新月为钩,清风作线,举网烟波,锦鳞易见。", + "rank": "上签" + }, + "二一二": { + "answer": "所问诸事看似高深莫测,只要不畏惧,终有明白一天。", + "question": "望去几重山,高深渐可攀,举头天上看,明月在人间。", + "rank": "中上签" + }, + "二一五": { + "answer": "此签若对男女间相恋、婚姻、结 等,恐属大不利,如问他事,亦波折重重。", + "question": "安坦路平夷,云中一雁飞,桃花逢骤雨,水畔女频啼。", + "rank": "上签" + }, + "二一八": { + "answer": "不祥。主出不利,诸事不顺交易折本,家业凋零,作速退守,尚恐不保妄意进行,更生不测占者戒之。", + "question": "汝往无攸利,花开又及秋,严霜物荐至,退步不存留。", + "rank": "下签" + }, + "二一六": { + "answer": "谨防家人失和,手足互残,并防身边亲人成仇家,小心翼翼,终可有成。", + "question": "门内起干戈,亲仇两不和,朱衣临日月,始觉笑呵呵。", + "rank": "中上签" + }, + "二一四": { + "answer": "行善积德,泽被乡里,将来必有好报。", + "question": "积德施功有子孙, 牛祭神及西邻,功名两字成全日,回首山河万物新。", + "rank": "中签" + }, + "二七": { + "answer": "不可固执己见。而若智珠在抱,成竹在胸,不受他人愚,不遭世人迷,见错自不错,真人自有真,占此签者,自决则吉,从人则凶。", + "question": "莫怪我见错,心性自成屙,偏僻不通心,真人却不魔。", + "rank": "中上签" + }, + "二七○": { + "answer": "过不求人之生活,身体虽劳,精神却愉快。", + "question": "躬耕陇亩,形神似劳,无拘无系,其乐陶陶。", + "rank": "中上签" + }, + "二七一": { + "answer": "大祸临头,心被鬼怪的病淹没而纠缠不放,除非有‘金、羊’有关事物来救。", + "question": "祸来见鬼,鬼病淹缠,金羊得路,身脱灾殃。", + "rank": "中下签" + }, + "二七七": { + "answer": "世事难以尽如人意,不是太过就是不及,为此伤神忧虑,毫无意义。", + "question": "有子长,成水局,时遇火反发福,不必过忧煎,人心苦不足。", + "rank": "下签" + }, + "二七三": { + "answer": "雄壮威严,果敢勇往始可折服众人。", + "question": "深山据猛虎,虎啸出山窝,扬威抖擞,何怕人多。", + "rank": "中下签" + }, + "二七九": { + "answer": "大吉大利,所问之事,困局即将突破,从此可入坦途。", + "question": "蛰龙已出世,头角首生成,云兴雨泽,得济苍生。", + "rank": "中上签" + }, + "二七二": { + "answer": "得此签者可能于仓猝间受命,代表所属协调重大事务,并获圆满成功。", + "question": "急起行,急起行,前途去,结同盟,只手擎天柱,史册好标名。", + "rank": "中签" + }, + "二七五": { + "answer": "知足常乐。此签人弃我取人浊我清,自甘恬淡脑杀繁华,真世外人也。", + "question": "山山山,山上建茅 ,不比人间栋宇,却如天上云昙。", + "rank": "中下签" + }, + "二七八": { + "answer": "陌生环境未了解前,勿冒然前往,如果必须前往,应结伴而行。", + "question": "黑夜里,勿前往,一有值,要着慌,牢牢记,须结党。", + "rank": "下签" + }, + "二七六": { + "answer": "得此签者一生劳碌,谋生之处屡易,好在住宿有着落,奔波途中亦安全。", + "question": "来去原无定处,时来时去安身,跋涉无虑,荣辱不计。", + "rank": "中上签" + }, + "二七四": { + "answer": "吾人行事,宜先制定良策,方可致胜可能。", + "question": "三天门,四地户,布阵成,明聚路,军马齐奔,鸣鼓进步。", + "rank": "中上签" + }, + "二三": { + "answer": "喜讯已到,故人安然无恙,健康痊愈在即。此签否极泰来,由困而复。千里外故人自尽力援手。令凡百顺遂也,若强忧煎足自寻苦趣也。", + "question": "喜喜喜,春风生桃李,不用强忧煎,明月人千里。", + "rank": "中上签" + }, + "二三○": { + "answer": "某事或某人之底细即可水落石出,做抉择不会有困难。", + "question": "玉出昆冈石,舟离古渡滩,行藏终有望,用舍不为难。", + "rank": "上签" + }, + "二三一": { + "answer": "阁下心事纠结不开,待客访友迟延难遇,日后处境将留怅恨。", + "question": "目下意难舒,有客来徐徐,金车虽历险,吝必有终与。", + "rank": "下签" + }, + "二三七": { + "answer": "平平,示人须以‘浮云散,明月照人来’之心情,进行心中之事。", + "question": "无中应有直,心事还成戚,云散月重圆,千里风帆急。", + "rank": "上签" + }, + "二三三": { + "answer": "所问诸事忧患深重,若得人指点迷津,或可化险为夷。", + "question": "恐惧忧煎,皆在目前,若逢明鉴,指破空传。", + "rank": "中签" + }, + "二三九": { + "answer": "援引外力助达目的后,要对外力有适当控制,以免外力从此将已束缚,如举债。", + "question": "大仗神威,群魔消灭,灭了又须威,神威亦极力,牢牢记取,免致久后失跌。", + "rank": "下签" + }, + "二三二": { + "answer": "所问之事可以托付他人去办,不过进行缓慢,好在尚不至出错。", + "question": "可以寄,可以托,事迟迟,无舛错。", + "rank": "上签" + }, + "二三五": { + "answer": "一切条件对已有利,亦无风险,奈合时运见拙而心烦意乱,唯有待贵人援手。", + "question": "道路狂招呼,风波一点无,时乖心绪乱,全仗贵人扶。", + "rank": "中上签" + }, + "二三八": { + "answer": "大吉,人生有些际遇必靠福份及神佑,事情只要含有蛇、兔因素,必有变迁。", + "question": "造化生来信自然,师征千里福绵绵,功名得就神明助,蛇兔相逢定变迁。", + "rank": "下签" + }, + "二三六": { + "answer": "要致富须走险路,做了抉择之后就应耐心以待,不必患得患失。", + "question": "临渊放钩,清绝点埃,巨鳌随得,不用疑猜。", + "rank": "上签" + }, + "二三四": { + "answer": "所问之事一时遭遇困阻,不辨路径,须排除障碍后,则再行进展可也。", + "question": "月掩云间,昏迷道路,云散月明,渐宜进步。", + "rank": "中下签" + }, + "二九": { + "answer": "大吉大利,此签为己即是为人,故致身青云,香闻十里。毋系三生之缘,亦即自食其报。占此签者宜益自策励,以期上苍天心。", + "question": "了却心头事,三生夙有缘,香开十里桂,移步入天边。", + "rank": "中上签" + }, + "二九○": { + "answer": "处理事情上不宜忽略小节,要特别注意突生之状况,并推想其缘由方可无事。", + "question": "走走走,遇一狗,急思寻,可长久。", + "rank": "上签" + }, + "二九一": { + "answer": "来得仓促之消息,不可轻信,变化 忽或反覆无常事情,少管为妙。", + "question": "不知真消息,消息蓦地来,月圆月缺夜,不许把门开。", + "rank": "中签" + }, + "二九七": { + "answer": "先经挫折磨练,然后其生命力必更坚强。", + "question": "木长春天根干老,子实三秋枝叶凋,不凋不谢,不见根牢。", + "rank": "中上签" + }, + "二九三": { + "answer": "见好就收。功成身退后,勿再插身名利场中,致求荣而辱,为乐而兴悲,占者当明出处之道。", + "question": "宾雁 湖地成陆,行建功勋早回程,贪恋终非世人福,莫教鸡鹜会相争。", + "rank": "中签" + }, + "二九九": { + "answer": "任何事物,真即真假即假,一经多方考验,底细便明。", + "question": "药饵真,服了宁,三剂后,足分明,神中神,清中清,固得紧,可长生。", + "rank": "下签" + }, + "二九二": { + "answer": "事情进行到最重要关头应慎思斟酌,方不致带来灾害。", + "question": "火旺处要不疲,水深处要不呆,到头当酌量,毋得惹他灾。", + "rank": "下签" + }, + "二九五": { + "answer": "万物生长、代谢均循一定之自然趋势,人类亦然,能悟其理,自必长寿无灾。", + "question": "叶归根,长立天地,水清源长流河海,人得金丹长生渊涯。", + "rank": "上签" + }, + "二九八": { + "answer": "早起三光,晏起三荒,应及时努力,遇事不可因循不振。", + "question": "叫道叫道,天将明了,何不伸首舒眉,反做蓬蒿到老。", + "rank": "中上签" + }, + "二九六": { + "answer": "花无百日娇,无千日好,得意常想失意时,诸般顺心时,应防突来失意或灾殃。", + "question": "乘马去长安,看花花正发,一日雨来淋,香色尽凋零。", + "rank": "中签" + }, + "二九四": { + "answer": "时运正佳,故凡求职、求偶、求学、求财等均有吉利。", + "question": "天上风,天边月,月白风清,两两相当。", + "rank": "中上签" + }, + "二二": { + "answer": "目前不顺,惟亦不致有风险。此签主彼此相助事茂不济,正人君子诚信相孚,无翻云覆雨之虑,用能一帆风顺也。", + "question": "事相扶,在半途,翻覆终可免,风波一点无。", + "rank": "下下签" + }, + "二二○": { + "answer": "因小失大,不怕一万,只怕万一,星星之火,亦可燎原。", + "question": "先关锁,续提防,小节不知戒,因循成大殃。", + "rank": "中下签" + }, + "二二一": { + "answer": "时运已转,凡事可以顺利进行无阻。", + "question": "燕语莺啼,花开满院,倚栏春睡觉,无语 愁颜。", + "rank": "中上签" + }, + "二二七": { + "answer": "不祥,应加谨防,困窘之境依旧,且有风雨飘摇之险。", + "question": "青毡空守旧,枝上巢生风,莫为一时喜,还疑此象凶。", + "rank": "中签" + }, + "二二三": { + "answer": "凡事求其循序渐进足矣,往往事将有成时又遭外来因素之阻扰。", + "question": "进步且徘徊,春风柳絮吹,水边行客倦,枕畔有忧怀。", + "rank": "中上签" + }, + "二二九": { + "answer": "和则无忧,决之为言诀也,与人诀别也,云还於岫月明於空,廊清翳障独显皎洁之义,占者须实行人和两字。", + "question": "上下和,忧愁决,千嶂云,一轮月。", + "rank": "下签" + }, + "二二二": { + "answer": "随时留心、深思,自必于事有补,前途开朗。", + "question": "劳心劳心,劳心有成,清风借力,欢笑前程。", + "rank": "中下签" + }, + "二二五": { + "answer": "狼狈脱逃一时,免却一场灾祸,在经过一番折腾后,终将回到安适生活中。", + "question": "垂翼遥天去,皆因避难行,一途经济意,又是满园春。", + "rank": "中上签" + }, + "二二八": { + "answer": "虽有阻碍,终将鸾凤合鸣,如问他事,则亦好事多磨,但终将如愿。", + "question": "莫言荆棘恶,终为鸾凤栖,目前应有待,何用早踌躇。", + "rank": "下签" + }, + "二二六": { + "answer": "大吉大利之上上签,已有喜讯佳音,机运一到,即可平步青云,直上九重。", + "question": "佳信至,开笑颜,飞腾一去,拨云上天。", + "rank": "中上签" + }, + "二二四": { + "answer": "所问诸事由于当事人之昏昧,小错很多,但并无大碍。", + "question": "玉石犹终昧,那堪小悔多,终无咎,笑呵呵。", + "rank": "中上签" + }, + "二五": { + "answer": "应防来自西方之暗箭,所问之事尚无征候。此签命骞时乖,群阴插弄,带物难寻,六甲欠安,规行矩步可免祸。", + "question": "见不见,也防人背面,遇不遇,到底无凭据。", + "rank": "下下签" + }, + "二五○": { + "answer": "吉祥,对儿女婚嫁、男女友谊、家室人丁等,更为称庆。", + "question": "女儿大,喜临门,嫁良人,添子孙,同拜受,感皇恩。", + "rank": "中下签" + }, + "二五一": { + "answer": "大不利,应谨言慎行,以防不测,免遭横事,此签于人为病痛,于事亦然。", + "question": "木生火,口不噤,疯癫作症,寒热相侵。", + "rank": "下下签" + }, + "二五七": { + "answer": "人生一切莫不有定数,对事不必过于计较。", + "question": "死有日,生有时,何事慢踌躇,飘然一往,心上无疑。", + "rank": "中签" + }, + "二五三": { + "answer": "凡事先防范于未然,才能安全无虑。", + "question": "槛栏起火,孽畜遭殃,预防得力,灭火成康。", + "rank": "中上签" + }, + "二五九": { + "answer": "此签恐系诸葛当年用兵制敌之策略,所卜之事可能双方实力相当。", + "question": "八门分八位,九星布九方,青赤黄白黑,五色卷锦装,交锋对垒,两两相当。", + "rank": "上签" + }, + "二五二": { + "answer": "在近三年半左右,尽量减少兴革异动,对过去所为加以反省,如此或可避祸。", + "question": "休休休,过了三年又六周,不猛省,祸到头。", + "rank": "中签" + }, + "二五五": { + "answer": "大吉大利,命中注定有神明护佑,逢秋八月或有贵人相助。", + "question": "福星照映,桂子香闻,满天星斗,光耀 人。", + "rank": "上签" + }, + "二五八": { + "answer": "进行之事突遇凶险,须拿勇气排除,事情方可顺利,得此签者恐有受惊吓之事。", + "question": "往来行僻处,猝然着一惊,豺狼若当道,斩灭方称心。", + "rank": "中签" + }, + "二五六": { + "answer": "环境至为险恶,既有近忧,又有远患,如想绝地求生,应先求取活命水源。", + "question": "东南北将来成故墟,燕蓟地苍生无存济,若要大奋雄心,水源不知何处?", + "rank": "下签" + }, + "二五四": { + "answer": "事情办成后,仍应持谨慎戒惧之心,否则恐出差错,使前功尽弃。", + "question": "已遂心头愿,始知志气伸,三山须把握,频频定太平。", + "rank": "中签" + }, + "二八": { + "answer": "吉祥,若卜仕途宦海之事,尤称合适。此签勉人时来运至,宜闻鸡起舞,勿坐失时机,他日衣锦荣归,耄年清福,系於当日遭际时决之。", + "question": "禄马交驰,男儿得志时,行程早办,荣归乐期颐。", + "rank": "上上签" + }, + "二八○": { + "answer": "一旦发生意外灾祸,事发就不可收拾,应有克制对策,庶几解除困难。", + "question": "火势薰天,天边尽赤,遇际水源,庶乎成格。", + "rank": "中下签" + }, + "二八一": { + "answer": "含下列寓意:工作地点以南方为宜,寻访可能得遇,交游虽不广,可获知己。", + "question": "向南有大道,乘马入杭城,不知吴人唱,更有一知音。", + "rank": "上签" + }, + "二八七": { + "answer": "进行一事,必先穷理探源,把握其中要领,方能得心应手。", + "question": "人不识仙,那有真诀,一入玄门,津津有益。", + "rank": "上签" + }, + "二八三": { + "answer": "此签寓意难明,或指形貌才智虽有缺陷,但天生万物,必有所长。", + "question": "勿嫌儿无唇,疾足追不及,纳入猿穴中,走狗何处觅。", + "rank": "上签" + }, + "二八九": { + "answer": "与其汲汲于追求功名,不如修身养性。", + "question": "功名虽多实际,何如修炼成真,真身不朽,万载长春。", + "rank": "中上签" + }, + "二八二": { + "answer": "家有恒产,虽说不多,若能认真经营终必有成。得此签者似不易离家另谋他业。", + "question": "有田一亩,尽可耕耘,无穷收获,都在西成。", + "rank": "中签" + }, + "二八五": { + "answer": "成大事者应志在四方,勿囿于一角,把握时机及早行动。七八或与时日机运有关。", + "question": "大奋冲天志,勿苦恋家乡,七八君行早,扬武在沙场。", + "rank": "中下签" + }, + "二八八": { + "answer": "所问之事,面貌并不清朗,须用心去探求其内蕴。", + "question": "勿谓说话太沈,泥了就不成真,悟出千般奥妙,方识仙道最神。", + "rank": "上上签" + }, + "二八六": { + "answer": "得此签者深受部属爱戴,都能为其赤诚工作,使其事业鸿图大展。", + "question": "葵花向日,忠赤倾心,大开广厦,乐享太平。", + "rank": "上签" + }, + "二八四": { + "answer": "一分耕耘,一分收获,天下无侥幸而成之事。", + "question": "六牛耕地,垦开无疆,收成结实,盈禀盈仓。", + "rank": "下签" + }, + "二六": { + "answer": "此签进不如退,行不如藏,富不如贫,达不如穷,能处处恬淡,即是处处保守,渔樵农圈,转可安居,富贵尊荣,今非昔比。", + "question": "一番桃李一番春,谁识当初气象新,林下水边寻活计,见山了了称心意。", + "rank": "上上签" + }, + "二六○": { + "answer": "此签有力争上游恶居下流之象,後两句警人尤深,坑堑地狱也,占之者速宜回头猛省,以此语为座右铭。", + "question": "终身不习上,在世却枉然,轮回不能免,永落深坑堑。", + "rank": "中签" + }, + "二六一": { + "answer": "得此签者可望得一子一女,亦可能一举得男女各一之双胞胎,凡事求阴阳调和。", + "question": "两个子女,同到齐行,阴阳和合,谋作欢欣。", + "rank": "下签" + }, + "二六七": { + "answer": "全力以赴,必有所成。占者慎勿甘自暴弃,坠青云之志也。", + "question": "滴漏声催鸡唱,趱行人逐队放,晚渡关津,前程无量。", + "rank": "中签" + }, + "二六三": { + "answer": "意外之好运,有时不是福气反成负担。", + "question": "数尾金鱼吞饵,丝竿钓了回头,家食翻嫌太贵,五湖四海遨游。", + "rank": "中签" + }, + "二六九": { + "answer": "寓意有二: 凡命运亨通者,即或居于枯树古井旁,福泽依增 勿营华屋。", + "question": "这颗树下,一穴生成,若迁此土,福禄骈臻。", + "rank": "上签" + }, + "二六二": { + "answer": "所问诸事疑难未解,但很快就能悟出解决之道。", + "question": "中有玄机赋,鸡鸣方显露,猛然悟禅关,打破君门路。", + "rank": "上签" + }, + "二六五": { + "answer": "所问事一两日内尚难定,日子到了事情自明朗,应为三个人合力办成之好事。", + "question": "日中不决,日到方明,一场好事,六耳同成。", + "rank": "下签" + }, + "二六八": { + "answer": "所念之人,远在他乡,久无讯息,对其怀念殷切。", + "question": "人在天涯外,久乏信音来,家人频望眼,草木畅胸怀。", + "rank": "上签" + }, + "二六六": { + "answer": "此签主群阴播弄淆乱心,故交友不可不慎,立意不可不定,断事不可不快,悟性不可不佳,占者终以远之为是。", + "question": "孤宿是妖星,猿猴及树精,入山遇此曜,迷了性和心。", + "rank": "下下签" + }, + "二六四": { + "answer": "天时依一定顺序运转,做任何事不能违背自然法则。", + "question": "卯日儿出林,午时正福临,卯生于寅,方见天心。", + "rank": "中签" + }, + "二四": { + "answer": "谨言慎行,始得平安。安分守己,谨防出入,商贾勿大斗小秤。士子勿诬圣蔑贤,在朝勿贪诈,在野勿争斗,占此签者宜深味之。", + "question": "意孜孜,心戚戚,要平安,防出入。", + "rank": "中下签" + }, + "二四○": { + "answer": "勉人立身修业,勿图官宦之奢望,勿为功禄所贪恋。", + "question": "道必坚心,坚心必道成,建功勋,早回程,造茅庵,修真身,一日飞升,仙班列名。", + "rank": "中上签" + }, + "二四一": { + "answer": "荣耀或羞辱取决人之一念之间,人云亦云,昏庸一生岂不可惜?", + "question": "一念上天堂,一念入地狱,地狱天堂,   便分荣辱,自立念头要真,不可随人碌碌。", + "rank": "中签" + }, + "二四七": { + "answer": "横逆之来出於意外,惊魄丧魂几濒於危,幸根本未摇,所损枝叶略加培植依然生气勃勃,有惊无险。", + "question": "蓦地狂风起,大树尽掀扬,枝叶未凋零,培植终无恙。", + "rank": "下签" + }, + "二四三": { + "answer": "所问事已步入歧途,是否及时省悟回头,视问卜者是否有缘及个性是否执拗。", + "question": "若是有缘人,一指便回首,执迷不悟者,屡引也不走。", + "rank": "下签" + }, + "二四九": { + "answer": "荣枯天定,不要为失意伤情,应乐天知命,得此签者恐刻下时运不佳。", + "question": "荣枯早定莫嗟伤,辛苦他邦安享家乡,为他人作嫁衣裳,今日君尝,他年改调别人尝。", + "rank": "中下签" + }, + "二四二": { + "answer": "所显诗句近乎玄虚,不适用现代,不妨再卜一]。", + "question": "羊逸群,日对民,逢牛口,便咬人,一个君一个臣,君臣有些惊,须仗真神拯救苍生。", + "rank": "中上签" + }, + "二四五": { + "answer": "大功告成之后,自可封侯或退隐山林,而选择后者才是大丈夫行径。", + "question": "男儿若得封侯印,不负人间走一遭,功成身退烟霞啸傲,脱却紫罗袍,方是男儿道。", + "rank": "上签" + }, + "二四八": { + "answer": "勿为假相所欺,应多方深入探讨真相。", + "question": "虚日旺相,法要推寻,四围旋绕,对敌冲营。", + "rank": "中签" + }, + "二四六": { + "answer": "世间有若干危害人体之嗜好,智者应以‘妖狐’迷人为鉴。", + "question": "心月狐狸,迷惑世人,世人不察,延久倾身。", + "rank": "上签" + }, + "二四四": { + "answer": "有好机运来,可以大放异彩,凡事均无阻塞,今后环境更趋有利。", + "question": "月儿升东,清光可挹,万里无云,海天一碧。", + "rank": "上上签" + }, + "五": { + "answer": "否极泰来,外旱逢甘雨,此乃待时而动之义。占得者必潜蓄精神,为奋发地。却不可轻举妄动,致转取戾。顺之者吉,逆之者否。", + "question": "春雷震,夏风巽,卧龙起,猛虎惊,风云会合,救济苍生。", + "rank": "中下签" + }, + "五○": { + "answer": "顺其自然。此签主官运亨通,财星高照,富贵尊荣,造物安排已定,占之者吉。", + "question": "财马两匆忙,官禄有定方,猪羊牛犬,自去主张。", + "rank": "中下签" + }, + "五一": { + "answer": "大器晚成,若问财运,得此签不祥,若问诉讼,则于缠讼多日可获胜诉。", + "question": "空空空,空里得成功,蟠桃千载熟,不怕五更风。", + "rank": "中下签" + }, + "五七": { + "answer": "此签主人只须正直,切不可随波逐流,与世浮沈,能如此名成利就,可操左券。叶落花开者,理之自然也,占此者务以存心正直为要。", + "question": "正直宜守,妄动生灾,利通名达,叶落花开。", + "rank": "中签" + }, + "五三": { + "answer": "惕之签,凡事须全力以赴,不可贪玩疏忽,时运来临,愿望自然可成。", + "question": "须着力,莫远游,长竿钓向蟾蜍窟,直欲云中得巨鳌。", + "rank": "中上签" + }, + "五九": { + "answer": "须守时耐运,待机而行,不可强求。妇人求得此签,恐有夫妻失和情事。", + "question": "纷纷复纷纷,欷 独掩门, 眉望灯火,伴我坐黄昏。", + "rank": "中下签" + }, + "五二": { + "answer": "吉祥,心境渐渐开朗,环境已转佳境,寻人定然相遇,其他亦有转机。", + "question": "愁脸放,笑颜开,秋月挂高台,人从千里来。", + "rank": "中签" + }, + "五五": { + "answer": "时运欠佳,一切难望有成,惟有依靠仅有之一线生机。", + "question": "细雨蒙蒙湿,江边路不通,道途音信远,凭仗借东风。", + "rank": "中下签" + }, + "五八": { + "answer": "所问之事波折连连,有人玉成,有人破坏,无地利之便,须稳妥安排为宜。", + "question": "君子升,小人阻,征战生离苦,前有吉人逢,信在马牛人在楚,事要营求妥。", + "rank": "中上签" + }, + "五六": { + "answer": "所问之事现时现地均难有成,如问姻缘,须向显赫人家去求,如问事业,波折重重。", + "question": "平地起云烟,时下未能安,高处觅姻缘。", + "rank": "中下签" + }, + "五四": { + "answer": "诸事难成。此签诸事不吉,占病不利,名财两空,胎孕有惊,行人不至,谋事不遂,能自猛省亦可挽回天心。", + "question": "无踪无迹,远近难觅,旱海行舟,空劳费力。", + "rank": "中上签" + }, + "八": { + "answer": "目前无人能识,日后必受众人赞颂,怀才不遇者得此签,日后必发达。绦老辱在泥涂,意在静观时机,一旦运至自亨通。", + "question": "虎恋高山别有机,众人目下尚狐疑,雁来嘹呖黄花发,此际声名达帝畿。", + "rank": "中上签" + }, + "八○": { + "answer": "不可暴殄天物,对事物体认不够,任意扔弃滥用,岂不可惜。", + "question": "木向阳春发,三阴又伏根,樵夫不知道,砍去作柴薪。", + "rank": "中下签" + }, + "八一": { + "answer": "此签不吉,月既缺镜又损,所问诸事自属不圆满,恐亦无转机。", + "question": "一月缺,一镜缺,不团圆,无可说。", + "rank": "下下签" + }, + "八七": { + "answer": "此签主功名成遂,财利丰收十全五福萃於一门,是惟忠孝之家,方克获兹善报,占者无不利也。", + "question": "福星照,吉宿临,青天有日见天真,龙飞下载到明庭。", + "rank": "上上签" + }, + "八三": { + "answer": "选择努力方向,如能吸取前贤经验,必能事半功倍,如得神助。", + "question": "我何宿,我何宿,海东河北成名录,一段神光,直冲天渎。", + "rank": "中签" + }, + "八九": { + "answer": "所问诸事意见纷陈,头绪杂乱,如不借助有力者,恐要白费心力。", + "question": "不归一,劳心力,贵人旁,宜借力。", + "rank": "中上签" + }, + "八二": { + "answer": "此签如问战略戎事大吉,问事业则大发,问考试则高中。", + "question": "车马到临,旌旗隐隐月分明,招安讨叛,永大前程。", + "rank": "中上签" + }, + "八五": { + "answer": "愁闷事在杯酒中尽释,夫妻间之不合应尽快化解。", + "question": "倾一 ,展愁眉,天地合,好思为。", + "rank": "中下签" + }, + "八八": { + "answer": "这一签所预示的结局是很差的,劳心劳力,没有收获,所幸的是自己身体方面、家人方面没有大碍,该说是不幸中的大幸。", + "question": "独钓寒潭,中途兴阑,水寒鱼不饵,空载月明还。", + "rank": "中上签" + }, + "八六": { + "answer": "得此签者如为主管,恐有欺害下属之事,结果遭到致命之报复。", + "question": "野鬼张弧射主人,暗中一箭鬼魂惊,忽然红日沈江海,难破空中事不明。", + "rank": "下下签" + }, + "八四": { + "answer": "金鳞影射钱财,警惕吾人谨言少语,如遇友人金钱周转,须防上当受骗。", + "question": "金鳞入手,得还防走,若论周旋,谨言缄口。", + "rank": "中上签" + }, + "六": { + "answer": "心性勿急切,着意搜寻,必能如愿。自来少参透事情之人,此签在使搜寻妙道,而妙道实亦并不奇妙,在人之自悟耳。", + "question": "非玄非奥,非浅非深,一个妙道,着意搜寻。", + "rank": "中下签" + }, + "六○": { + "answer": "戒妄想非分,只宜守身安命,若驰鹜远,徒乱人意,终仍无一成就。占之者切勿轻举妄动,就像美人在车,看自己则在船里,不相关也。", + "question": "红颜美,休挂怀,人在车中,舟行水里。", + "rank": "上上签" + }, + "六一": { + "answer": "桥断路绝,舟破风狂,命运可知矣,占此者能积德修身,广种福田自可转危为安,逢凶化吉,若仍诛求无厌,势必灾祸临身。", + "question": "桥已断,路不通,登舟理楫,又遇狂风。", + "rank": "下下签" + }, + "六七": { + "answer": "一鼓作气,勇往直前,即使往昔曾犯缺失,如今亦可重获振作之机。", + "question": "乘马前进,所求吉贞,随时谐美,缺月重明。", + "rank": "中上签" + }, + "六三": { + "answer": "此签主交卯辰流年,名利双收又逢卯辰生年之人,亦得提拔扶助之德,占者细思量遵行之。", + "question": "湖海意悠悠,烟波下钓钩,若逢龙与兔,名利一齐周。", + "rank": "中上签" + }, + "六九": { + "answer": "知足常乐,随遇而安,否则梦境难圆之慨,妇女得此签,宜勉力抛虚荣之心。", + "question": "不足不足,难伸心曲,野塘雨过月如钩,梦断邯郸眉黛愁。", + "rank": "中下签" + }, + "六二": { + "answer": "有财不招,家口多病,六甲无望,婚姻不成,功名蹭蹬,行人无信,官司口舌均属难免。占此者省些精神,勿为无益之事。", + "question": "深潭月,照镜影,一场空,安报信。", + "rank": "下下签" + }, + "六五": { + "answer": "请神容易送神难。易进难退,鸟脱樊笼而不得,鱼离网钩而不能,淹滞久久难望跳出火坑,占者有扰攘不宁,意绪纷如之象。", + "question": "入而易,出而难,恹恹到再三,交加意不堪。", + "rank": "中下签" + }, + "六八": { + "answer": "此签主外,出远行有利,得此签者,所问之事难题已解,难关已破,从此坦途。", + "question": "舟离古渡月离云,人出潼关好问津,且向前行去求住,何须疑虑两三心。", + "rank": "中签" + }, + "六六": { + "answer": "若时机未熟,但凭己力,尚难成就。妇女得此签,显示心意不足,青春蹉跎。", + "question": "事迟志速,而且反覆,直待岁寒,花残果熟。", + "rank": "中下签" + }, + "六四": { + "answer": "所问之事应重新来过,如以笃实之态度为之,或有可成。", + "question": "物不牢,人断桥,重整理,慢心高。", + "rank": "中下签" + }, + "四": { + "answer": "勉惕类,诸事无法顺利,踏实或有可望。大器晚成,得意必在暮年。若青年得志,必如秦之甘罗,唐之王勃,雨打风飘示警也。", + "question": "春花娇媚,不禁雨打风飘,秋菊幽芳,反耐霜雪傲。", + "rank": "中上签" + }, + "四○": { + "answer": "塞翁失马,焉知非福,诸事均欠顺遂,惟尚未铸下大错,还能全身而退。切勿轻信人言,优柔寡断,坐井观天。", + "question": "一带水,碧澄澄,舟住江上,月到天心;稳步其中,玄妙不闲,非人误己,几丧生身。", + "rank": "中下签" + }, + "四一": { + "answer": "此签示人既凡百称心遂意,便当即时行乐,不可不知足,今日因某事许愿,明日又为某事求祷,以致干渎神明也。惟修身以行善可已。", + "question": "桃李舒姘,春光鲜丽,良辰美景君须记,随心所往事事相宜,无用多疑干渎神祗。", + "rank": "中签" + }, + "四七": { + "answer": "此签主真为美德,人虽不知而神知也,故一念真诚,鬼神可格,金石为开。占得此签务当摒斥虚伪,力求真实,勿欺人以自欺也。", + "question": "真真真,人不识,真真真,神有灵,归宗返本,方是元精。", + "rank": "上上签" + }, + "四三": { + "answer": "所问之事可能走错方向,即改弦易辙,另觅可行之路。古来明哲保身,决不专走死路,悬崖勒马,别作他图,贵独具只眼。", + "question": "无上去,在前头,回头一悟,绳缰好收,千条万线路常在,自好搜求。", + "rank": "中上签" + }, + "四九": { + "answer": "久病者突逢良医,立即恢复健康,经营事业不佳者,可望获良才,兴隆有望。", + "question": "沈沈屙染,不见天心,雷门一震,体健身轻。", + "rank": "中下签" + }, + "四二": { + "answer": "玄机不玄,道本中庸,圣贤仙佛只是行中庸之道,遂为千百世所景仰。常人欲上仙梯何难之有,慎勿谓玄机隐微,甘居人後也。", + "question": "隐中显,显中微,个中有玄机,参得透了,直上仙梯。", + "rank": "上上签" + }, + "四五": { + "answer": "做事沈着稳定,自有容身之地,多热心公益,门庭自逢佳运。概须脚踏实地,不必行险侥幸,自有安身立命之所。", + "question": "不用忙,不用慌,自有驻足乡,鸣鼓响钟地,三宝见门墙。", + "rank": "中下签" + }, + "四八": { + "answer": "此签主舍近求远,一事无成 ,徒自劳苦,益时运不济,强求无益也。占此者须明心见性,尽可安贫乐道,毋庸逆天而行也。", + "question": "走尽天涯,风霜历遍,不如问人三天,渐渐有回首见。", + "rank": "中签" + }, + "四六": { + "answer": "一生争名夺利,最后化为乌有,回头是岸。此签言人一饮一食莫非前定,要为名利作马牛。", + "question": "奔波一世,总是虚浮,无常一到万事休,急早回头。", + "rank": "下下签" + }, + "四四": { + "answer": "签主福祸无门,惟人自招,放下屠刀,立地成佛。苦心修炼,必不自落凡庸,占此者当知荣辱之机,己实操之,不必怨天尤人也。", + "question": "四顾无门路,桃源路可通,修炼成正果,万岁寿如松。", + "rank": "上上签" + } +} \ No newline at end of file diff --git "a/almanac/assets/\346\261\211\344\273\252\346\226\207\351\273\221.ttf" "b/src/almanac/assets/\346\261\211\344\273\252\346\226\207\351\273\221.ttf" similarity index 100% rename from "almanac/assets/\346\261\211\344\273\252\346\226\207\351\273\221.ttf" rename to "src/almanac/assets/\346\261\211\344\273\252\346\226\207\351\273\221.ttf" diff --git a/almanac/draw_lots.py b/src/almanac/draw_lots.py similarity index 99% rename from almanac/draw_lots.py rename to src/almanac/draw_lots.py index 673d02b..454350e 100644 --- a/almanac/draw_lots.py +++ b/src/almanac/draw_lots.py @@ -1,11 +1,13 @@ +import json +import os +import random +import textwrap +import time + from PIL import Image, ImageDraw, ImageFont + from .almanac import month_to_chinese from .tweaks import text_r90 -import textwrap -import random -import time -import json -import os FILE_PATH = os.path.dirname(__file__) FONT_PATH = os.path.join(FILE_PATH, "assets", "汉仪文黑.ttf") @@ -16,7 +18,6 @@ lots_list = json.loads(f.read()) lots_items = list(lots_list.keys()) - time_font = ImageFont.truetype(FONT_PATH, 30) lot_font = ImageFont.truetype(FONT_PATH, 25) question_x = 250 diff --git a/almanac/group_list.json b/src/almanac/group_list.json similarity index 100% rename from almanac/group_list.json rename to src/almanac/group_list.json diff --git a/almanac/tweaks.py b/src/almanac/tweaks.py similarity index 97% rename from almanac/tweaks.py rename to src/almanac/tweaks.py index 64b2afb..e924d80 100644 --- a/almanac/tweaks.py +++ b/src/almanac/tweaks.py @@ -1,9 +1,8 @@ -from io import BytesIO -import requests import base64 import json -import time import os +import time +from io import BytesIO jsondb_template = { "10001": { @@ -83,4 +82,4 @@ def get_time(): if __name__ == "__main__": jdb = jsondb("t.json") user = jdb.user(2632324507) - print(user.db["time"] == get_time()) \ No newline at end of file + print(user.db["time"] == get_time()) diff --git a/artifact_collect/Artifact.py b/src/artifact_collect/Artifact.py similarity index 77% rename from artifact_collect/Artifact.py rename to src/artifact_collect/Artifact.py index d76951c..2828f41 100644 --- a/artifact_collect/Artifact.py +++ b/src/artifact_collect/Artifact.py @@ -1,13 +1,11 @@ -from PIL import Image,ImageFont,ImageDraw,ImageMath -from io import BytesIO -from ..config import SECONDARY_LEVEL_PROBABILITY,CONSUME_STRENGTHEN_POINTS - -import os +import base64 import json +import os import random -import base64 - +from io import BytesIO +from PIL import Image, ImageFont, ImageDraw, ImageMath +from config import SECONDARY_LEVEL_PROBABILITY, CONSUME_STRENGTHEN_POINTS FILE_PATH = os.path.dirname(__file__) @@ -15,14 +13,11 @@ ARTIFACT_PROPERTY = [] PROPERTY_LIST = {} - - artifact_obtain = {} -flower,feather,hourglass,cup,crown = (0,1,2,3,4) - -back_image = Image.open(os.path.join(FILE_PATH,"icon", 'background.png')) -ttf_path = os.path.join(FILE_PATH,"zh-cn.ttf") +flower, feather, hourglass, cup, crown = (0, 1, 2, 3, 4) +back_image = Image.open(os.path.join(FILE_PATH, "icon", 'background.png')) +ttf_path = os.path.join(FILE_PATH, "zh-cn.ttf") def init_json(): @@ -33,13 +28,13 @@ def init_json(): global PROPERTY_LIST global artifact_obtain - with open(os.path.join(FILE_PATH,"artifact_list.json"),"r",encoding="UTF-8") as f: + with open(os.path.join(FILE_PATH, "artifact_list.json"), "r", encoding="UTF-8") as f: ARTIFACT_LIST = json.load(f) - with open(os.path.join(FILE_PATH,"artifact_property.json"),"r",encoding="UTF-8") as f: + with open(os.path.join(FILE_PATH, "artifact_property.json"), "r", encoding="UTF-8") as f: ARTIFACT_PROPERTY = json.load(f) - with open(os.path.join(FILE_PATH,"property_list.json"),"r",encoding="UTF-8") as f: + with open(os.path.join(FILE_PATH, "property_list.json"), "r", encoding="UTF-8") as f: PROPERTY_LIST = json.load(f) for suit_name in ARTIFACT_LIST.keys(): @@ -50,12 +45,12 @@ def init_json(): artifact_obtain[obtain] = [] artifact_obtain[obtain].append(suit_name) -init_json() +init_json() class Artifact(object): - def __init__(self, property = None): + def __init__(self, property=None): # property是一个圣遗物名称字符串或者圣遗物属性字典 # 使用名称字符串初始化会随机圣遗物的属性 if property.__class__.__name__ == "str": @@ -65,18 +60,18 @@ def __init__(self, property = None): else: raise ValueError("你需要提供圣遗物名称字符串或一个字典对象") - def _name_init(self,_name): + def _name_init(self, _name): # 名称初始化圣遗物 self.name = _name self.suit_name = self.get_suit_name(self.name) self.level = 0 - self.artifact_type = self.get_artifact_type(self.suit_name,self.name) + self.artifact_type = self.get_artifact_type(self.suit_name, self.name) self.main = self.get_random_main() self.initial_secondary = {} self.strengthen_secondary_list = [] self.initialize_secondary() - def _dict_init(self,property): + def _dict_init(self, property): # 字典初始化圣遗物 for key in property.keys(): self.__dict__[key] = property[key] @@ -93,7 +88,7 @@ def get_suit_name(_name): return suit @staticmethod - def get_artifact_type(suit,name): + def get_artifact_type(suit, name): # suit表示套装名称,name表示部件名称 # 查询圣遗物部件在套装中是哪个位置,返回一个整数 # 从0到4分别表示 花 羽毛 沙漏 杯 头冠 @@ -105,9 +100,9 @@ def get_artifact_type(suit,name): def number_to_str(number): # 把数字转换成str并添加%符号 # 小于1的是百分比字符串,属性为数值或元素精通用整数,其他用浮点数 - if number < 1 : - number = number*100 - return ('%.1f'% number) + "%" + if number < 1: + number = number * 100 + return ('%.1f' % number) + "%" else: return str(int(number)) @@ -123,7 +118,7 @@ def get_random_secondary(self): temp_set = temp_set.difference(set(self.get_all_secondary_name())) return random.choice(list(temp_set)) - def get_random_secondary_value(self,secondary_name): + def get_random_secondary_value(self, secondary_name): # 获取一个副属性的值 # 每个副属性都有4个等级的值,表示出现或升级时的提升量,详情看property_list.json # 副属性4个等级的概率在config.py的SECONDARY_LEVEL_PROBABILITY里 @@ -132,10 +127,10 @@ def get_random_secondary_value(self,secondary_name): if r < SECONDARY_LEVEL_PROBABILITY[0]: return PROPERTY_LIST["secondary"][secondary_name]["level"][0] - if r < ( SECONDARY_LEVEL_PROBABILITY[0] + SECONDARY_LEVEL_PROBABILITY[1] ): + if r < (SECONDARY_LEVEL_PROBABILITY[0] + SECONDARY_LEVEL_PROBABILITY[1]): return PROPERTY_LIST["secondary"][secondary_name]["level"][1] - if r < ( SECONDARY_LEVEL_PROBABILITY[0] + SECONDARY_LEVEL_PROBABILITY[1] + SECONDARY_LEVEL_PROBABILITY[2] ): + if r < (SECONDARY_LEVEL_PROBABILITY[0] + SECONDARY_LEVEL_PROBABILITY[1] + SECONDARY_LEVEL_PROBABILITY[2]): return PROPERTY_LIST["secondary"][secondary_name]["level"][2] return PROPERTY_LIST["secondary"][secondary_name]["level"][3] @@ -158,7 +153,8 @@ def get_main_value(self): # 强满后主属性直接获取最大值,否则用初始值加上强化等级乘以成长值 return PROPERTY_LIST["main"][self.main]["max"] else: - return PROPERTY_LIST["main"][self.main]["initial_value"] + self.level * PROPERTY_LIST["main"][self.main]["growth_value"] + return PROPERTY_LIST["main"][self.main]["initial_value"] + self.level * PROPERTY_LIST["main"][self.main][ + "growth_value"] def get_secondary_property_value(self): # 累加初始和强化副属性的值 @@ -177,7 +173,7 @@ def initialize_secondary(self): # 这个方法会直接修改self.initial_secondary # 随机初始副属性的个数 - number = random.randint(3,4) + number = random.randint(3, 4) for _ in range(number): secondary = self.get_random_secondary() @@ -202,7 +198,8 @@ def strengthen(self): secondary = self.get_random_secondary() secondary_value = self.get_random_secondary_value(secondary) strengthen_type = "add" - self.strengthen_secondary_list.append({"type": strengthen_type, "property": secondary, "value": secondary_value}) + self.strengthen_secondary_list.append( + {"type": strengthen_type, "property": secondary, "value": secondary_value}) else: # 获取所有副属性 @@ -211,9 +208,11 @@ def strengthen(self): secondary = random.choice(temp_list) secondary_value = self.get_random_secondary_value(secondary) strengthen_type = "up" - self.strengthen_secondary_list.append({"type": strengthen_type, "property": secondary, "value": secondary_value}) + self.strengthen_secondary_list.append( + {"type": strengthen_type, "property": secondary, "value": secondary_value}) - return {"level":self.level,"strengthen_type":strengthen_type,"secondary":secondary,"secondary_value":secondary_value} + return {"level": self.level, "strengthen_type": strengthen_type, "secondary": secondary, + "secondary_value": secondary_value} def re_init(self): # 圣遗物洗点 @@ -223,7 +222,7 @@ def get_artifact_dict(self): # 把圣遗物信息打包成dict返回 return self.__dict__ - def get_artifact_detail(self,start = 1): + def get_artifact_detail(self, start=1): # 圣遗物详情 mes = self.get_artifact_CQ_code() mes += "\n\n" @@ -233,15 +232,15 @@ def get_artifact_detail(self,start = 1): while start <= self.level: if (start % 4) == 0: - strengthen_type = self.strengthen_secondary_list[int(start//4)-1]["type"] + strengthen_type = self.strengthen_secondary_list[int(start // 4) - 1]["type"] if strengthen_type == "up": strengthen_type = "强化" else: strengthen_type = "新增" - secondary = self.strengthen_secondary_list[int(start//4)-1]["property"] + secondary = self.strengthen_secondary_list[int(start // 4) - 1]["property"] secondary = PROPERTY_LIST["secondary"][secondary]["txt"] - value = self.strengthen_secondary_list[int(start//4)-1]["value"] + value = self.strengthen_secondary_list[int(start // 4) - 1]["value"] value = self.number_to_str(value) mes += f"第 {start} 级{strengthen_type}了 {secondary} ,强化值为 {value}\n" @@ -252,17 +251,17 @@ def get_artifact_detail(self,start = 1): def get_icon_path(self): # 获取图标的文件路径 name = f"{ARTIFACT_LIST[self.suit_name]['number']}_{self.artifact_type}.png" - return os.path.join(FILE_PATH,"icon",name) + return os.path.join(FILE_PATH, "icon", name) - def get_artifact_image(self,number): + def get_artifact_image(self, number): # 获取圣遗物图片,会返回一个image back = back_image.copy() icon = Image.open(self.get_icon_path()) - icon = icon.resize((180,180)) + icon = icon.resize((180, 180)) - icon_a = icon.getchannel("A") # 有的图alpha通道有问题,需要对alpha处理一下 + icon_a = icon.getchannel("A") # 有的图alpha通道有问题,需要对alpha处理一下 icon_a = ImageMath.eval("convert(a*b/256, 'L')", a=icon_a, b=icon_a) back.paste(icon, (220, 52), icon_a) @@ -270,25 +269,28 @@ def get_artifact_image(self,number): draw = ImageDraw.Draw(back) main_property_value = self.get_main_value() secondary_property_value = self.get_secondary_property_value() - draw.text((25, 10), self.name, fill="#ffffffff", font=ImageFont.truetype(ttf_path, size=28)) - if number : # 如果number不为0,在图片上加上编号 + draw.text((25, 10), self.name, fill="#ffffffff", font=ImageFont.truetype(ttf_path, size=28)) + if number: # 如果number不为0,在图片上加上编号 draw.text((340, 10), str(number), fill="#ffffffff", font=ImageFont.truetype(ttf_path, size=28)) - draw.text((25, 60), ARTIFACT_PROPERTY[self.artifact_type]['name'], fill="#ffffffff", font=ImageFont.truetype(ttf_path, size=20)) - draw.text((25, 130), PROPERTY_LIST['main'][self.main]['txt'], fill="#bfafa8", font=ImageFont.truetype(ttf_path, size=20)) - draw.text((25, 153), self.number_to_str(main_property_value), fill="#ffffffff", font=ImageFont.truetype(ttf_path, size=32)) - draw.text((30, 260), f"+{self.level}", fill="#ffffffff", font=ImageFont.truetype(ttf_path, size=18)) + draw.text((25, 60), ARTIFACT_PROPERTY[self.artifact_type]['name'], fill="#ffffffff", + font=ImageFont.truetype(ttf_path, size=20)) + draw.text((25, 130), PROPERTY_LIST['main'][self.main]['txt'], fill="#bfafa8", + font=ImageFont.truetype(ttf_path, size=20)) + draw.text((25, 153), self.number_to_str(main_property_value), fill="#ffffffff", + font=ImageFont.truetype(ttf_path, size=32)) + draw.text((30, 260), f"+{self.level}", fill="#ffffffff", font=ImageFont.truetype(ttf_path, size=18)) x = 25 y = 300 for secondary in secondary_property_value.keys(): name = PROPERTY_LIST["secondary"][secondary]["txt"] - value = self.number_to_str( secondary_property_value[secondary] ) + value = self.number_to_str(secondary_property_value[secondary]) draw.text((x, y), f"·{name}+{value}", fill="#495366", font=ImageFont.truetype(ttf_path, size=22)) y += 32 return back - def get_artifact_CQ_code(self,number = 0): + def get_artifact_CQ_code(self, number=0): # 返回圣遗物图片的CQ码 number为圣遗物在仓库的编号 image = self.get_artifact_image(number) @@ -299,8 +301,7 @@ def get_artifact_CQ_code(self,number = 0): return f"[CQ:image,file={base64_str}]" - -def calculate_strengthen_points(start = 1, end = 20): +def calculate_strengthen_points(start=1, end=20): # 计算强化需要的狗粮点数 if end > 20: end = 20 @@ -309,11 +310,3 @@ def calculate_strengthen_points(start = 1, end = 20): value += CONSUME_STRENGTHEN_POINTS[start] start += 1 return value - - - - - - - - diff --git a/artifact_collect/__init__.py b/src/artifact_collect/__init__.py similarity index 99% rename from artifact_collect/__init__.py rename to src/artifact_collect/__init__.py index 0557c54..c6f16aa 100644 --- a/artifact_collect/__init__.py +++ b/src/artifact_collect/__init__.py @@ -1,10 +1,10 @@ -from .Artifact import artifact_obtain, ARTIFACT_LIST, Artifact, calculate_strengthen_points -from ..config import STAMINA_RESTORE, MAX_STAMINA -from .json_rw import init_user_info, updata_uid_stamina, user_info, save_user_info +import random +from config import STAMINA_RESTORE, MAX_STAMINA from hoshino import Service -import random +from .Artifact import artifact_obtain, ARTIFACT_LIST, Artifact, calculate_strengthen_points +from .json_rw import init_user_info, updata_uid_stamina, user_info, save_user_info sv = Service("原神圣遗物收集") diff --git a/src/artifact_collect/artifact_list.json b/src/artifact_collect/artifact_list.json new file mode 100644 index 0000000..617ac3c --- /dev/null +++ b/src/artifact_collect/artifact_list.json @@ -0,0 +1,272 @@ +{ + "角斗士的终幕礼": { + "element": [ + "角斗士的留恋", + "角斗士的归宿", + "角斗士的希冀", + "角斗士的酣醉", + "角斗士的凯旋" + ], + "abbreviation": [ + "角斗士", + "角斗士套" + ], + "obtain": "龙狼", + "number": "15001", + "注释": "这个文件记录圣遗物的套装名,element表示包含的部件名,必须按照花羽毛沙漏杯头冠的顺序填写,abbreviation表示简称,obtain表示哪个副本掉落,number表示图标的编号" + }, + "流浪大地的乐团": { + "element": [ + "乐团的晨光", + "琴师的箭羽", + "终幕的时计", + "吟游者之壶", + "指挥的礼帽" + ], + "abbreviation": [ + "流浪" + ], + "obtain": "龙狼", + "number": "15003" + }, + "平息鸣雷的尊者": { + "element": [ + "平雷之心", + "平雷之羽", + "平雷之刻", + "平雷之器", + "平雷之冠" + ], + "abbreviation": [], + "obtain": "雷本", + "number": "14002" + }, + "如雷的盛怒": { + "element": [ + "雷鸟的怜悯", + "雷灾的孑遗", + "雷霆的时计", + "降雷的凶兆", + "唤雷的头冠" + ], + "abbreviation": [], + "obtain": "雷本", + "number": "15005" + }, + "渡过烈火的贤人": { + "element": [ + "渡火者的决绝", + "渡火者的解脱", + "渡火者的煎熬", + "渡火者的醒悟", + "渡火者的智慧" + ], + "abbreviation": [], + "obtain": "火本", + "number": "14003" + }, + "被怜爱的少女": { + "element": [ + "远方的少女之心", + "少女飘摇的思念", + "少女苦短的良辰", + "少女片刻的闲暇", + "少女易逝的芳颜" + ], + "abbreviation": [], + "obtain": "风本", + "number": "14004" + }, + "染血的骑士道": { + "element": [ + "染血的铁之心", + "染血的黑之羽", + "染血骑士之时", + "染血的骑士之杯", + "染血的铁假面" + ], + "abbreviation": [], + "obtain": "宗室本", + "number": "15008" + }, + "炽烈的炎之魔女": { + "element": [ + "魔女的炎之花", + "魔女的常燃之羽", + "魔女的破灭之时", + "魔女的心之火", + "焦灼的魔女帽" + ], + "abbreviation": [], + "obtain": "火本", + "number": "15006" + }, + "昔日宗室之仪": { + "element": [ + "宗室之花", + "宗室之翎", + "宗室时计", + "宗室银瓮", + "宗室面具" + ], + "abbreviation": [], + "obtain": "宗室本", + "number": "15007" + }, + "翠绿之影": { + "element": [ + "野花记忆的绿野", + "猎人青翠的箭羽", + "翠绿猎人的笃定", + "翠绿猎人的容器", + "翠绿的猎人之冠" + ], + "abbreviation": [], + "obtain": "风本", + "number": "15002" + }, + "冰风迷途的勇士": { + "element": [ + "历经风雪的思念", + "摧冰而行的执望", + "冰雪故园的终期", + "遍结寒霜的傲骨", + "破冰踏雪的回音" + ], + "abbreviation": [], + "obtain": "冰本", + "number": "14001" + }, + "沉沦之心": { + "element": [ + "饰金胸花", + "追忆之风", + "坚铜罗盘", + "沉波之盏", + "酒渍船帽" + ], + "abbreviation": [], + "obtain": "冰本", + "number": "15004" + }, + "悠古的磐岩": { + "element": [ + "磐陀裂生之花", + "嵯峨群峰之翼", + "星罗圭璧之晷", + "巉岩琢塑之樽", + "不动玄石之相" + ], + "abbreviation": [], + "obtain": "岩本", + "number": "14005" + }, + "逆飞的流星": { + "element": [ + "夏祭之花", + "夏祭终末", + "夏祭之刻", + "夏祭水玉", + "夏祭之面" + ], + "abbreviation": [], + "obtain": "岩本", + "number": "14006" + }, + "千岩牢固": { + "element": [ + "勋绩之花", + "昭武翎羽", + "金铜时晷", + "盟誓金爵", + "将帅兜鍪" + ], + "abbreviation": [], + "obtain": "苍白", + "number": "15017" + }, + "苍白之火": { + "element": [ + "无垢之花", + "贤医之羽", + "停摆之刻", + "超越之盏", + "嗤笑之面" + ], + "abbreviation": [], + "obtain": "苍白", + "number": "15018" + }, + "追忆之注连": { + "element": [ + "羁缠之花", + "思忆之矢", + "朝露之时", + "祈望之心", + "无常之面" + ], + "abbreviation": [], + "obtain": "充能", + "number": "15019" + }, + "绝缘之旗印": { + "element": [ + "明威之镡", + "切落之羽", + "雷云之笼", + "绯花之壶", + "华饰之兜" + ], + "abbreviation": [], + "obtain": "充能", + "number": "15020" + }, + "华馆梦醒形骸记": { + "element": [ + "荣花之期", + "华馆之羽", + "众生之谣", + "梦醒之瓢", + "形骸之笠" + ], + "abbreviation": [], + "obtain": "华馆", + "number": "15021" + }, + "海染砗磲": { + "element": [ + "海染之花", + "渊宫之羽", + "离别之贝", + "真珠之笼", + "海祇之冠" + ], + "abbreviation": [], + "obtain": "华馆", + "number": "15022" + }, + "辰砂往生录": { + "element": [ + "生灵之华", + "潜光片羽", + "阳辔之遗", + "结契之刻", + "虺雷之姿" + ], + "abbreviation": [], + "obtain": "余响", + "number": "15023" + }, + "来歆余响": { + "element": [ + "魂香之花", + "垂玉之叶", + "祝祀之凭", + "涌泉之盏", + "浮溯之珏" + ], + "abbreviation": [], + "obtain": "余响", + "number": "15024" + } +} \ No newline at end of file diff --git a/src/artifact_collect/artifact_property.json b/src/artifact_collect/artifact_property.json new file mode 100644 index 0000000..9169f60 --- /dev/null +++ b/src/artifact_collect/artifact_property.json @@ -0,0 +1,68 @@ +[ + { + "name": "生之花", + "property_list": [ + "生命数值加成" + ] + }, + { + "name": "死之羽", + "property_list": [ + "攻击数值加成" + ] + }, + { + "name": "时之沙", + "property_list": [ + "生命百分比加成", + "攻击百分比加成", + "防御百分比加成", + "元素精通", + "元素充能效率" + ] + }, + { + "name": "空之杯", + "property_list": [ + "生命百分比加成", + "攻击百分比加成", + "防御百分比加成", + "元素精通", + "风元素伤害加成", + "火元素伤害加成", + "水元素伤害加成", + "冰元素伤害加成", + "岩元素伤害加成", + "雷元素伤害加成", + "草元素伤害加成", + "物理伤害百分比加成" + ] + }, + { + "name": "理之冠", + "property_list": [ + "生命百分比加成", + "攻击百分比加成", + "防御百分比加成", + "元素精通", + "暴击率百分比加成", + "暴击伤害百分比加成", + "治疗百分比加成" + ] + }, + { + "name": "副词条", + "property_list": [ + "生命数值加成", + "生命百分比加成", + "攻击数值加成", + "攻击百分比加成", + "防御数值加成", + "防御百分比加成", + "元素精通", + "元素充能效率", + "暴击率百分比加成", + "暴击伤害百分比加成" + ] + } +] \ No newline at end of file diff --git a/artifact_collect/icon/0.png b/src/artifact_collect/icon/0.png similarity index 100% rename from artifact_collect/icon/0.png rename to src/artifact_collect/icon/0.png diff --git a/artifact_collect/icon/1.png b/src/artifact_collect/icon/1.png similarity index 100% rename from artifact_collect/icon/1.png rename to src/artifact_collect/icon/1.png diff --git a/artifact_collect/icon/14001_0.png b/src/artifact_collect/icon/14001_0.png similarity index 100% rename from artifact_collect/icon/14001_0.png rename to src/artifact_collect/icon/14001_0.png diff --git a/artifact_collect/icon/14001_1.png b/src/artifact_collect/icon/14001_1.png similarity index 100% rename from artifact_collect/icon/14001_1.png rename to src/artifact_collect/icon/14001_1.png diff --git a/artifact_collect/icon/14001_2.png b/src/artifact_collect/icon/14001_2.png similarity index 100% rename from artifact_collect/icon/14001_2.png rename to src/artifact_collect/icon/14001_2.png diff --git a/artifact_collect/icon/14001_3.png b/src/artifact_collect/icon/14001_3.png similarity index 100% rename from artifact_collect/icon/14001_3.png rename to src/artifact_collect/icon/14001_3.png diff --git a/artifact_collect/icon/14001_4.png b/src/artifact_collect/icon/14001_4.png similarity index 100% rename from artifact_collect/icon/14001_4.png rename to src/artifact_collect/icon/14001_4.png diff --git a/artifact_collect/icon/14002_0.png b/src/artifact_collect/icon/14002_0.png similarity index 100% rename from artifact_collect/icon/14002_0.png rename to src/artifact_collect/icon/14002_0.png diff --git a/artifact_collect/icon/14002_1.png b/src/artifact_collect/icon/14002_1.png similarity index 100% rename from artifact_collect/icon/14002_1.png rename to src/artifact_collect/icon/14002_1.png diff --git a/artifact_collect/icon/14002_2.png b/src/artifact_collect/icon/14002_2.png similarity index 100% rename from artifact_collect/icon/14002_2.png rename to src/artifact_collect/icon/14002_2.png diff --git a/artifact_collect/icon/14002_3.png b/src/artifact_collect/icon/14002_3.png similarity index 100% rename from artifact_collect/icon/14002_3.png rename to src/artifact_collect/icon/14002_3.png diff --git a/artifact_collect/icon/14002_4.png b/src/artifact_collect/icon/14002_4.png similarity index 100% rename from artifact_collect/icon/14002_4.png rename to src/artifact_collect/icon/14002_4.png diff --git a/artifact_collect/icon/14003_0.png b/src/artifact_collect/icon/14003_0.png similarity index 100% rename from artifact_collect/icon/14003_0.png rename to src/artifact_collect/icon/14003_0.png diff --git a/artifact_collect/icon/14003_1.png b/src/artifact_collect/icon/14003_1.png similarity index 100% rename from artifact_collect/icon/14003_1.png rename to src/artifact_collect/icon/14003_1.png diff --git a/artifact_collect/icon/14003_2.png b/src/artifact_collect/icon/14003_2.png similarity index 100% rename from artifact_collect/icon/14003_2.png rename to src/artifact_collect/icon/14003_2.png diff --git a/artifact_collect/icon/14003_3.png b/src/artifact_collect/icon/14003_3.png similarity index 100% rename from artifact_collect/icon/14003_3.png rename to src/artifact_collect/icon/14003_3.png diff --git a/artifact_collect/icon/14003_4.png b/src/artifact_collect/icon/14003_4.png similarity index 100% rename from artifact_collect/icon/14003_4.png rename to src/artifact_collect/icon/14003_4.png diff --git a/artifact_collect/icon/14004_0.png b/src/artifact_collect/icon/14004_0.png similarity index 100% rename from artifact_collect/icon/14004_0.png rename to src/artifact_collect/icon/14004_0.png diff --git a/artifact_collect/icon/14004_1.png b/src/artifact_collect/icon/14004_1.png similarity index 100% rename from artifact_collect/icon/14004_1.png rename to src/artifact_collect/icon/14004_1.png diff --git a/artifact_collect/icon/14004_2.png b/src/artifact_collect/icon/14004_2.png similarity index 100% rename from artifact_collect/icon/14004_2.png rename to src/artifact_collect/icon/14004_2.png diff --git a/artifact_collect/icon/14004_3.png b/src/artifact_collect/icon/14004_3.png similarity index 100% rename from artifact_collect/icon/14004_3.png rename to src/artifact_collect/icon/14004_3.png diff --git a/artifact_collect/icon/14004_4.png b/src/artifact_collect/icon/14004_4.png similarity index 100% rename from artifact_collect/icon/14004_4.png rename to src/artifact_collect/icon/14004_4.png diff --git a/artifact_collect/icon/14005_0.png b/src/artifact_collect/icon/14005_0.png similarity index 100% rename from artifact_collect/icon/14005_0.png rename to src/artifact_collect/icon/14005_0.png diff --git a/artifact_collect/icon/14005_1.png b/src/artifact_collect/icon/14005_1.png similarity index 100% rename from artifact_collect/icon/14005_1.png rename to src/artifact_collect/icon/14005_1.png diff --git a/artifact_collect/icon/14005_2.png b/src/artifact_collect/icon/14005_2.png similarity index 100% rename from artifact_collect/icon/14005_2.png rename to src/artifact_collect/icon/14005_2.png diff --git a/artifact_collect/icon/14005_3.png b/src/artifact_collect/icon/14005_3.png similarity index 100% rename from artifact_collect/icon/14005_3.png rename to src/artifact_collect/icon/14005_3.png diff --git a/artifact_collect/icon/14005_4.png b/src/artifact_collect/icon/14005_4.png similarity index 100% rename from artifact_collect/icon/14005_4.png rename to src/artifact_collect/icon/14005_4.png diff --git a/artifact_collect/icon/14006_0.png b/src/artifact_collect/icon/14006_0.png similarity index 100% rename from artifact_collect/icon/14006_0.png rename to src/artifact_collect/icon/14006_0.png diff --git a/artifact_collect/icon/14006_1.png b/src/artifact_collect/icon/14006_1.png similarity index 100% rename from artifact_collect/icon/14006_1.png rename to src/artifact_collect/icon/14006_1.png diff --git a/artifact_collect/icon/14006_2.png b/src/artifact_collect/icon/14006_2.png similarity index 100% rename from artifact_collect/icon/14006_2.png rename to src/artifact_collect/icon/14006_2.png diff --git a/artifact_collect/icon/14006_3.png b/src/artifact_collect/icon/14006_3.png similarity index 100% rename from artifact_collect/icon/14006_3.png rename to src/artifact_collect/icon/14006_3.png diff --git a/artifact_collect/icon/14006_4.png b/src/artifact_collect/icon/14006_4.png similarity index 100% rename from artifact_collect/icon/14006_4.png rename to src/artifact_collect/icon/14006_4.png diff --git a/artifact_collect/icon/15001_0.png b/src/artifact_collect/icon/15001_0.png similarity index 100% rename from artifact_collect/icon/15001_0.png rename to src/artifact_collect/icon/15001_0.png diff --git a/artifact_collect/icon/15001_1.png b/src/artifact_collect/icon/15001_1.png similarity index 100% rename from artifact_collect/icon/15001_1.png rename to src/artifact_collect/icon/15001_1.png diff --git a/artifact_collect/icon/15001_2.png b/src/artifact_collect/icon/15001_2.png similarity index 100% rename from artifact_collect/icon/15001_2.png rename to src/artifact_collect/icon/15001_2.png diff --git a/artifact_collect/icon/15001_3.png b/src/artifact_collect/icon/15001_3.png similarity index 100% rename from artifact_collect/icon/15001_3.png rename to src/artifact_collect/icon/15001_3.png diff --git a/artifact_collect/icon/15001_4.png b/src/artifact_collect/icon/15001_4.png similarity index 100% rename from artifact_collect/icon/15001_4.png rename to src/artifact_collect/icon/15001_4.png diff --git a/artifact_collect/icon/15002_0.png b/src/artifact_collect/icon/15002_0.png similarity index 100% rename from artifact_collect/icon/15002_0.png rename to src/artifact_collect/icon/15002_0.png diff --git a/artifact_collect/icon/15002_1.png b/src/artifact_collect/icon/15002_1.png similarity index 100% rename from artifact_collect/icon/15002_1.png rename to src/artifact_collect/icon/15002_1.png diff --git a/artifact_collect/icon/15002_2.png b/src/artifact_collect/icon/15002_2.png similarity index 100% rename from artifact_collect/icon/15002_2.png rename to src/artifact_collect/icon/15002_2.png diff --git a/artifact_collect/icon/15002_3.png b/src/artifact_collect/icon/15002_3.png similarity index 100% rename from artifact_collect/icon/15002_3.png rename to src/artifact_collect/icon/15002_3.png diff --git a/artifact_collect/icon/15002_4.png b/src/artifact_collect/icon/15002_4.png similarity index 100% rename from artifact_collect/icon/15002_4.png rename to src/artifact_collect/icon/15002_4.png diff --git a/artifact_collect/icon/15003_0.png b/src/artifact_collect/icon/15003_0.png similarity index 100% rename from artifact_collect/icon/15003_0.png rename to src/artifact_collect/icon/15003_0.png diff --git a/artifact_collect/icon/15003_1.png b/src/artifact_collect/icon/15003_1.png similarity index 100% rename from artifact_collect/icon/15003_1.png rename to src/artifact_collect/icon/15003_1.png diff --git a/artifact_collect/icon/15003_2.png b/src/artifact_collect/icon/15003_2.png similarity index 100% rename from artifact_collect/icon/15003_2.png rename to src/artifact_collect/icon/15003_2.png diff --git a/artifact_collect/icon/15003_3.png b/src/artifact_collect/icon/15003_3.png similarity index 100% rename from artifact_collect/icon/15003_3.png rename to src/artifact_collect/icon/15003_3.png diff --git a/artifact_collect/icon/15003_4.png b/src/artifact_collect/icon/15003_4.png similarity index 100% rename from artifact_collect/icon/15003_4.png rename to src/artifact_collect/icon/15003_4.png diff --git a/artifact_collect/icon/15004_0.png b/src/artifact_collect/icon/15004_0.png similarity index 100% rename from artifact_collect/icon/15004_0.png rename to src/artifact_collect/icon/15004_0.png diff --git a/artifact_collect/icon/15004_1.png b/src/artifact_collect/icon/15004_1.png similarity index 100% rename from artifact_collect/icon/15004_1.png rename to src/artifact_collect/icon/15004_1.png diff --git a/artifact_collect/icon/15004_2.png b/src/artifact_collect/icon/15004_2.png similarity index 100% rename from artifact_collect/icon/15004_2.png rename to src/artifact_collect/icon/15004_2.png diff --git a/artifact_collect/icon/15004_3.png b/src/artifact_collect/icon/15004_3.png similarity index 100% rename from artifact_collect/icon/15004_3.png rename to src/artifact_collect/icon/15004_3.png diff --git a/artifact_collect/icon/15004_4.png b/src/artifact_collect/icon/15004_4.png similarity index 100% rename from artifact_collect/icon/15004_4.png rename to src/artifact_collect/icon/15004_4.png diff --git a/artifact_collect/icon/15005_0.png b/src/artifact_collect/icon/15005_0.png similarity index 100% rename from artifact_collect/icon/15005_0.png rename to src/artifact_collect/icon/15005_0.png diff --git a/artifact_collect/icon/15005_1.png b/src/artifact_collect/icon/15005_1.png similarity index 100% rename from artifact_collect/icon/15005_1.png rename to src/artifact_collect/icon/15005_1.png diff --git a/artifact_collect/icon/15005_2.png b/src/artifact_collect/icon/15005_2.png similarity index 100% rename from artifact_collect/icon/15005_2.png rename to src/artifact_collect/icon/15005_2.png diff --git a/artifact_collect/icon/15005_3.png b/src/artifact_collect/icon/15005_3.png similarity index 100% rename from artifact_collect/icon/15005_3.png rename to src/artifact_collect/icon/15005_3.png diff --git a/artifact_collect/icon/15005_4.png b/src/artifact_collect/icon/15005_4.png similarity index 100% rename from artifact_collect/icon/15005_4.png rename to src/artifact_collect/icon/15005_4.png diff --git a/artifact_collect/icon/15006_0.png b/src/artifact_collect/icon/15006_0.png similarity index 100% rename from artifact_collect/icon/15006_0.png rename to src/artifact_collect/icon/15006_0.png diff --git a/artifact_collect/icon/15006_1.png b/src/artifact_collect/icon/15006_1.png similarity index 100% rename from artifact_collect/icon/15006_1.png rename to src/artifact_collect/icon/15006_1.png diff --git a/artifact_collect/icon/15006_2.png b/src/artifact_collect/icon/15006_2.png similarity index 100% rename from artifact_collect/icon/15006_2.png rename to src/artifact_collect/icon/15006_2.png diff --git a/artifact_collect/icon/15006_3.png b/src/artifact_collect/icon/15006_3.png similarity index 100% rename from artifact_collect/icon/15006_3.png rename to src/artifact_collect/icon/15006_3.png diff --git a/artifact_collect/icon/15006_4.png b/src/artifact_collect/icon/15006_4.png similarity index 100% rename from artifact_collect/icon/15006_4.png rename to src/artifact_collect/icon/15006_4.png diff --git a/artifact_collect/icon/15007_0.png b/src/artifact_collect/icon/15007_0.png similarity index 100% rename from artifact_collect/icon/15007_0.png rename to src/artifact_collect/icon/15007_0.png diff --git a/artifact_collect/icon/15007_1.png b/src/artifact_collect/icon/15007_1.png similarity index 100% rename from artifact_collect/icon/15007_1.png rename to src/artifact_collect/icon/15007_1.png diff --git a/artifact_collect/icon/15007_2.png b/src/artifact_collect/icon/15007_2.png similarity index 100% rename from artifact_collect/icon/15007_2.png rename to src/artifact_collect/icon/15007_2.png diff --git a/artifact_collect/icon/15007_3.png b/src/artifact_collect/icon/15007_3.png similarity index 100% rename from artifact_collect/icon/15007_3.png rename to src/artifact_collect/icon/15007_3.png diff --git a/artifact_collect/icon/15007_4.png b/src/artifact_collect/icon/15007_4.png similarity index 100% rename from artifact_collect/icon/15007_4.png rename to src/artifact_collect/icon/15007_4.png diff --git a/artifact_collect/icon/15008_0.png b/src/artifact_collect/icon/15008_0.png similarity index 100% rename from artifact_collect/icon/15008_0.png rename to src/artifact_collect/icon/15008_0.png diff --git a/artifact_collect/icon/15008_1.png b/src/artifact_collect/icon/15008_1.png similarity index 100% rename from artifact_collect/icon/15008_1.png rename to src/artifact_collect/icon/15008_1.png diff --git a/artifact_collect/icon/15008_2.png b/src/artifact_collect/icon/15008_2.png similarity index 100% rename from artifact_collect/icon/15008_2.png rename to src/artifact_collect/icon/15008_2.png diff --git a/artifact_collect/icon/15008_3.png b/src/artifact_collect/icon/15008_3.png similarity index 100% rename from artifact_collect/icon/15008_3.png rename to src/artifact_collect/icon/15008_3.png diff --git a/artifact_collect/icon/15008_4.png b/src/artifact_collect/icon/15008_4.png similarity index 100% rename from artifact_collect/icon/15008_4.png rename to src/artifact_collect/icon/15008_4.png diff --git a/artifact_collect/icon/15017_0.png b/src/artifact_collect/icon/15017_0.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15017_0.png rename to src/artifact_collect/icon/15017_0.png diff --git a/artifact_collect/icon/15017_1.png b/src/artifact_collect/icon/15017_1.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15017_1.png rename to src/artifact_collect/icon/15017_1.png diff --git a/artifact_collect/icon/15017_2.png b/src/artifact_collect/icon/15017_2.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15017_2.png rename to src/artifact_collect/icon/15017_2.png diff --git a/artifact_collect/icon/15017_3.png b/src/artifact_collect/icon/15017_3.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15017_3.png rename to src/artifact_collect/icon/15017_3.png diff --git a/artifact_collect/icon/15017_4.png b/src/artifact_collect/icon/15017_4.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15017_4.png rename to src/artifact_collect/icon/15017_4.png diff --git a/artifact_collect/icon/15018_0.png b/src/artifact_collect/icon/15018_0.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15018_0.png rename to src/artifact_collect/icon/15018_0.png diff --git a/artifact_collect/icon/15018_1.png b/src/artifact_collect/icon/15018_1.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15018_1.png rename to src/artifact_collect/icon/15018_1.png diff --git a/artifact_collect/icon/15018_2.png b/src/artifact_collect/icon/15018_2.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15018_2.png rename to src/artifact_collect/icon/15018_2.png diff --git a/artifact_collect/icon/15018_3.png b/src/artifact_collect/icon/15018_3.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15018_3.png rename to src/artifact_collect/icon/15018_3.png diff --git a/artifact_collect/icon/15018_4.png b/src/artifact_collect/icon/15018_4.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15018_4.png rename to src/artifact_collect/icon/15018_4.png diff --git a/artifact_collect/icon/15019_0.png b/src/artifact_collect/icon/15019_0.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15019_0.png rename to src/artifact_collect/icon/15019_0.png diff --git a/artifact_collect/icon/15019_1.png b/src/artifact_collect/icon/15019_1.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15019_1.png rename to src/artifact_collect/icon/15019_1.png diff --git a/artifact_collect/icon/15019_2.png b/src/artifact_collect/icon/15019_2.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15019_2.png rename to src/artifact_collect/icon/15019_2.png diff --git a/artifact_collect/icon/15019_3.png b/src/artifact_collect/icon/15019_3.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15019_3.png rename to src/artifact_collect/icon/15019_3.png diff --git a/artifact_collect/icon/15019_4.png b/src/artifact_collect/icon/15019_4.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15019_4.png rename to src/artifact_collect/icon/15019_4.png diff --git a/artifact_collect/icon/15020_0.png b/src/artifact_collect/icon/15020_0.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15020_0.png rename to src/artifact_collect/icon/15020_0.png diff --git a/artifact_collect/icon/15020_1.png b/src/artifact_collect/icon/15020_1.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15020_1.png rename to src/artifact_collect/icon/15020_1.png diff --git a/artifact_collect/icon/15020_2.png b/src/artifact_collect/icon/15020_2.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15020_2.png rename to src/artifact_collect/icon/15020_2.png diff --git a/artifact_collect/icon/15020_3.png b/src/artifact_collect/icon/15020_3.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15020_3.png rename to src/artifact_collect/icon/15020_3.png diff --git a/artifact_collect/icon/15020_4.png b/src/artifact_collect/icon/15020_4.png old mode 100755 new mode 100644 similarity index 100% rename from artifact_collect/icon/15020_4.png rename to src/artifact_collect/icon/15020_4.png diff --git a/artifact_collect/icon/15021_0.png b/src/artifact_collect/icon/15021_0.png similarity index 100% rename from artifact_collect/icon/15021_0.png rename to src/artifact_collect/icon/15021_0.png diff --git a/artifact_collect/icon/15021_1.png b/src/artifact_collect/icon/15021_1.png similarity index 100% rename from artifact_collect/icon/15021_1.png rename to src/artifact_collect/icon/15021_1.png diff --git a/artifact_collect/icon/15021_2.png b/src/artifact_collect/icon/15021_2.png similarity index 100% rename from artifact_collect/icon/15021_2.png rename to src/artifact_collect/icon/15021_2.png diff --git a/artifact_collect/icon/15021_3.png b/src/artifact_collect/icon/15021_3.png similarity index 100% rename from artifact_collect/icon/15021_3.png rename to src/artifact_collect/icon/15021_3.png diff --git a/artifact_collect/icon/15021_4.png b/src/artifact_collect/icon/15021_4.png similarity index 100% rename from artifact_collect/icon/15021_4.png rename to src/artifact_collect/icon/15021_4.png diff --git a/artifact_collect/icon/15022_0.png b/src/artifact_collect/icon/15022_0.png similarity index 100% rename from artifact_collect/icon/15022_0.png rename to src/artifact_collect/icon/15022_0.png diff --git a/artifact_collect/icon/15022_1.png b/src/artifact_collect/icon/15022_1.png similarity index 100% rename from artifact_collect/icon/15022_1.png rename to src/artifact_collect/icon/15022_1.png diff --git a/artifact_collect/icon/15022_2.png b/src/artifact_collect/icon/15022_2.png similarity index 100% rename from artifact_collect/icon/15022_2.png rename to src/artifact_collect/icon/15022_2.png diff --git a/artifact_collect/icon/15022_3.png b/src/artifact_collect/icon/15022_3.png similarity index 100% rename from artifact_collect/icon/15022_3.png rename to src/artifact_collect/icon/15022_3.png diff --git a/artifact_collect/icon/15022_4.png b/src/artifact_collect/icon/15022_4.png similarity index 100% rename from artifact_collect/icon/15022_4.png rename to src/artifact_collect/icon/15022_4.png diff --git a/artifact_collect/icon/15023_0.png b/src/artifact_collect/icon/15023_0.png similarity index 100% rename from artifact_collect/icon/15023_0.png rename to src/artifact_collect/icon/15023_0.png diff --git a/artifact_collect/icon/15023_1.png b/src/artifact_collect/icon/15023_1.png similarity index 100% rename from artifact_collect/icon/15023_1.png rename to src/artifact_collect/icon/15023_1.png diff --git a/artifact_collect/icon/15023_2.png b/src/artifact_collect/icon/15023_2.png similarity index 100% rename from artifact_collect/icon/15023_2.png rename to src/artifact_collect/icon/15023_2.png diff --git a/artifact_collect/icon/15023_3.png b/src/artifact_collect/icon/15023_3.png similarity index 100% rename from artifact_collect/icon/15023_3.png rename to src/artifact_collect/icon/15023_3.png diff --git a/artifact_collect/icon/15023_4.png b/src/artifact_collect/icon/15023_4.png similarity index 100% rename from artifact_collect/icon/15023_4.png rename to src/artifact_collect/icon/15023_4.png diff --git a/artifact_collect/icon/15024_0.png b/src/artifact_collect/icon/15024_0.png similarity index 100% rename from artifact_collect/icon/15024_0.png rename to src/artifact_collect/icon/15024_0.png diff --git a/artifact_collect/icon/15024_1.png b/src/artifact_collect/icon/15024_1.png similarity index 100% rename from artifact_collect/icon/15024_1.png rename to src/artifact_collect/icon/15024_1.png diff --git a/artifact_collect/icon/15024_2.png b/src/artifact_collect/icon/15024_2.png similarity index 100% rename from artifact_collect/icon/15024_2.png rename to src/artifact_collect/icon/15024_2.png diff --git a/artifact_collect/icon/15024_3.png b/src/artifact_collect/icon/15024_3.png similarity index 100% rename from artifact_collect/icon/15024_3.png rename to src/artifact_collect/icon/15024_3.png diff --git a/artifact_collect/icon/15024_4.png b/src/artifact_collect/icon/15024_4.png similarity index 100% rename from artifact_collect/icon/15024_4.png rename to src/artifact_collect/icon/15024_4.png diff --git a/artifact_collect/icon/2.png b/src/artifact_collect/icon/2.png similarity index 100% rename from artifact_collect/icon/2.png rename to src/artifact_collect/icon/2.png diff --git a/artifact_collect/icon/3.png b/src/artifact_collect/icon/3.png similarity index 100% rename from artifact_collect/icon/3.png rename to src/artifact_collect/icon/3.png diff --git a/artifact_collect/icon/4.png b/src/artifact_collect/icon/4.png similarity index 100% rename from artifact_collect/icon/4.png rename to src/artifact_collect/icon/4.png diff --git a/artifact_collect/icon/background.png b/src/artifact_collect/icon/background.png similarity index 100% rename from artifact_collect/icon/background.png rename to src/artifact_collect/icon/background.png diff --git a/artifact_collect/json_rw.py b/src/artifact_collect/json_rw.py similarity index 76% rename from artifact_collect/json_rw.py rename to src/artifact_collect/json_rw.py index bee42e4..62c76d4 100644 --- a/artifact_collect/json_rw.py +++ b/src/artifact_collect/json_rw.py @@ -1,27 +1,27 @@ - -import os import json +import os + +from config import MAX_STAMINA -from ..config import MAX_STAMINA from .Artifact import ARTIFACT_LIST FILE_PATH = os.path.dirname(__file__) -USER_INFO_PATH = os.path.join(FILE_PATH,"user_info.json") - +USER_INFO_PATH = os.path.join(FILE_PATH, "user_info.json") user_info = {} def save_user_info(): - with open(USER_INFO_PATH,'w',encoding='UTF-8') as f: - json.dump(user_info,f,ensure_ascii=False) + with open(USER_INFO_PATH, 'w', encoding='UTF-8') as f: + json.dump(user_info, f, ensure_ascii=False) + # 检查user_info.json是否存在,没有创建空的 if not os.path.exists(USER_INFO_PATH): save_user_info() # 读取user_info.json的信息 -with open(USER_INFO_PATH,'r',encoding='UTF-8') as f: +with open(USER_INFO_PATH, 'r', encoding='UTF-8') as f: user_info = json.load(f) # 检查user_info里边圣遗物的名称是不是和 artifact_list.json 对的上,对不上的话直接删除,不然后边会报错 @@ -31,14 +31,13 @@ def save_user_info(): for artifact in user_info[uid]["warehouse"]: suit_name = artifact["suit_name"] artifact_name = artifact["name"] - if ( suit_name in ARTIFACT_LIST ) and ( artifact_name in ARTIFACT_LIST[suit_name]["element"]): + if (suit_name in ARTIFACT_LIST) and (artifact_name in ARTIFACT_LIST[suit_name]["element"]): temp_user_artifact_list.append(artifact) user_info[uid]["warehouse"] = temp_user_artifact_list - -def init_user_info(uid:str): +def init_user_info(uid: str): if not (uid in user_info): user_info[uid] = {} user_info[uid]["stamina"] = 120 @@ -47,14 +46,10 @@ def init_user_info(uid:str): save_user_info() + def updata_uid_stamina(): # 更新体力值恢复,这个函数执行一次所有人体力值+1 for uid in user_info: if user_info[uid]["stamina"] < MAX_STAMINA: user_info[uid]["stamina"] += 1 save_user_info() - - - - - diff --git a/src/artifact_collect/property_list.json b/src/artifact_collect/property_list.json new file mode 100644 index 0000000..be9a9a9 --- /dev/null +++ b/src/artifact_collect/property_list.json @@ -0,0 +1,204 @@ +{ + "main": { + "生命数值加成": { + "txt": "生命值", + "initial_value": 717, + "growth_value": 203.15, + "max": 4780 + }, + "生命百分比加成": { + "txt": "生命值", + "initial_value": 0.07, + "growth_value": 0.0198, + "max": 0.466 + }, + "攻击数值加成": { + "txt": "攻击力", + "initial_value": 47, + "growth_value": 13.2, + "max": 311 + }, + "攻击百分比加成": { + "txt": "攻击力", + "initial_value": 0.07, + "growth_value": 0.0198, + "max": 0.466 + }, + "防御百分比加成": { + "txt": "防御力", + "initial_value": 0.087, + "growth_value": 0.0248, + "max": 0.583 + }, + "元素精通": { + "txt": "元素精通", + "initial_value": 28, + "growth_value": 7.95, + "max": 187 + }, + "元素充能效率": { + "txt": "元素充能效率", + "initial_value": 0.087, + "growth_value": 0.02155, + "max": 0.518 + }, + "暴击率百分比加成": { + "txt": "暴击率", + "initial_value": 0.047, + "growth_value": 0.0112, + "max": 0.311 + }, + "暴击伤害百分比加成": { + "txt": "暴击伤害", + "initial_value": 0.093, + "growth_value": 0.02845, + "max": 0.622 + }, + "治疗百分比加成": { + "txt": "治疗加成", + "initial_value": 0.054, + "growth_value": 0.01525, + "max": 0.359 + }, + "物理伤害百分比加成": { + "txt": "物理伤害加成", + "initial_value": 0.087, + "growth_value": 0.0248, + "max": 0.583 + }, + "风元素伤害加成": { + "txt": "风元素伤害加成", + "initial_value": 0.07, + "growth_value": 0.0198, + "max": 0.466 + }, + "火元素伤害加成": { + "txt": "火元素伤害加成", + "initial_value": 0.07, + "growth_value": 0.0198, + "max": 0.466 + }, + "水元素伤害加成": { + "txt": "水元素伤害加成", + "initial_value": 0.07, + "growth_value": 0.0198, + "max": 0.466 + }, + "冰元素伤害加成": { + "txt": "冰元素伤害加成", + "initial_value": 0.07, + "growth_value": 0.0198, + "max": 0.466 + }, + "雷元素伤害加成": { + "txt": "雷元素伤害加成", + "initial_value": 0.07, + "growth_value": 0.0198, + "max": 0.466 + }, + "草元素伤害加成": { + "txt": "草元素伤害加成", + "initial_value": 0.07, + "growth_value": 0.0198, + "max": 0.466 + }, + "岩元素伤害加成": { + "txt": "岩元素伤害加成", + "initial_value": 0.07, + "growth_value": 0.0198, + "max": 0.466 + } + }, + "secondary": { + "生命数值加成": { + "txt": "生命值", + "level": [ + 209, + 239, + 269, + 299 + ] + }, + "生命百分比加成": { + "txt": "生命值", + "level": [ + 0.041, + 0.047, + 0.053, + 0.058 + ] + }, + "攻击数值加成": { + "txt": "攻击力", + "level": [ + 14, + 16, + 18, + 19 + ] + }, + "攻击百分比加成": { + "txt": "攻击力", + "level": [ + 0.041, + 0.047, + 0.053, + 0.058 + ] + }, + "防御数值加成": { + "txt": "防御力", + "level": [ + 16, + 19, + 21, + 23 + ] + }, + "防御百分比加成": { + "txt": "防御力", + "level": [ + 0.051, + 0.058, + 0.066, + 0.073 + ] + }, + "元素精通": { + "txt": "元素精通", + "level": [ + 16, + 19, + 21, + 23 + ] + }, + "元素充能效率": { + "txt": "元素充能效率", + "level": [ + 0.045, + 0.052, + 0.058, + 0.065 + ] + }, + "暴击率百分比加成": { + "txt": "暴击率", + "level": [ + 0.027, + 0.031, + 0.035, + 0.039 + ] + }, + "暴击伤害百分比加成": { + "txt": "暴击伤害", + "level": [ + 0.054, + 0.062, + 0.070, + 0.078 + ] + } + } +} \ No newline at end of file diff --git a/artifact_collect/zh-cn.ttf b/src/artifact_collect/zh-cn.ttf similarity index 100% rename from artifact_collect/zh-cn.ttf rename to src/artifact_collect/zh-cn.ttf diff --git a/artifact_rate/__init__.py b/src/artifact_rate/__init__.py similarity index 97% rename from artifact_rate/__init__.py rename to src/artifact_rate/__init__.py index d2afca9..8d7a2ca 100644 --- a/artifact_rate/__init__.py +++ b/src/artifact_rate/__init__.py @@ -1,10 +1,10 @@ -from .artifact_eval import * -from hoshino import Service -import requests - from base64 import b64encode from io import BytesIO +from hoshino import Service + +from .artifact_eval import * + sv = Service("原神圣遗物评分") @@ -46,7 +46,7 @@ async def artifact_rate(bot, ev): err_msg = rate_result["full"]["message"] await bot.send(ev, f"发生了点小错误:\n{err_msg}\n*注:将在下版本加入属性修改", at_sender=True) return - format_result = f'圣遗物评分结果:\n主属性:{artifact_attr["main_item"]["name"]}\n{get_format_sub_item(artifact_attr)}'\ - f'------------------------------\n总分:{rate_result["total_percent"]}\n'\ + format_result = f'圣遗物评分结果:\n主属性:{artifact_attr["main_item"]["name"]}\n{get_format_sub_item(artifact_attr)}' \ + f'------------------------------\n总分:{rate_result["total_percent"]}\n' \ f'主词条:{rate_result["main_percent"]}\n副词条:{rate_result["sub_percent"]}\n评分、识图均来自genshin.pub' await bot.send(ev, format_result, at_sender=True) diff --git a/artifact_rate/artifact_eval.py b/src/artifact_rate/artifact_eval.py similarity index 99% rename from artifact_rate/artifact_eval.py rename to src/artifact_rate/artifact_eval.py index 3d3fe0e..267b9c4 100644 --- a/artifact_rate/artifact_eval.py +++ b/src/artifact_rate/artifact_eval.py @@ -1,7 +1,7 @@ -import requests - import json +import requests + ocr_url = "https://api.genshin.pub/api/v1/app/ocr" rate_url = "https://api.genshin.pub/api/v1/relic/rate" head = { @@ -42,6 +42,7 @@ async def rate_artifact(artifact_attr: dict): if __name__ == "__main__": from base64 import b64encode + with open('78.42.png', 'rb') as f: b64 = b64encode(f.read()).decode() print(rate_artifact(get_artifact_attr(b64))) diff --git a/src/asset_manager.py b/src/asset_manager.py new file mode 100644 index 0000000..624d51c --- /dev/null +++ b/src/asset_manager.py @@ -0,0 +1,130 @@ +import threading +import json +from urllib.parse import ParseResult as URL +from urllib.parse import urlparse +from collections import UserList +from typing import List, Union +from pathlib import Path +from sys import stdout +from io import BytesIO + +import aiofiles +import httpx +from PIL import Image + + +class BotAsset: + def __init__(self, path: Path): + if not path.is_file(): + raise TypeError(f"{path} not a file") + self.file = path + + def as_text(self, encoding='utf-8'): + with open(self.file, 'r', encoding=encoding) as asset_: + return asset_.read() + + def as_binary(self): + with open(self.file, 'rb') as asset_: + return asset_.read() + + async def async_as_binary(self): + async with aiofiles.open(self.file, 'rb') as asset_: + return await asset_.read() + + def as_bytestream(self): + binary_ = self.as_binary() + return BytesIO(binary_) + + def async_as_bytestream(self): + binary_ = await self.async_as_binary() + return BytesIO(binary_) + + def as_img(self): + return Image.open(self.file) + + async def async_as_img(self): + binary_ = await self.async_as_binary() + return Image.open(binary_) + + def as_json(self, encoding='utf-8'): + raw_json_ = self.as_text(encoding=encoding) + return json.loads(raw_json_) + + +# 提案 +# assets存储于固定目录 +# 重复字体/图像单次导入 + +class BotAssetManager: + def __init__(self, path: Path): + self.path = path + + def __truediv__(self, other): + new_path_ = self.path.joinpath(other) + if new_path_.is_file(): + return BotAsset(new_path_) + return new_path_ + + +class Downloader: + @staticmethod + def _validate(url: Union[str, URL]): + if isinstance(url, str): + url = urlparse(url) + if url.scheme in ['http', 'https']: + return True + return False + + @staticmethod + def _clear_prev_line(self): + stdout.write("\330[A\330[K\n") + + def _update_term_progress(self, filename: str): + strings = { + "bar": self.progress_char * round(self.progress * 10), + "filename": filename, + + } + + def _reset_progress(self): + self.progress = 0 + + def _update_avg_progress(self): + return 1 / len(self.file_list) + + def _progress_upd(self): + self.progress += self.avg_progress + self.count += 1 + + @property + def len(self): + return len(self.file_list) + + def download(self, url: Union[str, URL], dest: Union[str, Path]): + with httpx.Client(follow_redirects=True) as client_: + resp_ = client_.get(url) + filename = resp_.url.path.split('/')[-1] + if isinstance(dest, str): + dest = Path(dest) + with open(dest / filename, 'rb') as file_: + file_.write(resp_.read()) + with self.lock: + self._progress_upd() + + def __init__(self, file_list: List[Union[str, URL]], + progress_fmt: str = '{filename}|{bar}', + progress_char: str = '■', progress_width: int = 10): + self.file_list = UserList(file for file in file_list if self._validate(file)) + self.progress_fmt = progress_fmt + self.progress_char = progress_char + self.progress_width = progress_width + self.avg_progress = self._update_avg_progress() + self.progress = 0 + self.count = 0 + self.cache = {} + self.lock = threading.Lock() + + def __add__(self, other): + assert self._validate(other) + self.file_list.append(other) + self._update_avg_progress() diff --git a/gacha/__init__.py b/src/gacha/__init__.py similarity index 77% rename from gacha/__init__.py rename to src/gacha/__init__.py index 9f20f99..9bff6aa 100644 --- a/gacha/__init__.py +++ b/src/gacha/__init__.py @@ -1,11 +1,12 @@ -from hoshino import Service,priv -from .gacha import gacha_info , FILE_PATH , Gacha , POOL -from .pool_data import init_pool_list -import os import json +import os + +from config import Gacha10Limit, Gacha90Limit, Gacha180Limit +from hoshino import Service, priv from hoshino.util import DailyNumberLimiter -from ..config import Gacha10Limit,Gacha90Limit,Gacha180Limit +from .gacha import gacha_info, FILE_PATH, Gacha, POOL +from .pool_data import init_pool_list daily_limiter_10 = DailyNumberLimiter(Gacha10Limit) daily_limiter_90 = DailyNumberLimiter(Gacha90Limit) @@ -17,25 +18,21 @@ # 这个字典保存每个群对应的卡池是哪个,群号字符串为key,卡池名为value,群号不包含在字典key里卡池按默认DEFAULT_POOL } -def save_group_pool(): - with open(os.path.join(FILE_PATH,'gid_pool.json'),'w',encoding='UTF-8') as f: - json.dump(group_pool,f,ensure_ascii=False) +def save_group_pool(): + with open(os.path.join(FILE_PATH, 'gid_pool.json'), 'w', encoding='UTF-8') as f: + json.dump(group_pool, f, ensure_ascii=False) # 检查gid_pool.json是否存在,没有创建空的 -if not os.path.exists(os.path.join(FILE_PATH,'gid_pool.json')): +if not os.path.exists(os.path.join(FILE_PATH, 'gid_pool.json')): save_group_pool() - - # 读取gid_pool.json的信息 -with open(os.path.join(FILE_PATH,'gid_pool.json'),'r',encoding='UTF-8') as f: +with open(os.path.join(FILE_PATH, 'gid_pool.json'), 'r', encoding='UTF-8') as f: group_pool = json.load(f) - - @sv.on_prefix(["相遇之缘"], only_to_me=True) async def gacha_(bot, ev): gid = str(ev.group_id) if 'group_id' in dir(ev) else str(ev.guild_id) @@ -48,7 +45,8 @@ async def gacha_(bot, ev): else: G = Gacha() daily_limiter_10.increase(userid) - await bot.send(ev, G.gacha_10() , at_sender=True) + await bot.send(ev, G.gacha_10(), at_sender=True) + @sv.on_prefix(["纠缠之缘"], only_to_me=True) async def gacha_(bot, ev): @@ -62,8 +60,7 @@ async def gacha_(bot, ev): else: G = Gacha() daily_limiter_90.increase(userid) - await bot.send(ev, G.gacha_90(90) , at_sender=True) - + await bot.send(ev, G.gacha_90(90), at_sender=True) @sv.on_prefix(["原之井"], only_to_me=True) @@ -78,11 +75,10 @@ async def gacha_(bot, ev): G = Gacha(group_pool[gid]) else: G = Gacha() - await bot.send(ev, G.gacha_90(180) , at_sender=True) + await bot.send(ev, G.gacha_90(180), at_sender=True) - -@sv.on_prefix(["原神卡池","原神up","原神UP"]) +@sv.on_prefix(["原神卡池", "原神up", "原神UP"]) async def gacha_(bot, ev): gid = str(ev.group_id) if 'group_id' in dir(ev) else str(ev.guild_id) @@ -91,11 +87,11 @@ async def gacha_(bot, ev): else: info = gacha_info() - await bot.send(ev, info , at_sender=True) + await bot.send(ev, info, at_sender=True) -@sv.on_prefix(('原神卡池切换','原神切换卡池')) -async def set_pool(bot, ev): +@sv.on_prefix(('原神卡池切换', '原神切换卡池')) +async def set_pool(bot, ev): if not priv.check_priv(ev, priv.ADMIN): await bot.finish(ev, '只有群管理才能切换卡池', at_sender=True) @@ -106,7 +102,7 @@ async def set_pool(bot, ev): if gid in group_pool: group_pool[gid] = pool_name else: - group_pool.setdefault(gid,pool_name) + group_pool.setdefault(gid, pool_name) save_group_pool() await bot.send(ev, f"卡池已切换为 {pool_name} ") return @@ -122,5 +118,4 @@ async def set_pool(bot, ev): async def up_pool_(bot, ev): await bot.send(ev, '正在更新卡池') await init_pool_list() - await bot.send(ev,"更新卡池完成") - + await bot.send(ev, "更新卡池完成") diff --git a/gacha/gacha.py b/src/gacha/gacha.py similarity index 88% rename from gacha/gacha.py rename to src/gacha/gacha.py index a9acb7c..3fdd3a6 100644 --- a/gacha/gacha.py +++ b/src/gacha/gacha.py @@ -1,29 +1,27 @@ -from PIL import Image -from io import BytesIO -from .pool_data import POOL - +import base64 +import math import os import random -import math -import base64 - -FILE_PATH = os.path.dirname(__file__) -ICON_PATH = os.path.join(FILE_PATH,'icon') +from io import BytesIO +from PIL import Image +from .pool_data import POOL -DEFAULT_POOL = "常驻" # 默认卡池 +FILE_PATH = os.path.dirname(__file__) +ICON_PATH = os.path.join(FILE_PATH, 'icon') +DEFAULT_POOL = "常驻" # 默认卡池 class Gacha(object): - def __init__(self,_pool = DEFAULT_POOL): + def __init__(self, _pool=DEFAULT_POOL): # 实例化的时候就要传进来字符串表明要抽哪个卡池 self.pool = _pool - self.last_time_5 = "" # 记录上一次抽卡的5星是什么 - self.last_time_4 = "" # 记录上一次抽卡的4星是什么 + self.last_time_5 = "" # 记录上一次抽卡的5星是什么 + self.last_time_4 = "" # 记录上一次抽卡的4星是什么 # 保底计数,注意这个计数是从0开始的,每一次抽卡(包括第一次)之前都得+1 self.distance_5_star = 0 @@ -58,7 +56,6 @@ def __init__(self,_pool = DEFAULT_POOL): self._4_star_basic_probability = self.get_4_star_basic_probability() self.distance_frequency = self.get_distance_frequency() - @staticmethod def get_png_path(name): # 获取png文件路径,传入的参数是角色或武器名字,会自动在角色和武器文件夹搜索,找不到使用默认图标 @@ -74,7 +71,7 @@ def get_png_path(name): return os.path.join(ICON_PATH, "default.png") - def is_up(self,name): + def is_up(self, name): # 检查角色是否在UP里 # 如果name是一个空字符串表示是第一次抽到4星或5星 if name == "": @@ -87,13 +84,12 @@ def is_up(self,name): return False - - def is_star(self,name): + def is_star(self, name): # 检查角色或物品是几星的 # 返回对应的星星数 if (name in POOL[self.pool]['5_star_UP']) or (name in POOL[self.pool]['5_star_not_UP']): return "★★★★★" - if (name in POOL[self.pool]['4_star_UP']) or (name in POOL[self.pool]['4_star_not_UP']): # 4星常驻池就包含所有4星角色装备了 + if (name in POOL[self.pool]['4_star_UP']) or (name in POOL[self.pool]['4_star_not_UP']): # 4星常驻池就包含所有4星角色装备了 return "★★★★" return "★★★" @@ -130,14 +126,14 @@ def concat_pic(self, border=5): return des - def add_gacha_all_statistics(self,name): + def add_gacha_all_statistics(self, name): # 把每一次抽卡结果添加到gacha_all_statistics if name in self.gacha_all_statistics.keys(): self.gacha_all_statistics[name] += 1 else: self.gacha_all_statistics[name] = 1 - def update_last(self,name): + def update_last(self, name): # 这个方法用来更新第一次抽到4星或5星或UP的计数 if not self.last_4_up: if name in POOL[self.pool]['4_star_UP']: @@ -155,13 +151,13 @@ def update_last(self,name): if (name in POOL[self.pool]['5_star_not_UP']) or (name in POOL[self.pool]['5_star_UP']): self.last_5 = self.current_times + 1 - def is_guaranteed(self,frequency): + def is_guaranteed(self, frequency): # 检查本轮抽卡是不是全保底 - if frequency == 90 : - if self.gacha_rarity_statistics['5星'] == 1 and self.gacha_rarity_statistics['4星'] == 8: + if frequency == 90: + if self.gacha_rarity_statistics['5星'] == 1 and self.gacha_rarity_statistics['4星'] == 8: return True - if frequency == 180 : - if self.gacha_rarity_statistics['5星'] == 2 and self.gacha_rarity_statistics['4星'] == 16: + if frequency == 180: + if self.gacha_rarity_statistics['5星'] == 2 and self.gacha_rarity_statistics['4星'] == 16: return True return False @@ -170,11 +166,9 @@ def get_most_arms(self): if not self.gacha_all_statistics: raise KeyError(f"字典 self.gacha_all_statistics 是空的") most_value = max(self.gacha_all_statistics.values()) - for key,value in self.gacha_all_statistics.items(): - if most_value == value : - return {"name":key,"most":value} - - + for key, value in self.gacha_all_statistics.items(): + if most_value == value: + return {"name": key, "most": value} def get_up_probability(self): # 获取上一次抽卡抽到5星 UP 时,再次获取5星概率是多少 @@ -182,7 +176,6 @@ def get_up_probability(self): return 0.75 return 0.5 - def get_5_star_basic_probability(self): # 获取5星的基础概率 if self.pool.count("武器"): @@ -195,23 +188,19 @@ def get_4_star_basic_probability(self): return 0.060 return 0.051 - def get_distance_frequency(self): # 获取当前卡池的保底抽卡次数 if self.pool.count("武器"): return 80 return 90 - - - def get_5_star(self): # 先检查上次5星是否是UP,不是UP本次抽取必定是 UP, # 如果上次是UP,角色UP池本次有50%的概率还是 UP,50%概率非 UP, # 武器UP池本次有75%的概率还是 UP,25%概率非 UP,详情看UP_PROBABILITY # 先看是不是常驻池 - if self.pool == '常驻': + if self.pool == '常驻': return random.choice(POOL[self.pool]['5_star_not_UP']) # 下边是角色或武器的UP @@ -224,15 +213,13 @@ def get_5_star(self): else: return random.choice(POOL[self.pool]['5_star_UP']) - - def get_4_star(self): # 先检查上次4星是否是UP,不是UP本次抽取必定是 UP, # 如果上次是UP,角色UP池本次有50%的概率还是 UP,50%概率非 UP # 武器UP池本次有75%的概率还是UP,25%概率非 UP,详情看UP_PROBABILITY # 先看是不是常驻池 - if self.pool == '常驻': + if self.pool == '常驻': return random.choice(POOL[self.pool]['4_star_not_UP']) # 下边是角色或武器的UP @@ -261,7 +248,6 @@ def get_5_star_probability(self): else: return self._5_star_basic_probability + 0.06 * (self.distance_5_star - 73) - def gacha_one(self): # self.last_time_4表示上一个4星角色 # self.last_time_5表示上一个5星角色 @@ -277,9 +263,9 @@ def gacha_one(self): # 先检查是不是保底5星 if self.distance_5_star % self.distance_frequency == 0: self.gacha_rarity_statistics["5星"] += 1 - self.distance_5_star = 0 # 重置保底计数 - self.last_time_5 = self.get_5_star() # 抽一次卡,把结果赋值留给下一次抽卡判断 - return self.last_time_5 # 返回刚抽出的卡 + self.distance_5_star = 0 # 重置保底计数 + self.last_time_5 = self.get_5_star() # 抽一次卡,把结果赋值留给下一次抽卡判断 + return self.last_time_5 # 返回刚抽出的卡 # 检查是不是概率5星 if r < _5_star_probability: @@ -307,9 +293,6 @@ def gacha_one(self): self.gacha_rarity_statistics["3星"] += 1 return random.choice(POOL[self.pool]['3_star_not_UP']) - - - def gacha_10(self): # 抽10连 if not (self.pool in POOL.keys()): @@ -329,7 +312,7 @@ def gacha_10(self): self.add_gacha_all_statistics(new_gacha) # 把所有抽卡结果添加到gacha_all_statistics用于最后统计 - self.update_last(new_gacha) # 更新第一次抽到的计数 + self.update_last(new_gacha) # 更新第一次抽到的计数 mes = '本次祈愿得到以下角色装备:\n' res = self.concat_pic() @@ -338,7 +321,7 @@ def gacha_10(self): mes += '\n' mes += gacha_txt - if self.last_4: # 如果self.last_4为0表示没有抽到,这句话就不写了,下边3个判断标准一样 + if self.last_4: # 如果self.last_4为0表示没有抽到,这句话就不写了,下边3个判断标准一样 mes += f'第 {self.last_4} 抽首次出现4★!\n' if self.last_4_up: mes += f'第 {self.last_4_up} 抽首次出现4★UP!\n' @@ -351,7 +334,7 @@ def gacha_10(self): return mes - def gacha_90(self,frequency=90): + def gacha_90(self, frequency=90): # 抽一井 if not (self.pool in POOL.keys()): return '当前卡池已结束,请使用 原神卡池切换 切换其他卡池' @@ -362,10 +345,10 @@ def gacha_90(self,frequency=90): new_gacha = self.gacha_one() - if not (new_gacha in POOL[self.pool]['3_star_not_UP']): # 抽一井时图片上不保留3星的武器 + if not (new_gacha in POOL[self.pool]['3_star_not_UP']): # 抽一井时图片上不保留3星的武器 self.gacha_list.append(new_gacha) - self.add_gacha_all_statistics(new_gacha) # 把所有抽卡结果添加到gacha_all_statistics用于最后统计 + self.add_gacha_all_statistics(new_gacha) # 把所有抽卡结果添加到gacha_all_statistics用于最后统计 self.update_last(new_gacha) # 更新第一次抽到的计数 @@ -378,7 +361,7 @@ def gacha_90(self,frequency=90): mes += '\n' mes += gacha_txt - if self.last_4: # 如果self.last_4为0表示没有抽到,这句话就不写了 + if self.last_4: # 如果self.last_4为0表示没有抽到,这句话就不写了 mes += f'第 {self.last_4} 抽首次出现4★!\n' if self.last_4_up: mes += f'第 {self.last_4_up} 抽首次出现4★UP!\n' @@ -390,7 +373,6 @@ def gacha_90(self,frequency=90): most_arms = self.get_most_arms() mes += f"本次抽取最多的装备是 {most_arms['name']} {self.is_star(most_arms['name'])} ,共抽取到 {most_arms['most']} 次\n" - if self.is_guaranteed(frequency): mes += "居然全是保底,你脸也太黑了\n" @@ -398,8 +380,7 @@ def gacha_90(self,frequency=90): return mes - -def gacha_info(pool = DEFAULT_POOL): +def gacha_info(pool=DEFAULT_POOL): # UP角色信息 info_txt = f'当前卡池为 {pool} ,UP信息如下:\n' up_info = "" @@ -424,5 +405,3 @@ def gacha_info(pool = DEFAULT_POOL): info_txt += up_info return info_txt - - diff --git a/gacha/icon/1_star.png b/src/gacha/icon/1_star.png similarity index 100% rename from gacha/icon/1_star.png rename to src/gacha/icon/1_star.png diff --git a/gacha/icon/1_star_bg.png b/src/gacha/icon/1_star_bg.png similarity index 100% rename from gacha/icon/1_star_bg.png rename to src/gacha/icon/1_star_bg.png diff --git a/gacha/icon/2_star.png b/src/gacha/icon/2_star.png similarity index 100% rename from gacha/icon/2_star.png rename to src/gacha/icon/2_star.png diff --git a/gacha/icon/2_star_bg.png b/src/gacha/icon/2_star_bg.png similarity index 100% rename from gacha/icon/2_star_bg.png rename to src/gacha/icon/2_star_bg.png diff --git a/gacha/icon/3_star.png b/src/gacha/icon/3_star.png similarity index 100% rename from gacha/icon/3_star.png rename to src/gacha/icon/3_star.png diff --git a/gacha/icon/3_star_bg.png b/src/gacha/icon/3_star_bg.png similarity index 100% rename from gacha/icon/3_star_bg.png rename to src/gacha/icon/3_star_bg.png diff --git a/gacha/icon/4_star.png b/src/gacha/icon/4_star.png similarity index 100% rename from gacha/icon/4_star.png rename to src/gacha/icon/4_star.png diff --git a/gacha/icon/4_star_bg.png b/src/gacha/icon/4_star_bg.png similarity index 100% rename from gacha/icon/4_star_bg.png rename to src/gacha/icon/4_star_bg.png diff --git a/gacha/icon/5_star.png b/src/gacha/icon/5_star.png similarity index 100% rename from gacha/icon/5_star.png rename to src/gacha/icon/5_star.png diff --git a/gacha/icon/5_star_bg.png b/src/gacha/icon/5_star_bg.png similarity index 100% rename from gacha/icon/5_star_bg.png rename to src/gacha/icon/5_star_bg.png diff --git a/gacha/icon/anemo.png b/src/gacha/icon/anemo.png similarity index 100% rename from gacha/icon/anemo.png rename to src/gacha/icon/anemo.png diff --git a/gacha/icon/cryo.png b/src/gacha/icon/cryo.png similarity index 100% rename from gacha/icon/cryo.png rename to src/gacha/icon/cryo.png diff --git a/gacha/icon/default.png b/src/gacha/icon/default.png similarity index 100% rename from gacha/icon/default.png rename to src/gacha/icon/default.png diff --git a/gacha/icon/dendro.png b/src/gacha/icon/dendro.png similarity index 100% rename from gacha/icon/dendro.png rename to src/gacha/icon/dendro.png diff --git a/gacha/icon/electro.png b/src/gacha/icon/electro.png similarity index 100% rename from gacha/icon/electro.png rename to src/gacha/icon/electro.png diff --git a/gacha/icon/geo.png b/src/gacha/icon/geo.png similarity index 100% rename from gacha/icon/geo.png rename to src/gacha/icon/geo.png diff --git a/gacha/icon/hydro.png b/src/gacha/icon/hydro.png similarity index 100% rename from gacha/icon/hydro.png rename to src/gacha/icon/hydro.png diff --git a/gacha/icon/pyro.png b/src/gacha/icon/pyro.png similarity index 100% rename from gacha/icon/pyro.png rename to src/gacha/icon/pyro.png diff --git a/gacha/pool_data.py b/src/gacha/pool_data.py similarity index 73% rename from gacha/pool_data.py rename to src/gacha/pool_data.py index af20fd1..d6b306b 100644 --- a/gacha/pool_data.py +++ b/src/gacha/pool_data.py @@ -1,36 +1,31 @@ - -from PIL import Image,ImageFont,ImageDraw,ImageMath -from loguru import logger -from io import BytesIO - -import collections -import httpx import asyncio -import re -import os +import collections import json +import os +import re import time +from io import BytesIO - +import httpx +from PIL import Image, ImageFont, ImageDraw, ImageMath +from loguru import logger FILE_PATH = os.path.dirname(__file__) -ICON_PATH = os.path.join(FILE_PATH,'icon') +ICON_PATH = os.path.join(FILE_PATH, 'icon') - -POOL_API = "https://webstatic.mihoyo.com/hk4e/gacha_info/cn_gf01/gacha/list.json" +POOL_API = "https://webstatic.mihoyo.com/hk4e/gacha_info/cn_gf01/gacha/list.json" ROLES_API = ['https://genshin.honeyhunterworld.com/fam_chars/?lang=CHS', 'https://genshin.honeyhunterworld.com/db/char/unreleased-and-upcoming-characters/?lang=CHS'] -ARMS_API = ['https://genshin.honeyhunterworld.com/fam_sword/?lang=CHS', - 'https://genshin.honeyhunterworld.com/fam_claymore/?lang=CHS', - 'https://genshin.honeyhunterworld.com/fam_polearm/?lang=CHS', - 'https://genshin.honeyhunterworld.com/fam_bow/?lang=CHS', - 'https://genshin.honeyhunterworld.com/fam_catalyst/?lang=CHS'] +ARMS_API = ['https://genshin.honeyhunterworld.com/fam_sword/?lang=CHS', + 'https://genshin.honeyhunterworld.com/fam_claymore/?lang=CHS', + 'https://genshin.honeyhunterworld.com/fam_polearm/?lang=CHS', + 'https://genshin.honeyhunterworld.com/fam_bow/?lang=CHS', + 'https://genshin.honeyhunterworld.com/fam_catalyst/?lang=CHS'] ROLES_HTML_LIST = None ARMS_HTML_LIST = None -FONT_PATH = os.path.join(os.path.dirname(FILE_PATH),'artifact_collect',"zh-cn.ttf") -FONT=ImageFont.truetype(FONT_PATH, size=20) - +FONT_PATH = os.path.join(os.path.dirname(FILE_PATH), 'artifact_collect', "zh-cn.ttf") +FONT = ImageFont.truetype(FONT_PATH, size=20) # 这个字典记录的是3个不同的卡池,每个卡池的抽取列表 POOL = collections.defaultdict( @@ -43,18 +38,15 @@ }) - - async def get_url_data(url): # 获取url的数据 async with httpx.AsyncClient() as client: - resp = await client.get(url = url,timeout = 10) + resp = await client.get(url=url, timeout=10) if resp.status_code != 200: raise ValueError(f"从 {url} 获取数据失败,错误代码 {resp.status_code}") return resp.content - async def get_role_en_name(ch_name): # 从 genshin.honeyhunterworld.com 获取角色的英文名 global ROLES_HTML_LIST @@ -69,13 +61,12 @@ async def get_role_en_name(ch_name): txt = re.findall(pattern, html) if not txt: continue - txt = re.search('href="\\\\/.+\\\\/\?lang=CHS">',txt[0]).group() + txt = re.search('href="\\\\/.+\\\\/\?lang=CHS">', txt[0]).group() en_name = txt[8:-13] return en_name raise NameError(f"没有找到角色 {ch_name} 的图标名") - async def get_arm_id(ch_name): # 从 genshin.honeyhunterworld.com 获取武器的ID global ARMS_HTML_LIST @@ -106,22 +97,19 @@ async def get_icon(url): return icon - - async def get_role_element(en_name): # 获取角色属性,直接返回属性图标 Image url = f'https://genshin.honeyhunterworld.com/{en_name}/?lang=CHS' data = await get_url_data(url) data = data.decode("unicode_escape") - element = re.search('/img/icons/element/.+?_35.webp',data).group() + element = re.search('/img/icons/element/.+?_35.webp', data).group() element = element[19:-8] - element_path = os.path.join(FILE_PATH,'icon',f'{element}.png') + element_path = os.path.join(FILE_PATH, 'icon', f'{element}.png') return Image.open(element_path) - -async def paste_role_icon(ch_name,star): +async def paste_role_icon(ch_name, star): # 拼接角色图鉴图 en_name = await get_role_en_name(ch_name) @@ -129,49 +117,46 @@ async def paste_role_icon(ch_name,star): avatar_icon = await get_icon(url) element_icon = await get_role_element(en_name) - bg = Image.open(os.path.join(FILE_PATH,'icon',f'{star}_star_bg.png')) + bg = Image.open(os.path.join(FILE_PATH, 'icon', f'{star}_star_bg.png')) bg_a = bg.getchannel("A") - bg1 = Image.new("RGBA",bg.size) - txt_bg = Image.new("RGBA",(160,35),"#e9e5dc") - x = int(160/256 * avatar_icon.size[0]) + bg1 = Image.new("RGBA", bg.size) + txt_bg = Image.new("RGBA", (160, 35), "#e9e5dc") + x = int(160 / 256 * avatar_icon.size[0]) avatar_icon = avatar_icon.resize((x, 160)) element_icon = element_icon.resize((40, 40)) - x_pos = int(160/2 - x / 2) - bg.paste(avatar_icon, (x_pos,3),avatar_icon) - bg.paste(element_icon, (2,3),element_icon) - bg.paste(txt_bg, (0,163)) + x_pos = int(160 / 2 - x / 2) + bg.paste(avatar_icon, (x_pos, 3), avatar_icon) + bg.paste(element_icon, (2, 3), element_icon) + bg.paste(txt_bg, (0, 163)) draw = ImageDraw.Draw(bg) - draw.text((80, 180), ch_name, fill="#4a5466ff", font=FONT, anchor="mm",align="center") - bg1.paste(bg,(0,0),bg_a) + draw.text((80, 180), ch_name, fill="#4a5466ff", font=FONT, anchor="mm", align="center") + bg1.paste(bg, (0, 0), bg_a) return bg1 - -async def paste_arm_icon(ch_name,star): +async def paste_arm_icon(ch_name, star): # 拼接武器图鉴图 arm_id = await get_arm_id(ch_name) url = f'https://genshin.honeyhunterworld.com/img/{arm_id}.webp' arm_icon = await get_icon(url) - star_icon = Image.open(os.path.join(FILE_PATH,'icon',f'{star}_star.png')) + star_icon = Image.open(os.path.join(FILE_PATH, 'icon', f'{star}_star.png')) - bg = Image.open(os.path.join(FILE_PATH,'icon',f'{star}_star_bg.png')) + bg = Image.open(os.path.join(FILE_PATH, 'icon', f'{star}_star_bg.png')) bg_a = bg.getchannel("A") - bg1 = Image.new("RGBA",bg.size) - txt_bg = Image.new("RGBA",(160,35),"#e9e5dc") + bg1 = Image.new("RGBA", bg.size) + txt_bg = Image.new("RGBA", (160, 35), "#e9e5dc") x = int(160 / arm_icon.size[1] * arm_icon.size[0]) arm_icon = arm_icon.resize((x, 160)) x_pos = int(155 / 2 - x / 2) - bg.paste(arm_icon, (x_pos,3),arm_icon) - bg.paste(txt_bg, (0,163)) + bg.paste(arm_icon, (x_pos, 3), arm_icon) + bg.paste(txt_bg, (0, 163)) draw = ImageDraw.Draw(bg) - draw.text((80, 180), ch_name, fill="#4a5466ff", font=FONT, anchor="mm",align="center") - bg.paste(star_icon,(6,135),star_icon) - bg1.paste(bg,(0,0),bg_a) + draw.text((80, 180), ch_name, fill="#4a5466ff", font=FONT, anchor="mm", align="center") + bg.paste(star_icon, (6, 135), star_icon) + bg1.paste(bg, (0, 0), bg_a) return bg1 - - async def up_role_icon(name, star): # 更新角色图标 role_name_path = os.path.join(ICON_PATH, "角色图鉴", str(name) + ".png") @@ -182,15 +167,13 @@ async def up_role_icon(name, star): os.makedirs(os.path.join(ICON_PATH, '角色图鉴')) try: - role_icon = await paste_role_icon(name,star) - with open(role_name_path , "wb") as icon_file: + role_icon = await paste_role_icon(name, star) + with open(role_name_path, "wb") as icon_file: role_icon.save(icon_file) except Exception as e: logger.error(f"更新 {name} 角色图标失败,错误为 {e},建议稍后使用 更新原神卡池 指令重新更新") - - async def up_arm_icon(name, star): # 更新武器图标 arm_name_path = os.path.join(ICON_PATH, "武器图鉴", str(name) + ".png") @@ -202,14 +185,13 @@ async def up_arm_icon(name, star): try: - arm_icon = await paste_arm_icon(name,star) - with open(arm_name_path , "wb") as icon_file: + arm_icon = await paste_arm_icon(name, star) + with open(arm_name_path, "wb") as icon_file: arm_icon.save(icon_file) except Exception as e: logger.error(f"更新 {name} 武器图标失败,错误为 {e},建议稍后使用 更新原神卡池 指令重新更新") - async def init_pool_list(): # 初始化卡池数据 global ROLES_HTML_LIST @@ -218,7 +200,7 @@ async def init_pool_list(): ROLES_HTML_LIST = None ARMS_HTML_LIST = None POOL.clear() - + logger.info(f"正在更新卡池数据") data = await get_url_data(POOL_API) data = json.loads(data.decode("utf-8")) @@ -234,7 +216,7 @@ async def init_pool_list(): pool_data = await get_url_data(pool_url) pool_data = json.loads(pool_data.decode("utf-8")) - for prob_list in ['r3_prob_list','r4_prob_list','r5_prob_list']: + for prob_list in ['r3_prob_list', 'r4_prob_list', 'r5_prob_list']: for i in pool_data[prob_list]: item_name = i['item_name'] item_type = i["item_type"] @@ -248,11 +230,9 @@ async def init_pool_list(): POOL[pool_name][key].append(item_name) if item_type == '角色': - await up_role_icon(name = item_name,star = item_star) + await up_role_icon(name=item_name, star=item_star) else: - await up_arm_icon(name = item_name,star = item_star) - - + await up_arm_icon(name=item_name, star=item_star) # 初始化 diff --git a/material_remind/__init__.py b/src/material_remind/__init__.py similarity index 70% rename from material_remind/__init__.py rename to src/material_remind/__init__.py index 4262695..bd2d2e1 100644 --- a/material_remind/__init__.py +++ b/src/material_remind/__init__.py @@ -1,11 +1,11 @@ -from hoshino import Service,get_bot -from PIL import Image -from io import BytesIO - -import os +import base64 import json +import os import time -import base64 +from io import BytesIO + +from PIL import Image +from hoshino import Service, get_bot sv = Service("原神每日素材提醒") @@ -13,29 +13,32 @@ group_list = [] + def save_group_list(): - with open(os.path.join(FILE_PATH,'group_list.json'),'w',encoding='UTF-8') as f: - json.dump(group_list,f,ensure_ascii=False) + with open(os.path.join(FILE_PATH, 'group_list.json'), 'w', encoding='UTF-8') as f: + json.dump(group_list, f, ensure_ascii=False) + # 检查group_list.json是否存在,没有创建空的 -if not os.path.exists(os.path.join(FILE_PATH,'group_list.json')): +if not os.path.exists(os.path.join(FILE_PATH, 'group_list.json')): save_group_list() # 读取group_list.json的信息 -with open(os.path.join(FILE_PATH,'group_list.json'),'r',encoding='UTF-8') as f: +with open(os.path.join(FILE_PATH, 'group_list.json'), 'r', encoding='UTF-8') as f: group_list = json.load(f) -def get_today_material(name:str): + +def get_today_material(name: str): # 返回今天的材料图片CQ码 week = time.strftime("%w") if week == "0": return "今天是周日,所有材料副本都开放了。" - elif week in ["1","4"]: + elif week in ["1", "4"]: png_name = f"{name}_周一周四.png" - elif week in ["2","5"]: + elif week in ["2", "5"]: png_name = f"{name}_周二周五.png" - elif week in ["3","6"]: + elif week in ["3", "6"]: png_name = f"{name}_周三周六.png" image = Image.open(os.path.join(FILE_PATH, "icon", png_name)) @@ -46,7 +49,7 @@ def get_today_material(name:str): @sv.on_fullmatch('开启原神每日素材提醒') -async def open_remind(bot , ev): +async def open_remind(bot, ev): gid = str(ev.group_id) if 'group_id' in dir(ev) else str(ev.guild_id) if not (gid in group_list): group_list.append(gid) @@ -55,7 +58,7 @@ async def open_remind(bot , ev): @sv.on_fullmatch('关闭原神每日素材提醒') -async def off_remind(bot , ev): +async def off_remind(bot, ev): gid = str(ev.group_id) if 'group_id' in dir(ev) else str(ev.guild_id) if gid in group_list: group_list.remove(gid) @@ -63,19 +66,20 @@ async def off_remind(bot , ev): await bot.send(ev, "每日提醒已关闭") -@sv.on_fullmatch(["今日武器突破材料","今日武器材料","武器材料","今日武器升级材料"]) -async def send_arms_material_remind(bot , ev): +@sv.on_fullmatch(["今日武器突破材料", "今日武器材料", "武器材料", "今日武器升级材料"]) +async def send_arms_material_remind(bot, ev): arms_material_CQ = get_today_material("武器突破材料") await bot.send(ev, arms_material_CQ) -@sv.on_fullmatch(["今日角色天赋材料","今日角色材料","角色材料","今日天赋升级材料"]) -async def send_arms_material_remind(bot , ev): +@sv.on_fullmatch(["今日角色天赋材料", "今日角色材料", "角色材料", "今日天赋升级材料"]) +async def send_arms_material_remind(bot, ev): roles_material_CQ = get_today_material("角色天赋材料") await bot.send(ev, roles_material_CQ) - -@sv.on_fullmatch(["今日材料","今日素材"]) -async def send_arms_material_remind(bot , ev): + + +@sv.on_fullmatch(["今日材料", "今日素材"]) +async def send_arms_material_remind(bot, ev): if time.strftime("%w") == "0": await bot.send(ev, "今天是周日,所有材料副本都开放了。") return @@ -84,17 +88,16 @@ async def send_arms_material_remind(bot , ev): await bot.send(ev, arms_material_CQ) await bot.send(ev, roles_material_CQ) + @sv.scheduled_job('cron', hour='8') async def material_remind(): # 每日提醒 if time.strftime("%w") == "0": # 如果今天是周日就不发了 - return + return bot = get_bot() arms_material_CQ = get_today_material("武器突破材料") roles_material_CQ = get_today_material("角色天赋材料") for gid in group_list: - await bot.send_group_msg(group_id=int(gid),message=arms_material_CQ) + await bot.send_group_msg(group_id=int(gid), message=arms_material_CQ) await bot.send_group_msg(group_id=int(gid), message=roles_material_CQ) - - \ No newline at end of file diff --git "a/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" "b/src/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" similarity index 100% rename from "material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" rename to "src/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" diff --git "a/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" "b/src/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" similarity index 100% rename from "material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" rename to "src/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" diff --git "a/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" "b/src/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" similarity index 100% rename from "material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" rename to "src/material_remind/icon/\346\255\246\345\231\250\347\252\201\347\240\264\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" diff --git "a/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" "b/src/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" similarity index 100% rename from "material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" rename to "src/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\200\345\221\250\345\233\233.png" diff --git "a/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" "b/src/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" similarity index 100% rename from "material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" rename to "src/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\270\211\345\221\250\345\205\255.png" diff --git "a/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" "b/src/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" similarity index 100% rename from "material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" rename to "src/material_remind/icon/\350\247\222\350\211\262\345\244\251\350\265\213\346\235\220\346\226\231_\345\221\250\344\272\214\345\221\250\344\272\224.png" diff --git a/src/qiu_qiu_translation/__init__.py b/src/qiu_qiu_translation/__init__.py new file mode 100644 index 0000000..8afdd3f --- /dev/null +++ b/src/qiu_qiu_translation/__init__.py @@ -0,0 +1 @@ +from .qiu_qiu_translation import qiu_qiu_word_translation, qiu_qiu_phrase_translation diff --git a/qiu_qiu_translation/qiu_qiu_dictionary.json b/src/qiu_qiu_translation/qiu_qiu_dictionary.json similarity index 97% rename from qiu_qiu_translation/qiu_qiu_dictionary.json rename to src/qiu_qiu_translation/qiu_qiu_dictionary.json index 08d0f32..9109fd3 100644 --- a/qiu_qiu_translation/qiu_qiu_dictionary.json +++ b/src/qiu_qiu_translation/qiu_qiu_dictionary.json @@ -1,33 +1,23 @@ { "word": { - "a": "啊", - "beru": "做", "biadam": "找死啊", "biat": "暴揍", "buka": "肚子", - "celi": "元素", - "dada": "厉害", "dala": "什么", "domu": "跳舞", - "eleka": "此时此刻", - "guru": "咕", "gusha": "草", - "ika": "敌人", - "kundela": "活着", "kuzi": "强大", "kucha": "吃草", - "la": "啦~", "lata": "水元素", - "mani": "给予", "mi": "我", "mimi": "我们", @@ -35,85 +25,62 @@ "mosi": "吃", "movo": "带来", "muhe": "胜利", - "ni": "风", "nini": "风暴", "nunu": "睡觉", "nye": "不", - "odomu": "朋友", "olah": "你好", - "plata": "盾牌", "pupu": "噗噗", - "sada": "唱歌", "shato": "伴随", "si": "什么", - "tomo": "感激", "todo": "放心", "tiga": "矿石", - "upa": "聚集", "unu": "乌努", - "valo": "谢谢你", "vin": "酒", - "ya": "人", "yaya": "人们", "ye": "家伙", "yeye": "这些家伙", "yo": "你", "yoyo": "你们", - "zido": "杀死" - }, "phrase": { "beru si": "做什么", "biadam": "可恶啊,找死啊,愤怒语气", "biat": "打爆,暴揍;可恶的", - "dada": " 极好的,厉害的", "dala": "表示疑问,不明白的集合,翻译为哪个,什么", - "guru-guru": "拟声词,形容肚子咕咕叫的声音,饥饿", "guru guru": "拟声词,形容肚子咕咕叫的声音,饥饿", "gusha": "植物类食物,不怎么好的,难过的", - "kucha pupu": "拟声词,吃草时候的拟声词,咯吱噗噗,形容吃草吃得香,贬义", - "mita": "肉类,好的,好东西,有时代丘丘人,丘丘人部落,好肉族", "mosi mita": "吃肉,表示开心", "mosi gusha": "吃草,表示难过", "movo": "带来,搬运;可引申为收获,丰收", "muhe": "胜利,战胜;成功的", - "nini": "大量风元素,风暴,狂风", "nye": "表示否定,没有了,不是", - - "pupu":"拟声词,噗噗,表示嘲讽", - + "pupu": "拟声词,噗噗,表示嘲讽", "sada": "唱歌,歌颂", "shato": "乘着,伴随着", - "upa": "凝聚,聚集,集合;聚落,部落", "unu": "乌努,丘丘人所崇拜的神灵", - "valo": "谢谢你,不客气/再见", "vin": "酒的,喝酒有关的,酒桶盖子", - "ya": "特指人类,一个人类", "yaya": "人类的复数 ,大群人类", "ye": "你这个家伙,蔑称;或用于地位高者对地位低者的称呼", "yeye": "你们这些家伙,蔑称,ye的复数", "yo": "你,友善称呼", "yoyo": "你们,yo的复数,友善称呼ye", - - - "nye mita da ye mosi zido": "再见,一路平安", "vin plata dada": "你的酒桶盾牌真不错", "kucha pupu gucha ye": "你咯吱噗噗的吃草的样子真的好搞笑", diff --git a/src/qiu_qiu_translation/qiu_qiu_translation.py b/src/qiu_qiu_translation/qiu_qiu_translation.py new file mode 100644 index 0000000..4a1fff1 --- /dev/null +++ b/src/qiu_qiu_translation/qiu_qiu_translation.py @@ -0,0 +1,114 @@ +import json +from pathlib import Path +from typing import Union, Tuple, List + +FILE_PATH = Path(__file__) +DEFAULT_DICT = FILE_PATH / 'qiu_qiu_dictionary.json' + + +__all__ = ['DEFAULT_DICT', 'HilichurlDict', 'qiu_qiu_phrase_translation', 'qiu_qiu_word_translation'] + + +class HilichurlDict: # hilichurl <=> 丘丘人 + def _load(self, encoding='utf-8'): + with open(self.path, 'r', encoding=encoding) as qiu_dict: + data_ = json.load(qiu_dict) + self.WORD = data_["word"] + self.PHRASE = data_["phrase"] + self.KEYS = self.WORD.keys() + self.PHRASE.keys() + + def _validate(self, __wp: str) -> bool: + return True if __wp in self.KEYS else False + + def __init__(self, path: Path = DEFAULT_DICT): + self.path = path + self.data = {} + self.WORD = {} + self.PHRASE = {} + self.KEYS = {} + + self._load() + + def compare_word(self, word: str) -> str: + """ + 比对word库是否有匹配的单词,有的话返回翻译,没有返回原词 + + :param word: 单词 + :return: 单词翻译 + """ + return self.data.get(word, word) + + def compare_phrase(self, phrase): + """ + 比对短语库是否有匹配的单词,有的话返回翻译,没有的话匹配word库,都没有返回原词 + + :param phrase: 短语 + :return: 翻译的内容 + """ + if phrase in self.PHRASE: + return self.PHRASE.get(phrase) + if phrase in self.WORD: + return self.WORD[phrase] + + return phrase + + def translate(self, text: str) -> str: + """ + 将丘丘语句子直接按词直译 + + :param text: 需要翻译的文本 + :return: 翻译后的字符串 + """ + words_ = [t.strip() for t in text.split()] + result_ = '' + for word in words_: + trans_ = self.compare_word(word) + if trans_ == word: + result_ += f' {trans_} ' + else: + result_ += trans_ + return result_ + + def multiple_word(self, words: Union[str, list]) -> Tuple[str, List[str]]: + """ + 语句翻译, 返回有一个元组,分别是翻译成功的句子字符串与翻译失败的单词列表 + + :param words: 句子,支持自动拆分 + :return: 文本,句子翻译或者词组单独释义 + """ + if isinstance(words, str): + words = words.split() + success_result = '\n'.join( + f"{word}: {self.compare_phrase(word)}" for word in filter(self._validate, words) + ) + failure_result = list(filter(lambda x: not self._validate(x), words)) + + return success_result, failure_result + + +HILICHURL = HilichurlDict() + + +def qiu_qiu_word_translation(txt: str): + # 对语句按空格分隔替换单词翻译 + return HILICHURL.translate(txt) + + +def qiu_qiu_phrase_translation(phrase: str): + """ + 语句翻译,先看phrase库是不是有匹配的语句 + 没有的话把单词拆开返回单词的意思 + + :param phrase: 语句 + :return: 格式化后的文本 + """ + tra_phrase = HILICHURL.compare_phrase(phrase) + if tra_phrase != phrase: + return f"你查询的的丘丘语意思为:\n{tra_phrase}\n" + + result_ = HILICHURL.multiple_word(phrase) + return ''.join([ + "没有查到这句丘丘语,以下是单词的翻译\n", + result_[0], "\n不存在的翻译: ", + ' '.join(result_[1]) + ]) diff --git a/query_resource_points/__init__.py b/src/query_resource_points/__init__.py similarity index 98% rename from query_resource_points/__init__.py rename to src/query_resource_points/__init__.py index 7ea3da8..8a2b5d8 100644 --- a/query_resource_points/__init__.py +++ b/src/query_resource_points/__init__.py @@ -1,6 +1,5 @@ - -from loguru import logger from hoshino import Service + from .query_resource_points import get_resource_map_mes, get_resource_list_mes, init_point_list_and_map sv = Service("原神资源查询") diff --git a/query_resource_points/icon/0.png b/src/query_resource_points/icon/0.png similarity index 100% rename from query_resource_points/icon/0.png rename to src/query_resource_points/icon/0.png diff --git a/query_resource_points/icon/box.png b/src/query_resource_points/icon/box.png similarity index 100% rename from query_resource_points/icon/box.png rename to src/query_resource_points/icon/box.png diff --git a/query_resource_points/icon/box_alpha.png b/src/query_resource_points/icon/box_alpha.png similarity index 100% rename from query_resource_points/icon/box_alpha.png rename to src/query_resource_points/icon/box_alpha.png diff --git a/query_resource_points/query_resource_points.py b/src/query_resource_points/query_resource_points.py similarity index 78% rename from query_resource_points/query_resource_points.py rename to src/query_resource_points/query_resource_points.py index 26cf12c..e9180a3 100644 --- a/query_resource_points/query_resource_points.py +++ b/src/query_resource_points/query_resource_points.py @@ -1,38 +1,33 @@ - -from PIL import Image,ImageMath -from io import BytesIO -from loguru import logger +import asyncio +import base64 import json import os import time -import base64 -import httpx -import asyncio - +from io import BytesIO +import httpx +from PIL import Image, ImageMath +from loguru import logger -LABEL_URL = 'https://api-static.mihoyo.com/common/blackboard/ys_obc/v1/map/label/tree?app_sn=ys_obc' +LABEL_URL = 'https://api-static.mihoyo.com/common/blackboard/ys_obc/v1/map/label/tree?app_sn=ys_obc' POINT_LIST_URL = 'https://api-static.mihoyo.com/common/blackboard/ys_obc/v1/map/point/list?map_id=2&app_sn=ys_obc' -MAP_URL = "https://api-static.mihoyo.com/common/map_user/ys_obc/v1/map/info?map_id=2&app_sn=ys_obc&lang=zh-cn" +MAP_URL = "https://api-static.mihoyo.com/common/map_user/ys_obc/v1/map/info?map_id=2&app_sn=ys_obc&lang=zh-cn" -header = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36' +UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36' FILE_PATH = os.path.dirname(__file__) -MAP_PATH = os.path.join(FILE_PATH,"icon","map_icon.jpg") +MAP_PATH = os.path.join(FILE_PATH, "icon", "map_icon.jpg") Image.MAX_IMAGE_PIXELS = None - CENTER = None MAP_ICON = None - zoom = 0.5 -resource_icon_offset = (-int(150*0.5*zoom),-int(150*zoom)) - +resource_icon_offset = (-int(150 * 0.5 * zoom), -int(150 * zoom)) data = { - "all_resource_type":{ + "all_resource_type": { # 这个字典保存所有资源类型, # "1": { # "id": 1, @@ -47,26 +42,26 @@ # "children": [] # }, }, - "can_query_type_list":{ + "can_query_type_list": { # 这个字典保存所有可以查询的资源类型名称和ID,这个字典只有名称和ID # 上边字典里"depth": 2的类型才可以查询,"depth": 1的是1级目录,不能查询 # "七天神像":"2" # "风神瞳":"5" }, - "all_resource_point_list" :[ - # 这个列表保存所有资源点的数据 - # { - # "id": 2740, - # "label_id": 68, - # "x_pos": -1789, - # "y_pos": 2628, - # "author_name": "✟紫灵心✟", - # "ctime": "2020-10-29 10:41:21", - # "display_state": 1 - # }, + "all_resource_point_list": [ + # 这个列表保存所有资源点的数据 + # { + # "id": 2740, + # "label_id": 68, + # "x_pos": -1789, + # "y_pos": 2628, + # "author_name": "✟紫灵心✟", + # "ctime": "2020-10-29 10:41:21", + # "display_state": 1 + # }, ], - "date":"" #记录上次更新"all_resource_point_list"的日期 + "date": "" # 记录上次更新"all_resource_point_list"的日期 } @@ -79,6 +74,7 @@ async def download_icon(url): icon = resp.content return Image.open(BytesIO(icon)) + async def download_json(url): # 获取资源数据,返回 JSON async with httpx.AsyncClient() as client: @@ -91,7 +87,7 @@ async def download_json(url): async def up_icon_image(sublist): # 检查是否有图标,没有图标下载保存到本地 id = sublist["id"] - icon_path = os.path.join(FILE_PATH,"icon",f"{id}.png") + icon_path = os.path.join(FILE_PATH, "icon", f"{id}.png") if not os.path.exists(icon_path): logger.info(f"正在更新资源图标 {id}") @@ -99,8 +95,8 @@ async def up_icon_image(sublist): icon = await download_icon(icon_url) icon = icon.resize((150, 150)) - box_alpha = Image.open(os.path.join(FILE_PATH,"icon","box_alpha.png")).getchannel("A") - box = Image.open(os.path.join(FILE_PATH,"icon","box.png")) + box_alpha = Image.open(os.path.join(FILE_PATH, "icon", "box_alpha.png")).getchannel("A") + box = Image.open(os.path.join(FILE_PATH, "icon", "box.png")) try: icon_alpha = icon.getchannel("A") @@ -119,6 +115,7 @@ async def up_icon_image(sublist): with open(icon_path, "wb") as icon_file: bg.save(icon_file) + async def up_label_and_point_list(): # 更新label列表和资源点列表 logger.info(f"正在更新资源点数据") @@ -157,10 +154,10 @@ async def up_map(): for resource_point in data["all_resource_point_list"]: x_pos = resource_point["x_pos"] + origin[0] y_pos = resource_point["y_pos"] + origin[1] - x_start = min(x_start,x_pos) - y_start = min(y_start,y_pos) - x_end = max(x_end,x_pos) - y_end = max(y_end,y_pos) + x_start = min(x_start, x_pos) + y_start = min(y_start, y_pos) + x_end = max(x_end, x_pos) + y_end = max(y_end, y_pos) x_start -= 200 y_start -= 200 @@ -170,14 +167,14 @@ async def up_map(): CENTER = [origin[0] - x_start, origin[1] - y_start] x = int(x_end - x_start) y = int(y_end - y_start) - MAP_ICON = Image.new("RGB",(x,y)) + MAP_ICON = Image.new("RGB", (x, y)) y_offset = 0 for x_map_url_list in map_url_list: x_offset = 0 for y_map_url in x_map_url_list: map_url = y_map_url["url"] map_icon = await download_icon(map_url) - MAP_ICON.paste(map_icon,(int(-x_start) + x_offset, int(-y_start) + y_offset)) + MAP_ICON.paste(map_icon, (int(-x_start) + x_offset, int(-y_start) + y_offset)) x_offset += map_icon.size[0] y_offset += map_icon.size[1] @@ -189,17 +186,14 @@ async def init_point_list_and_map(): await up_map() - # 初始化 loop = asyncio.get_event_loop() loop.run_until_complete(init_point_list_and_map()) - - class Resource_map(object): - def __init__(self,resource_name): + def __init__(self, resource_name): self.resource_id = str(data["can_query_type_list"][resource_name]) # self.map_image = Image.open(MAP_PATH) @@ -214,42 +208,41 @@ def __init__(self,resource_name): self.y_end = 0 self.resource_icon = Image.open(self.get_icon_path()) - self.resource_icon = self.resource_icon.resize((int(150*zoom),int(150*zoom))) + self.resource_icon = self.resource_icon.resize((int(150 * zoom), int(150 * zoom))) self.resource_xy_list = self.get_resource_point_list() def get_icon_path(self): # 检查有没有图标,有返回正确图标,没有返回默认图标 - icon_path = os.path.join(FILE_PATH,"icon",f"{self.resource_id}.png") + icon_path = os.path.join(FILE_PATH, "icon", f"{self.resource_id}.png") if os.path.exists(icon_path): return icon_path else: - return os.path.join(FILE_PATH,"icon","0.png") + return os.path.join(FILE_PATH, "icon", "0.png") def get_resource_point_list(self): temp_list = [] for resource_point in data["all_resource_point_list"]: - if str(resource_point["label_id"]) == self.resource_id : + if str(resource_point["label_id"]) == self.resource_id: # 获取xy坐标,然后加上中心点的坐标完成坐标转换 x = resource_point["x_pos"] + CENTER[0] y = resource_point["y_pos"] + CENTER[1] - temp_list.append((int(x),int(y))) + temp_list.append((int(x), int(y))) return temp_list - def paste(self): - for x,y in self.resource_xy_list: + for x, y in self.resource_xy_list: # 把资源图片贴到地图上 # 这时地图已经裁切过了,要以裁切后的地图左上角为中心再转换一次坐标 x -= self.x_start y -= self.y_start - self.map_image.paste(self.resource_icon,(x + resource_icon_offset[0] , y + resource_icon_offset[1]),self.resource_icon) - + self.map_image.paste(self.resource_icon, (x + resource_icon_offset[0], y + resource_icon_offset[1]), + self.resource_icon) def crop(self): # 把大地图裁切到只保留资源图标位置 - for x,y in self.resource_xy_list: + for x, y in self.resource_xy_list: # 找出4个方向最远的坐标,用于后边裁切 self.x_start = min(x, self.x_start) self.y_start = min(y, self.y_start) @@ -263,16 +256,16 @@ def crop(self): self.y_end += 150 # 如果图片裁切的太小会看不出资源的位置在哪,检查图片裁切的长和宽看够不够1000,不到1000的按1000裁切 - if (self.x_end - self.x_start)<1000: + if (self.x_end - self.x_start) < 1000: center = int((self.x_end + self.x_start) / 2) self.x_start = center - 500 - self.x_end = center +500 - if (self.y_end - self.y_start)<1000: + self.x_end = center + 500 + if (self.y_end - self.y_start) < 1000: center = int((self.y_end + self.y_start) / 2) self.y_start = center - 500 - self.y_end = center +500 + self.y_end = center + 500 - self.map_image = self.map_image.crop((self.x_start,self.y_start,self.x_end,self.y_end)) + self.map_image = self.map_image.crop((self.x_start, self.y_start, self.x_end, self.y_end)) def get_cq_cod(self): @@ -293,10 +286,8 @@ def get_resource_count(self): return len(self.resource_xy_list) - async def get_resource_map_mes(name): - - if data["date"] != time.strftime("%d"): + if data["date"] != time.strftime("%d"): await init_point_list_and_map() if not (name in data["can_query_type_list"]): @@ -316,9 +307,7 @@ async def get_resource_map_mes(name): return mes - def get_resource_list_mes(): - temp = {} for id in data["all_resource_type"].keys(): @@ -335,7 +324,7 @@ def get_resource_list_mes(): for resource_type_id in temp.keys(): - if resource_type_id in ["1","12","50","51","95","131"]: + if resource_type_id in ["1", "12", "50", "51", "95", "131"]: # 在游戏里能查到的数据这里就不列举了,不然消息太长了 continue From 2d315022d3f5b9080cf8bc08467ad98ae702ad36 Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Fri, 3 Feb 2023 21:28:12 +0800 Subject: [PATCH 02/13] =?UTF-8?q?=E2=9A=A1=20=E5=9C=A3=E9=81=97=E7=89=A9?= =?UTF-8?q?=E8=AF=84=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 拆分圣遗物评分 --- src/artifact_rate/__init__.py | 43 +++++------------------------- src/artifact_rate/artifact_eval.py | 13 +++++---- 2 files changed, 12 insertions(+), 44 deletions(-) diff --git a/src/artifact_rate/__init__.py b/src/artifact_rate/__init__.py index 8d7a2ca..d485dd4 100644 --- a/src/artifact_rate/__init__.py +++ b/src/artifact_rate/__init__.py @@ -1,52 +1,21 @@ from base64 import b64encode from io import BytesIO -from hoshino import Service - from .artifact_eval import * -sv = Service("原神圣遗物评分") - -def get_format_sub_item(artifact_attr): +def format_sub_attr(artifact_attr): msg = "" for i in artifact_attr["sub_item"]: msg += f'{i["name"]:\u3000<6} | {i["value"]}\n' return msg -@sv.on_prefix(("圣遗物评分", "-rate")) -async def artifact_rate(bot, ev): - if '[CQ:image' not in ev["raw_message"]: - await bot.send(ev, "图呢?\n*请将-rate指令与截图一起发送", at_sender=True) - return - if len(ev["message"]) > 1: - await bot.send(ev, "只能上传一张截图哦", at_sender=True) - return - for i in ev["message"]: - if i["type"] == 'image': - image_url = i.data["url"] - break - continue - # await bot.send(ev, f"图片收到啦~\n正在识图中...") +async def rate_by_img(image_url: str): image_content = BytesIO(requests.get(image_url).content) image_b64 = b64encode(image_content.read()).decode() - try: - artifact_attr = await get_artifact_attr(image_b64) - except (requests.exceptions.ConnectionError, requests.exceptions.ReadTimeout): - await bot.send(ev, f"连接超时", at_sender=True) - return - if 'err' in artifact_attr.keys(): - err_msg = artifact_attr["full"]["message"] - await bot.send(ev, f"发生了点小错误:\n{err_msg}", at_sender=True) - return - # await bot.send(ev, f"识图成功!\n正在评分中...", at_sender=True) + artifact_attr = await get_artifact_attr(image_b64) rate_result = await rate_artifact(artifact_attr) - if 'err' in rate_result.keys(): - err_msg = rate_result["full"]["message"] - await bot.send(ev, f"发生了点小错误:\n{err_msg}\n*注:将在下版本加入属性修改", at_sender=True) - return - format_result = f'圣遗物评分结果:\n主属性:{artifact_attr["main_item"]["name"]}\n{get_format_sub_item(artifact_attr)}' \ - f'------------------------------\n总分:{rate_result["total_percent"]}\n' \ - f'主词条:{rate_result["main_percent"]}\n副词条:{rate_result["sub_percent"]}\n评分、识图均来自genshin.pub' - await bot.send(ev, format_result, at_sender=True) + return f'圣遗物评分结果:\n主属性:{artifact_attr["main_item"]["name"]}\n{format_sub_attr(artifact_attr)}' \ + f'------------------------------\n总分:{rate_result["total_percent"]}\n' \ + f'主词条:{rate_result["main_percent"]}\n副词条:{rate_result["sub_percent"]}\n评分、识图均来自genshin.pub' diff --git a/src/artifact_rate/artifact_eval.py b/src/artifact_rate/artifact_eval.py index 267b9c4..ac9ffb4 100644 --- a/src/artifact_rate/artifact_eval.py +++ b/src/artifact_rate/artifact_eval.py @@ -2,13 +2,12 @@ import requests -ocr_url = "https://api.genshin.pub/api/v1/app/ocr" -rate_url = "https://api.genshin.pub/api/v1/relic/rate" -head = { +URL_OCR = "https://api.genshin.pub/api/v1/app/ocr" +URL_EVAL = "https://api.genshin.pub/api/v1/relic/rate" +HEAD = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.67 ", - "Content-Type": "application/json; charset=UTF-8", - "Connection": "close" + "Content-Type": "application/json; charset=UTF-8" } @@ -19,7 +18,7 @@ async def get_artifact_attr(b64_str): } ) try: - req = requests.post(ocr_url, data=upload_json, headers=head, timeout=8) + req = requests.post(URL_OCR, data=upload_json, headers=HEAD, timeout=8) except requests.exceptions.RequestException as e: raise e data = json.loads(req.text) @@ -31,7 +30,7 @@ async def get_artifact_attr(b64_str): async def rate_artifact(artifact_attr: dict): upload_json_str = json.dumps(artifact_attr, ensure_ascii=False).encode('utf-8') try: - req = requests.post(rate_url, data=upload_json_str, headers=head, timeout=8) + req = requests.post(URL_EVAL, data=upload_json_str, headers=HEAD, timeout=8) except requests.exceptions.RequestException as e: raise e data = json.loads(req.text) From c12f93e41ef9df7b3cbd8e880d1d076b297fd544 Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Fri, 3 Feb 2023 22:38:16 +0800 Subject: [PATCH 03/13] =?UTF-8?q?=F0=9F=94=A5=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=EF=BC=9Aloguru?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 额外安装不够现实,对于hoshino(nb1)可以用nonebot.log --- .gitignore | 5 ++++- poetry.lock | 39 +-------------------------------------- pyproject.toml | 1 - 3 files changed, 5 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index 28d8e97..e3491af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .idea -.idea/* \ No newline at end of file +.idea/* + +# poetry +poetry.lock \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 35aac47..385ba64 100644 --- a/poetry.lock +++ b/poetry.lock @@ -31,14 +31,6 @@ category = "main" optional = false python-versions = ">=3.6" -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" - [[package]] name = "h11" version = "0.14.0" @@ -93,21 +85,6 @@ category = "main" optional = false python-versions = ">=3.5" -[[package]] -name = "loguru" -version = "0.6.0" -description = "Python logging made (stupidly) simple" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["colorama (>=0.3.4)", "docutils (==0.16)", "flake8 (>=3.7.7)", "tox (>=3.9.0)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "black (>=19.10b0)", "isort (>=5.1.1)", "Sphinx (>=4.1.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)"] - [[package]] name = "pillow" version = "9.4.0" @@ -142,33 +119,19 @@ category = "main" optional = false python-versions = ">=3.7" -[[package]] -name = "win32-setctime" -version = "1.1.0" -description = "A small Python utility to set file creation time on Windows" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.extras] -dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"] - [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "51d9849d8e9541bbfbacbba5a71851c01cf34722c5fc0cfe70e57ba3dfadf5cb" +content-hash = "9c96663101daae49ee8fadcb9f485d78cd7c5cd42955f03f8768da7265bb91e4" [metadata.files] aiofiles = [] anyio = [] certifi = [] -colorama = [] h11 = [] httpcore = [] httpx = [] idna = [] -loguru = [] pillow = [] rfc3986 = [] sniffio = [] -win32-setctime = [] diff --git a/pyproject.toml b/pyproject.toml index c1d267d..9b9c582 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,6 @@ license = "GNU General Public License v3.0" [tool.poetry.dependencies] python = "^3.8" -loguru = "^0.6.0" Pillow = "^9.4.0" httpx = "^0.23.3" aiofiles = "^22.1.0" From 79debb950ef5127d63d9acc87978080f7a8e5a76 Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Mon, 6 Feb 2023 21:34:59 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E2=9A=A1=20=E8=B5=84=E6=BA=90=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=99=A8=20Part.1=20=E4=B8=8B=E8=BD=BD=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现部分下载器功能 - 优化结构 --- src/asset_manager.py | 184 ++++++++++++++++++++++++++++++++----------- src/utils.py | 13 +++ 2 files changed, 150 insertions(+), 47 deletions(-) create mode 100644 src/utils.py diff --git a/src/asset_manager.py b/src/asset_manager.py index 624d51c..292de2b 100644 --- a/src/asset_manager.py +++ b/src/asset_manager.py @@ -1,16 +1,17 @@ -import threading import json -from urllib.parse import ParseResult as URL -from urllib.parse import urlparse +import threading from collections import UserList -from typing import List, Union +from io import BytesIO from pathlib import Path from sys import stdout -from io import BytesIO +from typing import List, Union +from logging import Logger import aiofiles import httpx from PIL import Image +from httpx import URL +from .utils import logger class BotAsset: @@ -60,71 +61,160 @@ def __init__(self, path: Path): self.path = path def __truediv__(self, other): - new_path_ = self.path.joinpath(other) - if new_path_.is_file(): - return BotAsset(new_path_) - return new_path_ + _new_path = self.path.joinpath(other) + if not _new_path.exists(): + return None + if _new_path.is_file(): + return BotAsset(_new_path) + return _new_path + def _get_path(self, absolute_path: Union[str, Path]): + _dest = self.path.joinpath(absolute_path) + if not _dest.exists(): + return None + return _dest -class Downloader: - @staticmethod - def _validate(url: Union[str, URL]): + def fetch_assets(self, assets_list: List[Union[str, URL]], max_connections: int = 5): + _downloader = Downloader(file_list=assets_list) + + +class DownloadItem: + def __init__(self, url: Union[str, URL], dest: Union[str, Path, None] = None, **kwargs): if isinstance(url, str): - url = urlparse(url) - if url.scheme in ['http', 'https']: + url = URL(url=url) + if isinstance(dest, str): + dest = Path(dest) + self.url: URL = url + self.dest: Union[Path, None] = dest + if kwargs: + for k, v in kwargs.values(): + setattr(self, k, v) + + def validate(self): + if self.url.scheme in ['http', 'https']: return True return False + +class Downloader: @staticmethod - def _clear_prev_line(self): + def _get_connection_slice(list_, chunk_size) -> List[List[DownloadItem]]: + n = len(list_) + return [list_[i:i + chunk_size] for i in range(0, n, chunk_size)] + [ + list_[n - n % chunk_size:]] if n % chunk_size != 0 else [] + + @staticmethod + def _clear_prev_line(): stdout.write("\330[A\330[K\n") - def _update_term_progress(self, filename: str): - strings = { - "bar": self.progress_char * round(self.progress * 10), - "filename": filename, + @staticmethod + def _guess_if_file(__item: DownloadItem) -> bool: + if '.' in __item.url.path: + return True + return False - } + @staticmethod + def _get_filename(__item: DownloadItem): + return __item.url.path.split('/')[-1] - def _reset_progress(self): - self.progress = 0 + @staticmethod + def _convert_url(url: Union[str, tuple, URL, httpx.URL]) -> Union[DownloadItem, None]: + if isinstance(url, tuple): + if len(url) < 1: + return None + if len(url) == 1: + return DownloadItem(url=url[0]) + + def _get_dest_folder(self, dest: Union[str, Path]): + if isinstance(dest, str): + dest = Path(dest) + if not dest.is_absolute(): + dest = self.dest_path / dest + if dest.is_file(): + dest = dest.parent + dest.mkdir(parents=True, exist_ok=True) + return dest - def _update_avg_progress(self): - return 1 / len(self.file_list) + def _update_term_progress(self, filename: str): + variables = { + "bar": self.progress_char * round(self.progress * self.bar_width), + "filename": filename, + "count": self.finish_count, + "len": self.len + } + if self.finish_count != 0: + self._clear_prev_line() + self.logger.info(self.progress_fmt.format(**variables)) def _progress_upd(self): - self.progress += self.avg_progress - self.count += 1 + self.finish_count += 1 - @property - def len(self): - return len(self.file_list) - - def download(self, url: Union[str, URL], dest: Union[str, Path]): + def _download(self, dl_item: DownloadItem, dest: Union[str, Path]): with httpx.Client(follow_redirects=True) as client_: - resp_ = client_.get(url) - filename = resp_.url.path.split('/')[-1] - if isinstance(dest, str): - dest = Path(dest) + resp_ = client_.get(dl_item.url) + filename = self._get_filename(dl_item) + dest = self._get_dest_folder(dest) with open(dest / filename, 'rb') as file_: file_.write(resp_.read()) with self.lock: self._progress_upd() + self._update_term_progress(filename) + + async def _async_download(self, dl_item: DownloadItem, dest: Union[str, Path]): + async with httpx.AsyncClient(follow_redirects=True) as client_: + resp_ = await client_.get(dl_item.url) + filename = self._get_filename(dl_item) + dest = self._get_dest_folder(dest) + with aiofiles.open(dest / filename, 'rb') as file_: + file_.write(resp_.read()) + with self.lock: + self._progress_upd() + self._update_term_progress(filename) + + @property + def len(self): + return len(self.task_list) - def __init__(self, file_list: List[Union[str, URL]], - progress_fmt: str = '{filename}|{bar}', - progress_char: str = '■', progress_width: int = 10): - self.file_list = UserList(file for file in file_list if self._validate(file)) + @property + def progress(self): + return self.finish_count / self.len + + def multi_download(self, max_connections: int = 5): # 多线程下载 max_connections impl: _tasks[::max_connections] + _tasks = [] + for s in self._get_connection_slice(_tasks, max_connections): + for file in s: + _dest = file.dest if file.dest is not None else self.dest_path + _tasks.append( + threading.Thread(target=self._download, kwargs={ + "url": file, + "dest": file.dest + }) + ) + + def async_multi_download(self, max_connections: int = 5): # 异步下载 + _tasks = [] + + def __init__(self, file_list: List[Union[str, tuple, URL, DownloadItem]], dest: Union[str, Path] = '', + progress_fmt: str = '{filename}|{bar}', progress_char: str = '■', bar_width: int = 10, + overwrite_dest: bool = False, __logger: Logger = logger): + self.cache = {} + self.task_list: List[DownloadItem] = [] + self.dest_path = dest + self.bar_width = bar_width self.progress_fmt = progress_fmt self.progress_char = progress_char - self.progress_width = progress_width - self.avg_progress = self._update_avg_progress() - self.progress = 0 - self.count = 0 - self.cache = {} + self.finish_count = 0 + self.logger: Logger = __logger self.lock = threading.Lock() + for file in file_list: + _item = self._convert_url(file) + if not _item.validate(): + continue + self.task_list.append(_item) + def __add__(self, other): - assert self._validate(other) - self.file_list.append(other) - self._update_avg_progress() + if not isinstance(other, (str, URL, httpx.URL)): + return None + _item = DownloadItem(url=other) + self.task_list.append(_item) diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..485f75f --- /dev/null +++ b/src/utils.py @@ -0,0 +1,13 @@ +import logging +import sys + +logger: logging.Logger = logging.getLogger('GI Bot') +default_handler = logging.StreamHandler(sys.stdout) +default_handler.setFormatter( + logging.Formatter('[%(asctime)s %(name)s] %(levelname)s: %(message)s')) +logger.addHandler(default_handler) + + +__all__ = [ + 'logger', +] From fb3a19844210bbc01fa69c66224aa13e39c3f4ec Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Tue, 7 Feb 2023 21:54:42 +0800 Subject: [PATCH 05/13] =?UTF-8?q?=F0=9F=8E=A8=20[=E8=87=AA=E5=8A=A8]?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 格式化代码 * 优化Import --- CHANGELOG.md | 33 +++- README.md | 20 ++- poetry.lock | 4 +- src/almanac/__init__.py | 4 +- src/artifact_collect/Artifact.py | 4 +- src/artifact_collect/__init__.py | 9 +- src/asset_manager.py | 163 ++---------------- src/gacha/__init__.py | 6 +- src/gacha/pool_data.py | 2 +- src/material_remind/__init__.py | 2 +- src/qiu_qiu_translation/__init__.py | 2 +- .../qiu_qiu_translation.py | 3 +- src/query_resource_points/__init__.py | 2 +- .../query_resource_points.py | 2 +- 14 files changed, 68 insertions(+), 188 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5d24ee..763b172 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,7 +51,10 @@ ### 2021-7-27 -* 对资源查询的代码逻辑进行调整,防止资源查询时出现killed @ [928e983](https://github.com/H-K-Y/Genshin_Impact_bot/commit/928e983) +* + +对资源查询的代码逻辑进行调整,防止资源查询时出现killed @ [928e983](https://github.com/H-K-Y/Genshin_Impact_bot/commit/928e983) + * 加入新命令 更新原神地图 用于爬取大地图文件 @ [91f5422](https://github.com/H-K-Y/Genshin_Impact_bot/commit/91f5422) ### 2021-6-2 @@ -67,7 +70,9 @@ ### 2021-3-24 -* 加入了原神黄历,黄历的数据来源于 [可莉特调](https://genshin.pub/) @ [3c85818](https://github.com/H-K-Y/Genshin_Impact_bot/commit/3c85818) +* + +加入了原神黄历,黄历的数据来源于 [可莉特调](https://genshin.pub/) @ [3c85818](https://github.com/H-K-Y/Genshin_Impact_bot/commit/3c85818) ### 2021-3-11 @@ -77,7 +82,10 @@ ### 2020-12-13 -* 资源列表查询现在改为直接抓取米游社地图的数据,每天自动更新 @ [24374bb](https://github.com/H-K-Y/Genshin_Impact_bot/commit/24374bb) +* + +资源列表查询现在改为直接抓取米游社地图的数据,每天自动更新 @ [24374bb](https://github.com/H-K-Y/Genshin_Impact_bot/commit/24374bb) + * 修复查询资源列表消息过长导致发送失败的问题 @ [88c219b](https://github.com/H-K-Y/Genshin_Impact_bot/commit/88c219b) ### 2020-11-26 @@ -90,7 +98,9 @@ ### 2020-11-3 -* 修复了找神瞳可以添加相同名称的编号导致报错的问题 @ [e38bb44](https://github.com/H-K-Y/Genshin_Impact_bot/commit/e38bb44) +* + +修复了找神瞳可以添加相同名称的编号导致报错的问题 @ [e38bb44](https://github.com/H-K-Y/Genshin_Impact_bot/commit/e38bb44) ### 2020-10-31 @@ -107,12 +117,17 @@ ### 2020-10-22 * 修复了4星概率写错了导致4星只能保底抽出的问题 @ [4476bed](https://github.com/H-K-Y/Genshin_Impact_bot/commit/4476bed) -* 加入了更多抽卡的统计结果,比如抽出最多的武器是啥,第一个4星和5星事多少抽出的 @ [f6d5cc6](https://github.com/H-K-Y/Genshin_Impact_bot/commit/f6d5cc6) +* + +加入了更多抽卡的统计结果,比如抽出最多的武器是啥,第一个4星和5星事多少抽出的 @ [f6d5cc6](https://github.com/H-K-Y/Genshin_Impact_bot/commit/f6d5cc6) ### 2020-10-21 -* 在config.py加入了抽卡限制功能,限制每个人一天最多抽多少次 @ [bcdcba0](https://github.com/H-K-Y/Genshin_Impact_bot/commit/bcdcba0) - 感谢[corvo007](https://github.com/corvo007)提出的粪pr (粪pr是他自己说的 +* + +在config.py加入了抽卡限制功能,限制每个人一天最多抽多少次 @ [bcdcba0](https://github.com/H-K-Y/Genshin_Impact_bot/commit/bcdcba0) +感谢[corvo007](https://github.com/corvo007)提出的粪pr (粪pr是他自己说的 + * 修复了第一次切换卡池后不能再切换卡池的问题 @ [2ea0ea2](https://github.com/H-K-Y/Genshin_Impact_bot/commit/2ea0ea2) * 修复了查看UP信息时报错的问题 @ [2ea0ea2](https://github.com/H-K-Y/Genshin_Impact_bot/commit/2ea0ea2) @@ -127,4 +142,6 @@ * 加入10连抽,90连抽和180连抽 @ [c2f43b4](https://github.com/H-K-Y/Genshin_Impact_bot/commit/c2f43b4) * 加入抽卡发送图片功能 @ [02b4592](https://github.com/H-K-Y/Genshin_Impact_bot/commit/02b4592) -* 修复了Windows系统发送图片时可能出现的路径问题,图片全部改为base64发送 @ [000122c](https://github.com/H-K-Y/Genshin_Impact_bot/commit/000122c) \ No newline at end of file +* + +修复了Windows系统发送图片时可能出现的路径问题,图片全部改为base64发送 @ [000122c](https://github.com/H-K-Y/Genshin_Impact_bot/commit/000122c) \ No newline at end of file diff --git a/README.md b/README.md index 29fce6f..3ffa420 100644 --- a/README.md +++ b/README.md @@ -10,18 +10,20 @@ ![LANG](https://img.shields.io/badge/language-python-3572A5?style=flat-square) ![Hoshino](https://img.shields.io/badge/%E7%89%88%E6%9C%AC-Hoshino-ff8a80?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyBkYXRhLXYtMTEyNDFiYTI9IiIgYXJpYS1oaWRkZW49InRydWUiIGZvY3VzYWJsZT0iZmFsc2UiIGRhdGEtcHJlZml4PSJmYXMiIGRhdGEtaWNvbj0iY29kZS1icmFuY2giIHJvbGU9ImltZyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMzg0IDUxMiIgY2xhc3M9InN2Zy1pbmxpbmUtLWZhIGZhLWNvZGUtYnJhbmNoIGZhLXctMTIiIGNvbG9yPSIjZmZmZmZmIj48cGF0aCBkYXRhLXYtMTEyNDFiYTI9IiIgZmlsbD0iY3VycmVudENvbG9yIiBkPSJNMzg0IDE0NGMwLTQ0LjItMzUuOC04MC04MC04MHMtODAgMzUuOC04MCA4MGMwIDM2LjQgMjQuMyA2Ny4xIDU3LjUgNzYuOC0uNiAxNi4xLTQuMiAyOC41LTExIDM2LjktMTUuNCAxOS4yLTQ5LjMgMjIuNC04NS4yIDI1LjctMjguMiAyLjYtNTcuNCA1LjQtODEuMyAxNi45di0xNDRjMzIuNS0xMC4yIDU2LTQwLjUgNTYtNzYuMyAwLTQ0LjItMzUuOC04MC04MC04MFMwIDM1LjggMCA4MGMwIDM1LjggMjMuNSA2Ni4xIDU2IDc2LjN2MTk5LjNDMjMuNSAzNjUuOSAwIDM5Ni4yIDAgNDMyYzAgNDQuMiAzNS44IDgwIDgwIDgwczgwLTM1LjggODAtODBjMC0zNC0yMS4yLTYzLjEtNTEuMi03NC42IDMuMS01LjIgNy44LTkuOCAxNC45LTEzLjQgMTYuMi04LjIgNDAuNC0xMC40IDY2LjEtMTIuOCA0Mi4yLTMuOSA5MC04LjQgMTE4LjItNDMuNCAxNC0xNy40IDIxLjEtMzkuOCAyMS42LTY3LjkgMzEuNi0xMC44IDU0LjQtNDAuNyA1NC40LTc1Ljl6TTgwIDY0YzguOCAwIDE2IDcuMiAxNiAxNnMtNy4yIDE2LTE2IDE2LTE2LTcuMi0xNi0xNiA3LjItMTYgMTYtMTZ6bTAgMzg0Yy04LjggMC0xNi03LjItMTYtMTZzNy4yLTE2IDE2LTE2IDE2IDcuMiAxNiAxNi03LjIgMTYtMTYgMTZ6bTIyNC0zMjBjOC44IDAgMTYgNy4yIDE2IDE2cy03LjIgMTYtMTYgMTYtMTYtNy4yLTE2LTE2IDcuMi0xNiAxNi0xNnoiIGNsYXNzPSIiPjwvcGF0aD48L3N2Zz4=) -![Nonebot2](https://img.shields.io/badge/%E7%89%88%E6%9C%AC-Nonebot2-a7ffeb?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyBkYXRhLXYtMTEyNDFiYTI9IiIgYXJpYS1oaWRkZW49InRydWUiIGZvY3VzYWJsZT0iZmFsc2UiIGRhdGEtcHJlZml4PSJmYXMiIGRhdGEtaWNvbj0iY29kZS1icmFuY2giIHJvbGU9ImltZyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMzg0IDUxMiIgY2xhc3M9InN2Zy1pbmxpbmUtLWZhIGZhLWNvZGUtYnJhbmNoIGZhLXctMTIiIGNvbG9yPSIjZmZmZmZmIj48cGF0aCBkYXRhLXYtMTEyNDFiYTI9IiIgZmlsbD0iY3VycmVudENvbG9yIiBkPSJNMzg0IDE0NGMwLTQ0LjItMzUuOC04MC04MC04MHMtODAgMzUuOC04MCA4MGMwIDM2LjQgMjQuMyA2Ny4xIDU3LjUgNzYuOC0uNiAxNi4xLTQuMiAyOC41LTExIDM2LjktMTUuNCAxOS4yLTQ5LjMgMjIuNC04NS4yIDI1LjctMjguMiAyLjYtNTcuNCA1LjQtODEuMyAxNi45di0xNDRjMzIuNS0xMC4yIDU2LTQwLjUgNTYtNzYuMyAwLTQ0LjItMzUuOC04MC04MC04MFMwIDM1LjggMCA4MGMwIDM1LjggMjMuNSA2Ni4xIDU2IDc2LjN2MTk5LjNDMjMuNSAzNjUuOSAwIDM5Ni4yIDAgNDMyYzAgNDQuMiAzNS44IDgwIDgwIDgwczgwLTM1LjggODAtODBjMC0zNC0yMS4yLTYzLjEtNTEuMi03NC42IDMuMS01LjIgNy44LTkuOCAxNC45LTEzLjQgMTYuMi04LjIgNDAuNC0xMC40IDY2LjEtMTIuOCA0Mi4yLTMuOSA5MC04LjQgMTE4LjItNDMuNCAxNC0xNy40IDIxLjEtMzkuOCAyMS42LTY3LjkgMzEuNi0xMC44IDU0LjQtNDAuNyA1NC40LTc1Ljl6TTgwIDY0YzguOCAwIDE2IDcuMiAxNiAxNnMtNy4yIDE2LTE2IDE2LTE2LTcuMi0xNi0xNiA3LjItMTYgMTYtMTZ6bTAgMzg0Yy04LjggMC0xNi03LjItMTYtMTZzNy4yLTE2IDE2LTE2IDE2IDcuMiAxNiAxNi03LjIgMTYtMTYgMTZ6bTIyNC0zMjBjOC44IDAgMTYgNy4yIDE2IDE2cy03LjIgMTYtMTYgMTYtMTYtNy4yLTE2LTE2IDcuMi0xNiAxNi0xNnoiIGNsYXNzPSIiPjwvcGF0aD48L3N2Zz4=) -![QQ](https://img.shields.io/badge/QQ-GI%20Bot%20Group-9cf?logo=Tencent%20QQ&style=for-the-badge) +![Nonebot2](https://img.shields.io/badge/%E7%89%88%E6%9C%AC-Nonebot2-a7ffeb?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyBkYXRhLXYtMTEyNDFiYTI9IiIgYXJpYS1oaWRkZW49InRydWUiIGZvY3VzYWJsZT0iZmFsc2UiIGRhdGEtcHJlZml4PSJmYXMiIGRhdGEtaWNvbj0iY29kZS1icmFuY2giIHJvbGU9ImltZyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMzg0IDUxMiIgY2xhc3M9InN2Zy1pbmxpbmUtLWZhIGZhLWNvZGUtYnJhbmNoIGZhLXctMTIiIGNvbG9yPSIjZmZmZmZmIj48cGF0aCBkYXRhLXYtMTEyNDFiYTI9IiIgZmlsbD0iY3VycmVudENvbG9yIiBkPSJNMzg0IDE0NGMwLTQ0LjItMzUuOC04MC04MC04MHMtODAgMzUuOC04MCA4MGMwIDM2LjQgMjQuMyA2Ny4xIDU3LjUgNzYuOC0uNiAxNi4xLTQuMiAyOC41LTExIDM2LjktMTUuNCAxOS4yLTQ5LjMgMjIuNC04NS4yIDI1LjctMjguMiAyLjYtNTcuNCA1LjQtODEuMyAxNi45di0xNDRjMzIuNS0xMC4yIDU2LTQwLjUgNTYtNzYuMyAwLTQ0LjItMzUuOC04MC04MC04MFMwIDM1LjggMCA4MGMwIDM1LjggMjMuNSA2Ni4xIDU2IDc2LjN2MTk5LjNDMjMuNSAzNjUuOSAwIDM5Ni4yIDAgNDMyYzAgNDQuMiAzNS44IDgwIDgwIDgwczgwLTM1LjggODAtODBjMC0zNC0yMS4yLTYzLjEtNTEuMi03NC42IDMuMS01LjIgNy44LTkuOCAxNC45LTEzLjQgMTYuMi04LjIgNDAuNC0xMC40IDY2LjEtMTIuOCA0Mi4yLTMuOSA5MC04LjQgMTE4LjItNDMuNCAxNC0xNy40IDIxLjEtMzkuOCAyMS42LTY3LjkgMzEuNi0xMC44IDU0LjQtNDAuNyA1NC40LTc1Ljl6TTgwIDY0YzguOCAwIDE2IDcuMiAxNiAxNnMtNy4yIDE2LTE2IDE2LTE2LTcuMi0xNi0xNiA3LjItMTYgMTYtMTZ6bTAgMzg0Yy04LjggMC0xNi03LjItMTYtMTZzNy4yLTE2IDE2LTE2IDE2IDcuMiAxNiAxNi03LjIgMTYtMTYgMTZ6bTIyNC0zMjBjOC44IDAgMTYgNy4yIDE2IDE2cy03LjIgMTYtMTYgMTYtMTYtNy4yLTE2LTE2IDcuMi0xNiAxNi0xNnoiIGNsYXNzPSIiPjwvcGF0aD48L3N2Zz4=) +![QQ](https://img.shields.io/badge/QQ-GI%20Bot%20Group-9cf?logo=Tencent%20QQ&style=for-the-badge) ->This is a Genshin Impact plugin for [HoshinoBot](https://github.com/Ice-Cirno/HoshinoBot) +> This is a Genshin Impact plugin for [HoshinoBot](https://github.com/Ice-Cirno/HoshinoBot) > >这是一个[HoshinoBot](https://github.com/Ice-Cirno/HoshinoBot)和[nonebot2](https://github.com/nonebot/nonebot2)的原神相关插件 ~~这个项目目前正在扩展,加入更多原神相关娱乐和信息查询功能,敬请期待~~ -#### 因原作者弃坑/nonebot进入beta时代/米游社API变动/多维度地图等诸多原因导致难以在原有版本上进行修改,将于不久后**停止对该版本功能的增加**并完全转向下一个版本;加群了解更多 [GI Bot Group](https://jq.qq.com/?_wv=1027&k=1faV2txy) +#### 因原作者弃坑/nonebot进入beta时代/米游社API变动/多维度地图等诸多原因导致难以在原有版本上进行修改,将于不久后* + +*停止对该版本功能的增加**并完全转向下一个版本;加群了解更多 [GI Bot Group](https://jq.qq.com/?_wv=1027&k=1faV2txy) 讨论群[GI Bot Group](https://jq.qq.com/?_wv=1027&k=1faV2txy) @@ -34,12 +36,12 @@ ## 目录 - **部署** - - [安装(HoshinoBot)](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%AE%89%E8%A3%85%EF%BC%88Hoshino%EF%BC%89) - - [安装(NoneBot2)](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%AE%89%E8%A3%85%EF%BC%88Nonebot2%EF%BC%89) + - [安装(HoshinoBot)](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%AE%89%E8%A3%85%EF%BC%88Hoshino%EF%BC%89) + - [安装(NoneBot2)](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%AE%89%E8%A3%85%EF%BC%88Nonebot2%EF%BC%89) - **使用** - - [命令](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%91%BD%E4%BB%A4) - - [演示](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E6%95%88%E6%9E%9C%E6%BC%94%E7%A4%BA) - - [常见问题](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) + - [命令](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%91%BD%E4%BB%A4) + - [演示](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E6%95%88%E6%9E%9C%E6%BC%94%E7%A4%BA) + - [常见问题](https://github.com/H-K-Y/Genshin_Impact_bot/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98) ## 更新记录 diff --git a/poetry.lock b/poetry.lock index 385ba64..4d3063d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -68,7 +68,7 @@ python-versions = ">=3.7" [package.dependencies] certifi = "*" httpcore = ">=0.15.0,<0.17.0" -rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} +rfc3986 = { version = ">=1.3,<2", extras = ["idna2008"] } sniffio = "*" [package.extras] @@ -106,7 +106,7 @@ optional = false python-versions = "*" [package.dependencies] -idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} +idna = { version = "*", optional = true, markers = "extra == \"idna2008\"" } [package.extras] idna2008 = ["idna"] diff --git a/src/almanac/__init__.py b/src/almanac/__init__.py index cf9f97c..252187a 100644 --- a/src/almanac/__init__.py +++ b/src/almanac/__init__.py @@ -1,7 +1,7 @@ -from hoshino import Service, priv, get_bot +from hoshino import get_bot, priv, Service from .almanac import get_almanac_base64_str, load_data -from .draw_lots import get_pic, draw_info, gen_pic +from .draw_lots import draw_info, gen_pic, get_pic from .tweaks import * FILE_PATH = os.path.dirname(__file__) diff --git a/src/artifact_collect/Artifact.py b/src/artifact_collect/Artifact.py index 2828f41..ddb954b 100644 --- a/src/artifact_collect/Artifact.py +++ b/src/artifact_collect/Artifact.py @@ -4,8 +4,8 @@ import random from io import BytesIO -from PIL import Image, ImageFont, ImageDraw, ImageMath -from config import SECONDARY_LEVEL_PROBABILITY, CONSUME_STRENGTHEN_POINTS +from config import CONSUME_STRENGTHEN_POINTS, SECONDARY_LEVEL_PROBABILITY +from PIL import Image, ImageDraw, ImageFont, ImageMath FILE_PATH = os.path.dirname(__file__) diff --git a/src/artifact_collect/__init__.py b/src/artifact_collect/__init__.py index c6f16aa..04ddc3c 100644 --- a/src/artifact_collect/__init__.py +++ b/src/artifact_collect/__init__.py @@ -1,10 +1,10 @@ import random -from config import STAMINA_RESTORE, MAX_STAMINA +from config import MAX_STAMINA, STAMINA_RESTORE from hoshino import Service -from .Artifact import artifact_obtain, ARTIFACT_LIST, Artifact, calculate_strengthen_points -from .json_rw import init_user_info, updata_uid_stamina, user_info, save_user_info +from .Artifact import Artifact, ARTIFACT_LIST, artifact_obtain, calculate_strengthen_points +from .json_rw import init_user_info, save_user_info, updata_uid_stamina, user_info sv = Service("原神圣遗物收集") @@ -261,7 +261,8 @@ async def _transform_all_strengthen(bot, ev): user_info[uid]["strengthen_points"] += strengthen_points save_user_info() - await bot.send(ev, f"0级圣遗物已全部转化为狗粮,共转化 {_0_level_artifact} 个圣遗物,获得狗粮点数 {strengthen_points}") + await bot.send(ev, + f"0级圣遗物已全部转化为狗粮,共转化 {_0_level_artifact} 个圣遗物,获得狗粮点数 {strengthen_points}") @sv.scheduled_job('interval', minutes=STAMINA_RESTORE) diff --git a/src/asset_manager.py b/src/asset_manager.py index 292de2b..67d16f0 100644 --- a/src/asset_manager.py +++ b/src/asset_manager.py @@ -1,17 +1,14 @@ import json -import threading -from collections import UserList from io import BytesIO from pathlib import Path -from sys import stdout from typing import List, Union -from logging import Logger import aiofiles -import httpx -from PIL import Image from httpx import URL -from .utils import logger +from PIL import Image + +from .asset_index import BuiltinAssets +from .downloader import Downloader, DownloadItem class BotAsset: @@ -59,6 +56,7 @@ def as_json(self, encoding='utf-8'): class BotAssetManager: def __init__(self, path: Path): self.path = path + self.files = [] def __truediv__(self, other): _new_path = self.path.joinpath(other) @@ -68,153 +66,16 @@ def __truediv__(self, other): return BotAsset(_new_path) return _new_path - def _get_path(self, absolute_path: Union[str, Path]): - _dest = self.path.joinpath(absolute_path) + def _get_path(self, relative_path: Union[str, Path]): + _dest = self.path.joinpath(relative_path) if not _dest.exists(): return None return _dest + def require(self, + asset_type: Union[BuiltinAssets, Union[str, URL, DownloadItem], List[Union[str, URL, DownloadItem]]]): + ... + def fetch_assets(self, assets_list: List[Union[str, URL]], max_connections: int = 5): _downloader = Downloader(file_list=assets_list) - - -class DownloadItem: - def __init__(self, url: Union[str, URL], dest: Union[str, Path, None] = None, **kwargs): - if isinstance(url, str): - url = URL(url=url) - if isinstance(dest, str): - dest = Path(dest) - self.url: URL = url - self.dest: Union[Path, None] = dest - if kwargs: - for k, v in kwargs.values(): - setattr(self, k, v) - - def validate(self): - if self.url.scheme in ['http', 'https']: - return True - return False - - -class Downloader: - @staticmethod - def _get_connection_slice(list_, chunk_size) -> List[List[DownloadItem]]: - n = len(list_) - return [list_[i:i + chunk_size] for i in range(0, n, chunk_size)] + [ - list_[n - n % chunk_size:]] if n % chunk_size != 0 else [] - - @staticmethod - def _clear_prev_line(): - stdout.write("\330[A\330[K\n") - - @staticmethod - def _guess_if_file(__item: DownloadItem) -> bool: - if '.' in __item.url.path: - return True - return False - - @staticmethod - def _get_filename(__item: DownloadItem): - return __item.url.path.split('/')[-1] - - @staticmethod - def _convert_url(url: Union[str, tuple, URL, httpx.URL]) -> Union[DownloadItem, None]: - if isinstance(url, tuple): - if len(url) < 1: - return None - if len(url) == 1: - return DownloadItem(url=url[0]) - - def _get_dest_folder(self, dest: Union[str, Path]): - if isinstance(dest, str): - dest = Path(dest) - if not dest.is_absolute(): - dest = self.dest_path / dest - if dest.is_file(): - dest = dest.parent - dest.mkdir(parents=True, exist_ok=True) - return dest - - def _update_term_progress(self, filename: str): - variables = { - "bar": self.progress_char * round(self.progress * self.bar_width), - "filename": filename, - "count": self.finish_count, - "len": self.len - } - if self.finish_count != 0: - self._clear_prev_line() - self.logger.info(self.progress_fmt.format(**variables)) - - def _progress_upd(self): - self.finish_count += 1 - - def _download(self, dl_item: DownloadItem, dest: Union[str, Path]): - with httpx.Client(follow_redirects=True) as client_: - resp_ = client_.get(dl_item.url) - filename = self._get_filename(dl_item) - dest = self._get_dest_folder(dest) - with open(dest / filename, 'rb') as file_: - file_.write(resp_.read()) - with self.lock: - self._progress_upd() - self._update_term_progress(filename) - - async def _async_download(self, dl_item: DownloadItem, dest: Union[str, Path]): - async with httpx.AsyncClient(follow_redirects=True) as client_: - resp_ = await client_.get(dl_item.url) - filename = self._get_filename(dl_item) - dest = self._get_dest_folder(dest) - with aiofiles.open(dest / filename, 'rb') as file_: - file_.write(resp_.read()) - with self.lock: - self._progress_upd() - self._update_term_progress(filename) - - @property - def len(self): - return len(self.task_list) - - @property - def progress(self): - return self.finish_count / self.len - - def multi_download(self, max_connections: int = 5): # 多线程下载 max_connections impl: _tasks[::max_connections] - _tasks = [] - for s in self._get_connection_slice(_tasks, max_connections): - for file in s: - _dest = file.dest if file.dest is not None else self.dest_path - _tasks.append( - threading.Thread(target=self._download, kwargs={ - "url": file, - "dest": file.dest - }) - ) - - def async_multi_download(self, max_connections: int = 5): # 异步下载 - _tasks = [] - - def __init__(self, file_list: List[Union[str, tuple, URL, DownloadItem]], dest: Union[str, Path] = '', - progress_fmt: str = '{filename}|{bar}', progress_char: str = '■', bar_width: int = 10, - overwrite_dest: bool = False, __logger: Logger = logger): - self.cache = {} - self.task_list: List[DownloadItem] = [] - self.dest_path = dest - self.bar_width = bar_width - self.progress_fmt = progress_fmt - self.progress_char = progress_char - self.finish_count = 0 - self.logger: Logger = __logger - self.lock = threading.Lock() - - for file in file_list: - _item = self._convert_url(file) - if not _item.validate(): - continue - self.task_list.append(_item) - - def __add__(self, other): - if not isinstance(other, (str, URL, httpx.URL)): - return None - _item = DownloadItem(url=other) - self.task_list.append(_item) + _downloader += self.files diff --git a/src/gacha/__init__.py b/src/gacha/__init__.py index 9bff6aa..6024ff4 100644 --- a/src/gacha/__init__.py +++ b/src/gacha/__init__.py @@ -1,11 +1,11 @@ import json import os -from config import Gacha10Limit, Gacha90Limit, Gacha180Limit -from hoshino import Service, priv +from config import Gacha10Limit, Gacha180Limit, Gacha90Limit +from hoshino import priv, Service from hoshino.util import DailyNumberLimiter -from .gacha import gacha_info, FILE_PATH, Gacha, POOL +from .gacha import FILE_PATH, Gacha, gacha_info, POOL from .pool_data import init_pool_list daily_limiter_10 = DailyNumberLimiter(Gacha10Limit) diff --git a/src/gacha/pool_data.py b/src/gacha/pool_data.py index d6b306b..728c56d 100644 --- a/src/gacha/pool_data.py +++ b/src/gacha/pool_data.py @@ -7,8 +7,8 @@ from io import BytesIO import httpx -from PIL import Image, ImageFont, ImageDraw, ImageMath from loguru import logger +from PIL import Image, ImageDraw, ImageFont, ImageMath FILE_PATH = os.path.dirname(__file__) ICON_PATH = os.path.join(FILE_PATH, 'icon') diff --git a/src/material_remind/__init__.py b/src/material_remind/__init__.py index bd2d2e1..4a21699 100644 --- a/src/material_remind/__init__.py +++ b/src/material_remind/__init__.py @@ -4,8 +4,8 @@ import time from io import BytesIO +from hoshino import get_bot, Service from PIL import Image -from hoshino import Service, get_bot sv = Service("原神每日素材提醒") diff --git a/src/qiu_qiu_translation/__init__.py b/src/qiu_qiu_translation/__init__.py index 8afdd3f..2c71032 100644 --- a/src/qiu_qiu_translation/__init__.py +++ b/src/qiu_qiu_translation/__init__.py @@ -1 +1 @@ -from .qiu_qiu_translation import qiu_qiu_word_translation, qiu_qiu_phrase_translation +from .qiu_qiu_translation import qiu_qiu_phrase_translation, qiu_qiu_word_translation diff --git a/src/qiu_qiu_translation/qiu_qiu_translation.py b/src/qiu_qiu_translation/qiu_qiu_translation.py index 4a1fff1..320f1a4 100644 --- a/src/qiu_qiu_translation/qiu_qiu_translation.py +++ b/src/qiu_qiu_translation/qiu_qiu_translation.py @@ -1,11 +1,10 @@ import json from pathlib import Path -from typing import Union, Tuple, List +from typing import List, Tuple, Union FILE_PATH = Path(__file__) DEFAULT_DICT = FILE_PATH / 'qiu_qiu_dictionary.json' - __all__ = ['DEFAULT_DICT', 'HilichurlDict', 'qiu_qiu_phrase_translation', 'qiu_qiu_word_translation'] diff --git a/src/query_resource_points/__init__.py b/src/query_resource_points/__init__.py index 8a2b5d8..aa33e0d 100644 --- a/src/query_resource_points/__init__.py +++ b/src/query_resource_points/__init__.py @@ -1,6 +1,6 @@ from hoshino import Service -from .query_resource_points import get_resource_map_mes, get_resource_list_mes, init_point_list_and_map +from .query_resource_points import get_resource_list_mes, get_resource_map_mes, init_point_list_and_map sv = Service("原神资源查询") diff --git a/src/query_resource_points/query_resource_points.py b/src/query_resource_points/query_resource_points.py index e9180a3..2c15578 100644 --- a/src/query_resource_points/query_resource_points.py +++ b/src/query_resource_points/query_resource_points.py @@ -6,8 +6,8 @@ from io import BytesIO import httpx -from PIL import Image, ImageMath from loguru import logger +from PIL import Image, ImageMath LABEL_URL = 'https://api-static.mihoyo.com/common/blackboard/ys_obc/v1/map/label/tree?app_sn=ys_obc' POINT_LIST_URL = 'https://api-static.mihoyo.com/common/blackboard/ys_obc/v1/map/point/list?map_id=2&app_sn=ys_obc' From 497f0e07ea52b449cce4ee7d0ae7a200fa767f22 Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Tue, 7 Feb 2023 21:57:12 +0800 Subject: [PATCH 06/13] =?UTF-8?q?=F0=9F=9A=A9=20=E6=8B=86=E5=88=86download?= =?UTF-8?q?er?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 拆分downloader * 添加BuiltinIndex 未完成 --- src/asset_index.py | 38 ++++++++++ src/downloader.py | 170 +++++++++++++++++++++++++++++++++++++++++++++ src/utils.py | 1 - 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 src/asset_index.py create mode 100644 src/downloader.py diff --git a/src/asset_index.py b/src/asset_index.py new file mode 100644 index 0000000..84e2439 --- /dev/null +++ b/src/asset_index.py @@ -0,0 +1,38 @@ +from collections import UserList +from enum import Enum +from typing import Sequence, Union + +from httpx import URL + +from .asset_manager import DownloadItem + +__all__ = ['BuiltinAssets'] + + +class BuiltinAssetBase(UserList): + type: str + description: str + + +class BuiltinAssetGroup(BuiltinAssetBase): + def __init__(self, asset_type: str, description: str, urls: Sequence[Union[str, URL, DownloadItem]]): + self.type = asset_type + self.description = description + super().__init__(urls) + + +class GameItems( + BuiltinAssetBase): # use https://waf-api-takumi.mihoyo.com/common/map_user/ys_obc/v1/map/game_item?map_id=2&app_sn=ys_obc&lang=zh-cn + def _fetch_index(self): + ... + + +class GameMaps( + BuiltinAssetBase): # use https://api-static.mihoyo.com/common/map_user/ys_obc/v1/map/info?map_id=2&app_sn=ys_obc&lang=zh-cn + def _get_map_index(self): + ... + + +class BuiltinAssets(Enum): + game_item_all = GameItems() + map = GameMaps() diff --git a/src/downloader.py b/src/downloader.py new file mode 100644 index 0000000..97836a4 --- /dev/null +++ b/src/downloader.py @@ -0,0 +1,170 @@ +import asyncio +import threading +import uuid +from concurrent.futures import ThreadPoolExecutor +from logging import Logger +from pathlib import Path +from sys import stdout +from typing import List, Union + +import aiofiles +import httpx +from httpx import URL + +from .utils import logger + + +class DownloadItem: + def __init__(self, url: Union[str, URL], dest: Union[str, Path, None] = None, **kwargs): + if isinstance(url, str): + url = URL(url=url) + if isinstance(dest, str): + dest = Path(dest) + self.url: URL = url + self.trace_id = uuid.uuid4() + self.dest: Union[Path, None] = dest + if kwargs: + for k, v in kwargs.values(): + setattr(self, k, v) + + def validate(self): + if self.url.scheme in ['http', 'https']: + return True + return False + + +class Downloader: + @staticmethod + def _get_connection_slice(list_, chunk_size) -> List[List[DownloadItem]]: + n = len(list_) + return [list_[i:i + chunk_size] for i in range(0, n, chunk_size)] + [ + list_[n - n % chunk_size:]] if n % chunk_size != 0 else [] + + @staticmethod + def _clear_prev_line(): + stdout.write("\330[A\330[K\n") + + @staticmethod + def _guess_if_file(__item: DownloadItem) -> bool: + if '.' in __item.url.path: + return True + return False + + @staticmethod + def _get_filename(__item: DownloadItem): + return __item.url.path.split('/')[-1] + + @staticmethod + def _convert_url(url: Union[str, tuple, URL, httpx.URL]) -> Union[DownloadItem, None]: + if isinstance(url, tuple): + if len(url) < 1: + return None + if len(url) == 1: + return DownloadItem(url=url[0]) + if len(url) >= 2: + return DownloadItem(*url[:2]) + return DownloadItem(url=url) + + def _get_dest_folder(self, dest: Union[str, Path]): + if isinstance(dest, str): + dest = Path(dest) + if not dest.is_absolute(): + dest = self.dest_path / dest + if dest.is_file(): + dest = dest.parent + dest.mkdir(parents=True, exist_ok=True) + return dest + + def _update_term_progress(self, filename: str): + variables = { + "bar": self.progress_char * round(self.progress * self.bar_width), + "filename": filename, + "count": self.finish_count, + "len": self.len + } + if self.finish_count != 0: + self._clear_prev_line() + self.logger.info(self.progress_fmt.format(**variables)) + + def _progress_upd(self): + self.finish_count += 1 + + def _download(self, dl_item: DownloadItem): + with httpx.Client(follow_redirects=True) as client_: + _filename = self._get_filename(dl_item) + _resp = client_.get(dl_item.url) + with self.lock: + self._progress_upd() + self._update_term_progress(_filename) + if _resp.status_code != 200: + return False + dest = self._get_dest_folder(dl_item.dest) if dl_item is not None else self.dest_path + with open(dest / _filename, 'rb') as file_: + file_.write(_resp.read()) + return True + + async def _async_download(self, dl_item: DownloadItem): + async with httpx.AsyncClient(follow_redirects=True) as client_: + _filename = self._get_filename(dl_item) + resp_ = await client_.get(dl_item.url) + with self.lock: + self._progress_upd() + self._update_term_progress(_filename) + if resp_.status_code != 200: + return False + dest = self._get_dest_folder(dl_item.dest) if dl_item is not None else self.dest_path + with aiofiles.open(dest / _filename, 'rb') as file_: + await file_.write(resp_.read()) + return True + + @property + def len(self): + return len(self.task_list) + + @property + def progress(self): + return self.finish_count / self.len + + def multi_download(self, max_connections: int = 5): # 多线程下载 max_connections impl: _tasks[::max_connections] + with ThreadPoolExecutor(max_workers=max_connections) as executor: + _result = [executor.submit(self._download, dl_item=item_) for item_ in self.task_list] + result_state = [r.done() for r in _result] + success_count = result_state.count(True) + if not all(result_state): + self.logger.warning(f'下载完毕。| 成功: {success_count} 失败: {len(result_state) - success_count}') + return False + self.logger.info(f'下载完毕。已完成 {success_count} 个下载任务。') + return True + + def async_multi_download(self, max_connections: int = 5): # 异步下载 + _tasks = [] + for item_ in self.task_list: + _tasks.append(asyncio.create_task(self._async_download(item_))) + chunks = self._get_connection_slice(_tasks, max_connections) + for chunk in chunks: + _ = asyncio.gather(*chunk) + + def __init__(self, file_list: List[Union[str, tuple, URL, DownloadItem]], dest: Union[str, Path] = '', + progress_fmt: str = '{filename}|{bar}', progress_char: str = '■', bar_width: int = 10, + overwrite_dest: bool = False, __logger: Logger = logger): + self.cache = {} + self.task_list: List[DownloadItem] = [] + self.dest_path = dest + self.bar_width = bar_width + self.progress_fmt = progress_fmt + self.progress_char = progress_char + self.finish_count = 0 + self.logger: Logger = __logger + self.lock = threading.Lock() + + for file in file_list: + _item = self._convert_url(file) + if not _item.validate(): + continue + self.task_list.append(_item) + + def __iadd__(self, other): + if not isinstance(other, (str, URL, httpx.URL)): + return + _item = DownloadItem(url=other) + self.task_list.append(_item) diff --git a/src/utils.py b/src/utils.py index 485f75f..65534eb 100644 --- a/src/utils.py +++ b/src/utils.py @@ -7,7 +7,6 @@ logging.Formatter('[%(asctime)s %(name)s] %(levelname)s: %(message)s')) logger.addHandler(default_handler) - __all__ = [ 'logger', ] From afcfb9869f63657fa065bcd1ee8b245080d90e42 Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Thu, 2 Mar 2023 10:09:47 +0800 Subject: [PATCH 07/13] =?UTF-8?q?=E2=9A=97=EF=B8=8F=20Config&Database=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit !Config并不理想,直接使用Pydantic可能会更好 --- database.py | 62 ++++++++++++++++ src/config.py | 89 +++++++++++++++++++++++ src/database.py | 156 ++++++++++++++++++++++++++++++++++++++++ tests/test_almanac.py | 0 tests/test_hilichurl.py | 0 5 files changed, 307 insertions(+) create mode 100644 database.py create mode 100644 src/config.py create mode 100644 src/database.py create mode 100644 tests/test_almanac.py create mode 100644 tests/test_hilichurl.py diff --git a/database.py b/database.py new file mode 100644 index 0000000..cbfe3e6 --- /dev/null +++ b/database.py @@ -0,0 +1,62 @@ +import sqlite3 +from enum import Enum +from pathlib import Path +from typing import Tuple, List, Union, Optional, get_type_hints + + +class SqliteType(Enum): + INTEGER = "INTEGER" + PRIMARY = "PRIMARY KEY" + REAL = "REAL" + TEXT = "TEXT" + BLOB = "BLOB" + NULL = "NULL" + + +class TableBase: + def _get_typing_hints(self): + return + + +class Database: + def __init__(self, db: Union[str, Path]): + self._conn = sqlite3.connect(str(db)) + + def _get_cursor(self): + return self._conn.cursor() + + def _chk_column_def(self, columns: List[Tuple[str, SqliteType, Optional[bool]]]) -> bool: + if all(isinstance(col_, tuple) and len(col_) >= 2 and len() for col_ in columns) + return True + return False + + + + def list_tables(self) -> list: + cursor_ = self.execute("SELECT name FROM sqlite_master WHERE type='table';") + return list(cursor_.fetchall()) + + def execute(self, sql: str, params: Tuple = None): + cursor = self._get_cursor() + if params: + cursor.execute(sql, params) + else: + cursor.execute(sql) + self._conn.commit() + return cursor + + def create_table(self, name: str, columns: List[Tuple[str, SqliteType, Optional[bool]]], gen_id: Optional[bool] = True): + if not all(isinstance(datatype, SqliteType) for col, datatype in columns): + raise TypeError("Datatype must be a SqliteType") + if gen_id: + columns = [('ID', SqliteType)] + formatted_table_schema = ', '.join( + f'{col[0]} {col[1].value}' if len(col) == 2 else f'{col[0]} {col[1].value} NOT NULL' for col in columns + ) + table_sql = f'CREATE TABLE IF NOT EXISTS {name} ({formatted_table_schema})' + + +class Table: + def __init__(self, name: str, columns: List[Tuple[str, SqliteType]], db: Database): + self.name = name + self.columns = columns \ No newline at end of file diff --git a/src/config.py b/src/config.py new file mode 100644 index 0000000..38770de --- /dev/null +++ b/src/config.py @@ -0,0 +1,89 @@ +from pathlib import Path +from collections import UserDict +from typing import Callable, Optional, Union, Type, TypeVar, Dict + +from tomlkit import TOMLDocument +from tomlkit.items import Table, Trivia +from .utils import logger + + +TomlAvailType = Union[str, bool, int, float, list, tuple, dict] +TomlAvailTypes = (str, bool, int, float, list, tuple, dict) +TomlAvailClasses = TypeVar('TomlAvailClasses', bound=TomlAvailType) + + +class ConfigField: + description: str + """ + Fields of config, note that `tuple` will be automatically converted to list(array) + """ + def __init__(self, __type: Type[TomlAvailClasses], + description: Optional[Union[str, None]] = None, + default: Optional[Union[TomlAvailType, None]] = None): + if __type not in {str, bool, int, float, list, tuple, dict}: + self._type = str + else: + self._type = __type + self.description = description + if isinstance(default, self._type): + self._value = default + else: + self._value = self._type() + + def update(self, value: TomlAvailType): + if isinstance(value, self._type): + self._value = value + else: + self._value = self._type(value) + + def clear(self): + self._value = self._type() + + @property + def value(self): + return self._value + + @property + def type(self): + return self._type + + +class BaseContainer(UserDict): + def __init__(self, on_error: Optional[Callable] = logger.error): + self.__on_error = on_error + self._update_fields() + super().__init__() + + def _update_fields(self): + _fields = filter(lambda x: not x[0].startswith('_'), self.__class__.__dict__.items()) + for _field_name, _field_definition in _fields: + if _field_definition in {str, bool, int, float, list, tuple}: + self[_field_name] = ConfigField(_field_definition) + if isinstance(_field_definition, ConfigField): + self[_field_name] = _field_definition + + +class ConfigTable(BaseContainer): + def __init__(self, **fields: Union[Type[ConfigField], Type[TomlAvailType]]): + super().__init__() + self._update_fields() + + for _field_name, _field_definition in fields.items(): + if _field_definition in {str, bool, int, float, list, tuple}: + self[_field_name] = ConfigField(_field_definition) + if isinstance(_field_definition, ConfigField): + self[_field_name] = _field_definition + + +class ConfigBase(BaseContainer): + """ + ConfigBase. + + Example: + class MyConfig(ConfigBase): + foo = ConfigField(str, description="foo", default="bar") + + config = MyConfig('./config.toml') + assert config.foo == "bar" + """ + ... diff --git a/src/database.py b/src/database.py new file mode 100644 index 0000000..09c8349 --- /dev/null +++ b/src/database.py @@ -0,0 +1,156 @@ +import sqlite3 +from enum import Enum +from pathlib import Path +from typing import Tuple, List, Union, Optional, Mapping, Any + +from pydantic import BaseModel + + +SQL_KEY_STRING = [ + 'select', 'where', 'order', 'limit', + 'offset', 'delete', 'pragma', 'alter' +] + + +class SqliteType(Enum): + INTEGER = "INTEGER" + PRIMARY = "PRIMARY KEY" + REAL = "REAL" + TEXT = "TEXT" + BLOB = "BLOB" + NULL = "NULL" + + +class Sql(str): + def __init__(self, base_sql: str = ''): + assert self._check_if_sql(base_sql) + self.__split_sql: list = self.split_sql() + super().__init__(base_sql) + + @staticmethod + def _check_if_sql(sql: str): + if any(_[0].startswith(_[1]) for _ in zip([sql.split()[0].lower()] * len(SQL_KEY_STRING), SQL_KEY_STRING)): + return True + return False + + def split_sql(self) -> list: + split_ = self.split() + index_list = [ + index for index, s in enumerate(split_) if s.lower() in SQL_KEY_STRING + ] + return [ + split_[:index_] if pos == 0 else split_[index_ - 1:index_] + for pos, index_ in enumerate(index_list) + ] + + def join_sql(self, other: str): + self.__split_sql.append(other) + + +class Database: + def __init__(self, db: Union[str, Path]): + if isinstance(db, Path): + db = str(db.absolute()) + self._conn = sqlite3.connect(db) + self.commit = self._conn.commit + + def __getattr__(self, item): + return Table(item, self) + + def __getitem__(self, item): + return Table(item, self) + + def _get_cursor(self): + return self._conn.cursor() + + def list_tables(self) -> list: + cursor_ = self.execute("SELECT name FROM sqlite_master WHERE type='table';") + return list(cursor_.fetchall()) + + def execute(self, sql: str, params: Union[Tuple[Union[str, bytes, bytearray, memoryview, int, float]], None] = None): + cursor = self._get_cursor() + if params: + cursor.execute(sql, params) + else: + cursor.execute(sql) + self._conn.commit() + return cursor + + def create_table(self, name: str, columns: List[Tuple[str, SqliteType, Optional[bool]]], + gen_id: Optional[bool] = True): + if not all(isinstance(datatype, SqliteType) for col, datatype in columns): + raise TypeError("Datatype must be a SqliteType") + if gen_id: + columns = [('ID', SqliteType), *columns] + formatted_table_schema = ', '.join( + f'{col[0]} {col[1].value}' if len(col) == 2 else f'{col[0]} {col[1].value} NOT NULL' for col in columns + ) + create_table_sql = f'create table if not exists {name} ({formatted_table_schema})' + self.execute(sql=create_table_sql) + + +class Table: + def __init__(self, name: str, __database: Database): + self._name = name + self._database = __database + + self.execute = self._database.execute + self.commit = self._database.commit + + @staticmethod + def _check_column_def(columns: List[Tuple[str, SqliteType, Optional[bool]]]) -> bool: + if all(isinstance(col_, tuple) for col_ in columns): + return True + return False + + def exists(self): + _result = self.execute( + f"SELECT name FROM sqlite_master WHERE type='table' AND name='{self._name}';" + ).fetchall() + if _result: + return True + return False + + def get_schema(self): + _schema_info = self.execute(f'pragma table_info({self._name});').fetchall() + return ', '.join(f'{si_[1]} {si_[2]}{" NOT NULL" if si_[3] else ""}' for si_ in _schema_info) + + def drop(self): + self.execute(f'drop table if exists {self._name}') + + def delete(self, __filter: Mapping[str, Any], maximum: int = None, auto_commit: bool = True): + delete_sql = f'delete from {self._name}' + if __filter: + delete_sql += ' where ' + \ + ' and '.join(f'{k} == ?' for k in __filter.keys()) + if maximum: + delete_sql += f' limit {maximum}' + cursor = self.execute(delete_sql) + + def find(self, __filter: Mapping[str, Any], maximum: int = None): + find_sql = f'select * from {self._name} where ' + \ + ' and '.join(f'{k} == ?' for k in __filter.keys()) + if maximum: + find_sql += f' limit {maximum}' + return self.execute(find_sql, params=tuple(__filter.values())).fetchall() + + def find_one(self, __filter: Mapping[str, Any]): + find_sql = f'select * from {self._name} where ' + \ + ' and '.join(f'{k} == ?' for k in __filter.keys()) + ' limit 1' + return self.execute(find_sql, params=tuple(__filter.values())).fetchone() + + def insert(self, __obj: Mapping[str, Any], auto_commit: bool = True): + insert_sql = f'insert into {self._name} ({", ".join(__obj.keys())}) values ({", ".join(__obj.values())})' + cursor_ = self.execute(insert_sql) + if auto_commit: + self.commit() + return cursor_.rowcount + + def update(self, __filter: Mapping[str, Any], __updates: Mapping[str, Any], auto_commit: bool = True): + where_sql_snippet = ' and '.join(f'{k} == ?' for k in __filter.keys()) + set_sql_snippet = ', '.join(f'{k} = ?' for k in __updates.keys()) + update_sql = f'update {self._name} set {set_sql_snippet} where {where_sql_snippet}' + cursor_ = self.execute(update_sql) + if auto_commit: + self.commit() + return cursor_.rowcount diff --git a/tests/test_almanac.py b/tests/test_almanac.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_hilichurl.py b/tests/test_hilichurl.py new file mode 100644 index 0000000..e69de29 From ab6fe567f5c8e284eddddcf96d3ede559dd41b3b Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Thu, 2 Mar 2023 11:48:59 +0800 Subject: [PATCH 08/13] =?UTF-8?q?=F0=9F=92=A9=20=E5=8F=A6=E4=B8=80?= =?UTF-8?q?=E7=A7=8D=E5=8F=AF=E8=83=BD=E7=9A=84config=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit !氵代码 懒得想json怎么搞注释了 --- src/config.py | 172 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 103 insertions(+), 69 deletions(-) diff --git a/src/config.py b/src/config.py index 38770de..7226d97 100644 --- a/src/config.py +++ b/src/config.py @@ -1,81 +1,91 @@ +import json +from abc import ABC, abstractmethod from pathlib import Path from collections import UserDict -from typing import Callable, Optional, Union, Type, TypeVar, Dict +from typing import Callable, Optional, Union, Type, TypeVar, Dict, Literal +import tomlkit +from pydantic import BaseModel, create_model from tomlkit import TOMLDocument from tomlkit.items import Table, Trivia from .utils import logger -TomlAvailType = Union[str, bool, int, float, list, tuple, dict] -TomlAvailTypes = (str, bool, int, float, list, tuple, dict) -TomlAvailClasses = TypeVar('TomlAvailClasses', bound=TomlAvailType) +class SimpleLoaderBase(ABC): + def __init__(self, path: Union[str, Path], encoding: str = 'utf-8'): + if not isinstance(path, Path): + path = Path(Path) + self.__path = path + self.encoding = encoding + @abstractmethod + def load(self): + ... -class ConfigField: - description: str - """ - Fields of config, note that `tuple` will be automatically converted to list(array) - """ - def __init__(self, __type: Type[TomlAvailClasses], - description: Optional[Union[str, None]] = None, - default: Optional[Union[TomlAvailType, None]] = None): - if __type not in {str, bool, int, float, list, tuple, dict}: - self._type = str - else: - self._type = __type - self.description = description - if isinstance(default, self._type): - self._value = default - else: - self._value = self._type() - - def update(self, value: TomlAvailType): - if isinstance(value, self._type): - self._value = value - else: - self._value = self._type(value) - - def clear(self): - self._value = self._type() - - @property - def value(self): - return self._value - - @property - def type(self): - return self._type - - -class BaseContainer(UserDict): - def __init__(self, on_error: Optional[Callable] = logger.error): - self.__on_error = on_error - self._update_fields() - super().__init__() - - def _update_fields(self): - _fields = filter(lambda x: not x[0].startswith('_'), self.__class__.__dict__.items()) - for _field_name, _field_definition in _fields: - if _field_definition in {str, bool, int, float, list, tuple}: - self[_field_name] = ConfigField(_field_definition) - if isinstance(_field_definition, ConfigField): - self[_field_name] = _field_definition - - -class ConfigTable(BaseContainer): - def __init__(self, **fields: Union[Type[ConfigField], Type[TomlAvailType]]): - super().__init__() - self._update_fields() - - for _field_name, _field_definition in fields.items(): - if _field_definition in {str, bool, int, float, list, tuple}: - self[_field_name] = ConfigField(_field_definition) - if isinstance(_field_definition, ConfigField): - self[_field_name] = _field_definition - - -class ConfigBase(BaseContainer): + @abstractmethod + def save(self, __obj): + ... + + @abstractmethod + async def async_load(self): + ... + + @abstractmethod + async def async_save(self, __obj): + ... + + +class JSONLoader(SimpleLoaderBase): + def __dumps_data(self, __data: dict, __schema: dict): + _result = {} + _properties = __schema['properties'] + for k, v in _properties: + ... + + + def load(self): + with open(self.__path, 'r', encoding=self.encoding) as _config_file: + return json.load(_config_file) + + def save(self, __obj: 'ConfigBase'): + _properties = __obj.schema().get('properties') + _data = __obj.dict() + with open(self.__path, 'w+', encoding=self.encoding) as _config_file: + json.dump(obj=__obj, fp=_config_file, ensure_ascii=False) + + async def async_load(self): + return self.load() + + async def async_save(self, __obj): + return self.save(__obj) + + +class TomlLoader(SimpleLoaderBase): + def load(self): + with open(self.__path, 'r', encoding=self.encoding) as _config_file: + return tomlkit.load(_config_file) + + def save(self, __obj): + with open(self.__path, 'w+', encoding=self.encoding) as _config_file: + tomlkit.dump(__obj, _config_file) + + async def async_load(self): + return self.load() + + async def async_save(self, __obj): + return self.save(__obj) + + +def get_loader(file_ext: str): + file_ext = file_ext.lower() + if file_ext == 'json': + return JSONLoader + if file_ext == 'toml': + return TomlLoader + return None + + +class ConfigBase(BaseModel): """ ConfigBase. @@ -86,4 +96,28 @@ class MyConfig(ConfigBase): config = MyConfig('./config.toml') assert config.foo == "bar" """ - ... + + @staticmethod + def __check_config_ext(path: Union[str, Path]): + if not isinstance(path, Path): + path = Path(path) + _name_split = path.name.lower().split() + if len(_name_split) <= 2: + return None + if _name_split[-1] in ['json', 'toml', 'conf', 'ini']: + return _name_split[-1] + return None + + def reload(self): + self.__data = self.__loader.load() + self.model = self.parse_obj(self.__data) + + def save(self): + ... + + def __init__(self, path: Union[str, Path]): + _loader = get_loader(self.__check_config_ext(path)) + self.__config_path = path + self.__loader: SimpleLoaderBase = _loader(path) + self.__data = self.__loader.load() + self.model = super().__init__(**self.__data) From ada8f31f202dab02778b5bf987c119f82e2905e7 Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Sat, 4 Mar 2023 22:48:12 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=E2=9C=A8=20=E5=8F=AF=E7=94=A8=E7=9A=84?= =?UTF-8?q?=E7=AE=80=E5=8D=95Config=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 简单的Config实现。 * 支持使用pydantic Model & Field 作为值 * 支持在配置类中的键发生改变时同步更新toml文件 * 就像使用pydantic Model一样简单! --- src/config.py | 211 ++++++++++++++++++++++--------------------- tests/test_config.py | 0 2 files changed, 107 insertions(+), 104 deletions(-) create mode 100644 tests/test_config.py diff --git a/src/config.py b/src/config.py index 7226d97..4358805 100644 --- a/src/config.py +++ b/src/config.py @@ -1,123 +1,126 @@ -import json -from abc import ABC, abstractmethod from pathlib import Path -from collections import UserDict -from typing import Callable, Optional, Union, Type, TypeVar, Dict, Literal +from typing import Any, Tuple, Type, Union, TypeVar, Optional import tomlkit -from pydantic import BaseModel, create_model -from tomlkit import TOMLDocument -from tomlkit.items import Table, Trivia -from .utils import logger +from pydantic import BaseModel, PrivateAttr, ValidationError +from pydantic.error_wrappers import ErrorWrapper +from tomlkit import TOMLDocument, comment - -class SimpleLoaderBase(ABC): - def __init__(self, path: Union[str, Path], encoding: str = 'utf-8'): - if not isinstance(path, Path): - path = Path(Path) - self.__path = path - self.encoding = encoding - - @abstractmethod - def load(self): - ... - - @abstractmethod - def save(self, __obj): - ... - - @abstractmethod - async def async_load(self): - ... - - @abstractmethod - async def async_save(self, __obj): - ... - - -class JSONLoader(SimpleLoaderBase): - def __dumps_data(self, __data: dict, __schema: dict): - _result = {} - _properties = __schema['properties'] - for k, v in _properties: - ... - - - def load(self): - with open(self.__path, 'r', encoding=self.encoding) as _config_file: - return json.load(_config_file) - - def save(self, __obj: 'ConfigBase'): - _properties = __obj.schema().get('properties') - _data = __obj.dict() - with open(self.__path, 'w+', encoding=self.encoding) as _config_file: - json.dump(obj=__obj, fp=_config_file, ensure_ascii=False) - - async def async_load(self): - return self.load() - - async def async_save(self, __obj): - return self.save(__obj) - - -class TomlLoader(SimpleLoaderBase): - def load(self): - with open(self.__path, 'r', encoding=self.encoding) as _config_file: - return tomlkit.load(_config_file) - - def save(self, __obj): - with open(self.__path, 'w+', encoding=self.encoding) as _config_file: - tomlkit.dump(__obj, _config_file) - - async def async_load(self): - return self.load() - - async def async_save(self, __obj): - return self.save(__obj) - - -def get_loader(file_ext: str): - file_ext = file_ext.lower() - if file_ext == 'json': - return JSONLoader - if file_ext == 'toml': - return TomlLoader - return None +__all__ = ['ConfigBase'] +Model = TypeVar('Model', bound='BaseModel') class ConfigBase(BaseModel): """ - ConfigBase. + ConfigBase. Note that due to problems with the upstream `tomlkit`, + you may not be able to add comments to the bool type or table. Example: class MyConfig(ConfigBase): - foo = ConfigField(str, description="foo", default="bar") + foo: str = Field('bar', description="foo") config = MyConfig('./config.toml') assert config.foo == "bar" - """ - - @staticmethod - def __check_config_ext(path: Union[str, Path]): - if not isinstance(path, Path): - path = Path(path) - _name_split = path.name.lower().split() - if len(_name_split) <= 2: - return None - if _name_split[-1] in ['json', 'toml', 'conf', 'ini']: - return _name_split[-1] - return None - def reload(self): - self.__data = self.__loader.load() - self.model = self.parse_obj(self.__data) + Also support: + class ConfTable(BaseModel): + table_member: int = 1 - def save(self): - ... + class MyConfig(ConfigBase): + foo: str = Field('bar', description="foo") + table1: ConfTable = ConfTable() + """ + __config_path: Path = PrivateAttr(Path('./config.toml')) + __toml_document: TOMLDocument = PrivateAttr(TOMLDocument()) + + class Config: + anystr_strip_whitespace = True + use_enum_values = True + validate_assignment = True + + def _model2conf(self, _data: BaseModel) -> TOMLDocument: + _result = TOMLDocument() + for k, v in _data.__fields__.items(): + _key = v.field_info.alias if v.field_info.alias else k + if issubclass(v.type_, BaseModel): + _result[_key] = self._model2conf(_data.__getattribute__(k)) + else: + _result[_key] = _data.__getattribute__(k) + if v.field_info.description: + _result.item(_key).comment(v.field_info.description) + return _result + + def load(self, config_path: Optional[Path] = None) -> TOMLDocument: + """ + Load from toml file. + + :param config_path: Path object + :return: TOMLDocument object + """ + if not config_path: + config_path = self.__config_path + if not config_path.exists(): + self.save(config_path) + with open(config_path, 'r', encoding='utf-8') as _config: + _document = tomlkit.load(_config) + self.__toml_document = _document + if set(_document) ^ set(self.__toml_document): # modify the toml file when the configuration key changed + self.save() + return _document + + def reload(self) -> Tuple[Path, TOMLDocument]: + """ + Reload the configuration. + """ + self.load() + self.parse_obj(self.__toml_document) + return self.__config_path, self.__toml_document + + def save(self, file_path: Optional[Path] = None): + """ + Save the configuration file to specified file path. + :param file_path: Path object + """ + _conf_doc = TOMLDocument() + _doc_desc = self.schema().get('description', None) + if _doc_desc and _doc_desc != ConfigBase.schema().get('description', None): + _conf_doc.add(comment(_doc_desc)) + _conf_doc.update(self._model2conf(self)) + self.__toml_document = _conf_doc + if not file_path: + file_path = self.__config_path + if not file_path.parent.exists(): + file_path.mkdir(parents=True) + with open(file_path, 'w+', encoding='utf8') as _config: + tomlkit.dump(_conf_doc, _config) + + def parse_obj(self: Type['Model'], obj: Any) -> 'Model': + """ + Fix the problem in the parse_obj of the parent class after modifying the __init__ method + :param obj: Any object + :return: Model + """ + obj = self._enforce_dict_if_root(obj) + if not isinstance(obj, dict): + try: + obj = dict(obj) + except (TypeError, ValueError) as e: + exc = TypeError(f'{self.__name__} expected dict not {obj.__class__.__name__}') + raise ValidationError([ErrorWrapper(exc, loc='__root__')], self) from e + return super().__init__(**dict(self.__toml_document)) def __init__(self, path: Union[str, Path]): - _loader = get_loader(self.__check_config_ext(path)) + """ + Initialize the Config object from the given path + :param path: string or Path object + """ + if not isinstance(path, Path): + path = Path(path) + if not path.exists(): + super().__init__() + self.save(path) + self.__config_path = path + _document = self.load() + super().__init__(**dict(_document)) self.__config_path = path - self.__loader: SimpleLoaderBase = _loader(path) - self.__data = self.__loader.load() - self.model = super().__init__(**self.__data) + self.__toml_document = _document diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 0000000..e69de29 From 6d9ff8c2d5268f04f7fb79fd9c2eb9f1ef3f8911 Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Sat, 4 Mar 2023 22:50:46 +0800 Subject: [PATCH 10/13] =?UTF-8?q?=E2=9E=95=20=E6=B7=BB=E5=8A=A0=E4=BE=9D?= =?UTF-8?q?=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 注意:无论是hoshino抑或是nonebot,其依赖均包含此次新增的两项依赖,实际部署时无需用户手动安装 --- poetry.lock | 340 ++++++++++++++++++++++++++++++++++++++++++++++--- pyproject.toml | 5 + 2 files changed, 327 insertions(+), 18 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4d3063d..93e003e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Poetry and should not be changed by hand. + [[package]] name = "aiofiles" version = "22.1.0" @@ -5,6 +7,10 @@ description = "File support for asyncio." category = "main" optional = false python-versions = ">=3.7,<4.0" +files = [ + {file = "aiofiles-22.1.0-py3-none-any.whl", hash = "sha256:1142fa8e80dbae46bb6339573ad4c8c0841358f79c6eb50a493dceca14621bad"}, + {file = "aiofiles-22.1.0.tar.gz", hash = "sha256:9107f1ca0b2a5553987a94a3c9959fe5b491fdf731389aa5b7b1bd0733e32de6"}, +] [[package]] name = "anyio" @@ -13,16 +19,39 @@ description = "High level compatibility layer for multiple asynchronous event lo category = "main" optional = false python-versions = ">=3.6.2" +files = [ + {file = "anyio-3.6.2-py3-none-any.whl", hash = "sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3"}, + {file = "anyio-3.6.2.tar.gz", hash = "sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421"}, +] [package.dependencies] idna = ">=2.8" sniffio = ">=1.1" [package.extras] -doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] -test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] +doc = ["packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["contextlib2", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (<0.15)", "uvloop (>=0.15)"] trio = ["trio (>=0.16,<0.22)"] +[[package]] +name = "attrs" +version = "22.2.0" +description = "Classes Without Boilerplate" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, + {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] +tests = ["attrs[tests-no-zope]", "zope.interface"] +tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] + [[package]] name = "certifi" version = "2022.12.7" @@ -30,6 +59,37 @@ description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" +files = [ + {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, + {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.1.0" +description = "Backport of PEP 654 (exception groups)" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, + {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"}, +] + +[package.extras] +test = ["pytest (>=6)"] [[package]] name = "h11" @@ -38,6 +98,10 @@ description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] [[package]] name = "httpcore" @@ -46,6 +110,10 @@ description = "A minimal low-level HTTP client." category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "httpcore-0.16.3-py3-none-any.whl", hash = "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"}, + {file = "httpcore-0.16.3.tar.gz", hash = "sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb"}, +] [package.dependencies] anyio = ">=3.0,<5.0" @@ -64,11 +132,15 @@ description = "The next generation HTTP client." category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "httpx-0.23.3-py3-none-any.whl", hash = "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"}, + {file = "httpx-0.23.3.tar.gz", hash = "sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9"}, +] [package.dependencies] certifi = "*" httpcore = ">=0.15.0,<0.17.0" -rfc3986 = { version = ">=1.3,<2", extras = ["idna2008"] } +rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} sniffio = "*" [package.extras] @@ -84,6 +156,34 @@ description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "packaging" +version = "23.0" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, + {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, +] [[package]] name = "pillow" @@ -92,11 +192,183 @@ description = "Python Imaging Library (Fork)" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "Pillow-9.4.0-1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b4b4e9dda4f4e4c4e6896f93e84a8f0bcca3b059de9ddf67dac3c334b1195e1"}, + {file = "Pillow-9.4.0-1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:fb5c1ad6bad98c57482236a21bf985ab0ef42bd51f7ad4e4538e89a997624e12"}, + {file = "Pillow-9.4.0-1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:f0caf4a5dcf610d96c3bd32932bfac8aee61c96e60481c2a0ea58da435e25acd"}, + {file = "Pillow-9.4.0-1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:3f4cc516e0b264c8d4ccd6b6cbc69a07c6d582d8337df79be1e15a5056b258c9"}, + {file = "Pillow-9.4.0-1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b8c2f6eb0df979ee99433d8b3f6d193d9590f735cf12274c108bd954e30ca858"}, + {file = "Pillow-9.4.0-1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b70756ec9417c34e097f987b4d8c510975216ad26ba6e57ccb53bc758f490dab"}, + {file = "Pillow-9.4.0-1-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:43521ce2c4b865d385e78579a082b6ad1166ebed2b1a2293c3be1d68dd7ca3b9"}, + {file = "Pillow-9.4.0-2-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:9d9a62576b68cd90f7075876f4e8444487db5eeea0e4df3ba298ee38a8d067b0"}, + {file = "Pillow-9.4.0-2-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:87708d78a14d56a990fbf4f9cb350b7d89ee8988705e58e39bdf4d82c149210f"}, + {file = "Pillow-9.4.0-2-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:8a2b5874d17e72dfb80d917213abd55d7e1ed2479f38f001f264f7ce7bae757c"}, + {file = "Pillow-9.4.0-2-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:83125753a60cfc8c412de5896d10a0a405e0bd88d0470ad82e0869ddf0cb3848"}, + {file = "Pillow-9.4.0-2-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9e5f94742033898bfe84c93c831a6f552bb629448d4072dd312306bab3bd96f1"}, + {file = "Pillow-9.4.0-2-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:013016af6b3a12a2f40b704677f8b51f72cb007dac785a9933d5c86a72a7fe33"}, + {file = "Pillow-9.4.0-2-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:99d92d148dd03fd19d16175b6d355cc1b01faf80dae93c6c3eb4163709edc0a9"}, + {file = "Pillow-9.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:2968c58feca624bb6c8502f9564dd187d0e1389964898f5e9e1fbc8533169157"}, + {file = "Pillow-9.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c5c1362c14aee73f50143d74389b2c158707b4abce2cb055b7ad37ce60738d47"}, + {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd752c5ff1b4a870b7661234694f24b1d2b9076b8bf337321a814c612665f343"}, + {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3049a10261d7f2b6514d35bbb7a4dfc3ece4c4de14ef5876c4b7a23a0e566d"}, + {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16a8df99701f9095bea8a6c4b3197da105df6f74e6176c5b410bc2df2fd29a57"}, + {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:94cdff45173b1919350601f82d61365e792895e3c3a3443cf99819e6fbf717a5"}, + {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ed3e4b4e1e6de75fdc16d3259098de7c6571b1a6cc863b1a49e7d3d53e036070"}, + {file = "Pillow-9.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5b2f8a31bd43e0f18172d8ac82347c8f37ef3e0b414431157718aa234991b28"}, + {file = "Pillow-9.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:09b89ddc95c248ee788328528e6a2996e09eaccddeeb82a5356e92645733be35"}, + {file = "Pillow-9.4.0-cp310-cp310-win32.whl", hash = "sha256:f09598b416ba39a8f489c124447b007fe865f786a89dbfa48bb5cf395693132a"}, + {file = "Pillow-9.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:f6e78171be3fb7941f9910ea15b4b14ec27725865a73c15277bc39f5ca4f8391"}, + {file = "Pillow-9.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:3fa1284762aacca6dc97474ee9c16f83990b8eeb6697f2ba17140d54b453e133"}, + {file = "Pillow-9.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eaef5d2de3c7e9b21f1e762f289d17b726c2239a42b11e25446abf82b26ac132"}, + {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4dfdae195335abb4e89cc9762b2edc524f3c6e80d647a9a81bf81e17e3fb6f0"}, + {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6abfb51a82e919e3933eb137e17c4ae9c0475a25508ea88993bb59faf82f3b35"}, + {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451f10ef963918e65b8869e17d67db5e2f4ab40e716ee6ce7129b0cde2876eab"}, + {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:6663977496d616b618b6cfa43ec86e479ee62b942e1da76a2c3daa1c75933ef4"}, + {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:60e7da3a3ad1812c128750fc1bc14a7ceeb8d29f77e0a2356a8fb2aa8925287d"}, + {file = "Pillow-9.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:19005a8e58b7c1796bc0167862b1f54a64d3b44ee5d48152b06bb861458bc0f8"}, + {file = "Pillow-9.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f715c32e774a60a337b2bb8ad9839b4abf75b267a0f18806f6f4f5f1688c4b5a"}, + {file = "Pillow-9.4.0-cp311-cp311-win32.whl", hash = "sha256:b222090c455d6d1a64e6b7bb5f4035c4dff479e22455c9eaa1bdd4c75b52c80c"}, + {file = "Pillow-9.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:ba6612b6548220ff5e9df85261bddc811a057b0b465a1226b39bfb8550616aee"}, + {file = "Pillow-9.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5f532a2ad4d174eb73494e7397988e22bf427f91acc8e6ebf5bb10597b49c493"}, + {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dd5a9c3091a0f414a963d427f920368e2b6a4c2f7527fdd82cde8ef0bc7a327"}, + {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef21af928e807f10bf4141cad4746eee692a0dd3ff56cfb25fce076ec3cc8abe"}, + {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:847b114580c5cc9ebaf216dd8c8dbc6b00a3b7ab0131e173d7120e6deade1f57"}, + {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:653d7fb2df65efefbcbf81ef5fe5e5be931f1ee4332c2893ca638c9b11a409c4"}, + {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:46f39cab8bbf4a384ba7cb0bc8bae7b7062b6a11cfac1ca4bc144dea90d4a9f5"}, + {file = "Pillow-9.4.0-cp37-cp37m-win32.whl", hash = "sha256:7ac7594397698f77bce84382929747130765f66406dc2cd8b4ab4da68ade4c6e"}, + {file = "Pillow-9.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:46c259e87199041583658457372a183636ae8cd56dbf3f0755e0f376a7f9d0e6"}, + {file = "Pillow-9.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:0e51f608da093e5d9038c592b5b575cadc12fd748af1479b5e858045fff955a9"}, + {file = "Pillow-9.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:765cb54c0b8724a7c12c55146ae4647e0274a839fb6de7bcba841e04298e1011"}, + {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:519e14e2c49fcf7616d6d2cfc5c70adae95682ae20f0395e9280db85e8d6c4df"}, + {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d197df5489004db87d90b918033edbeee0bd6df3848a204bca3ff0a903bef837"}, + {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0845adc64fe9886db00f5ab68c4a8cd933ab749a87747555cec1c95acea64b0b"}, + {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:e1339790c083c5a4de48f688b4841f18df839eb3c9584a770cbd818b33e26d5d"}, + {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:a96e6e23f2b79433390273eaf8cc94fec9c6370842e577ab10dabdcc7ea0a66b"}, + {file = "Pillow-9.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7cfc287da09f9d2a7ec146ee4d72d6ea1342e770d975e49a8621bf54eaa8f30f"}, + {file = "Pillow-9.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d7081c084ceb58278dd3cf81f836bc818978c0ccc770cbbb202125ddabec6628"}, + {file = "Pillow-9.4.0-cp38-cp38-win32.whl", hash = "sha256:df41112ccce5d47770a0c13651479fbcd8793f34232a2dd9faeccb75eb5d0d0d"}, + {file = "Pillow-9.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7a21222644ab69ddd9967cfe6f2bb420b460dae4289c9d40ff9a4896e7c35c9a"}, + {file = "Pillow-9.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0f3269304c1a7ce82f1759c12ce731ef9b6e95b6df829dccd9fe42912cc48569"}, + {file = "Pillow-9.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cb362e3b0976dc994857391b776ddaa8c13c28a16f80ac6522c23d5257156bed"}, + {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2e0f87144fcbbe54297cae708c5e7f9da21a4646523456b00cc956bd4c65815"}, + {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28676836c7796805914b76b1837a40f76827ee0d5398f72f7dcc634bae7c6264"}, + {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0884ba7b515163a1a05440a138adeb722b8a6ae2c2b33aea93ea3118dd3a899e"}, + {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:53dcb50fbdc3fb2c55431a9b30caeb2f7027fcd2aeb501459464f0214200a503"}, + {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:e8c5cf126889a4de385c02a2c3d3aba4b00f70234bfddae82a5eaa3ee6d5e3e6"}, + {file = "Pillow-9.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6c6b1389ed66cdd174d040105123a5a1bc91d0aa7059c7261d20e583b6d8cbd2"}, + {file = "Pillow-9.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0dd4c681b82214b36273c18ca7ee87065a50e013112eea7d78c7a1b89a739153"}, + {file = "Pillow-9.4.0-cp39-cp39-win32.whl", hash = "sha256:6d9dfb9959a3b0039ee06c1a1a90dc23bac3b430842dcb97908ddde05870601c"}, + {file = "Pillow-9.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:54614444887e0d3043557d9dbc697dbb16cfb5a35d672b7a0fcc1ed0cf1c600b"}, + {file = "Pillow-9.4.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b9b752ab91e78234941e44abdecc07f1f0d8f51fb62941d32995b8161f68cfe5"}, + {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3b56206244dc8711f7e8b7d6cad4663917cd5b2d950799425076681e8766286"}, + {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aabdab8ec1e7ca7f1434d042bf8b1e92056245fb179790dc97ed040361f16bfd"}, + {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db74f5562c09953b2c5f8ec4b7dfd3f5421f31811e97d1dbc0a7c93d6e3a24df"}, + {file = "Pillow-9.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e9d7747847c53a16a729b6ee5e737cf170f7a16611c143d95aa60a109a59c336"}, + {file = "Pillow-9.4.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b52ff4f4e002f828ea6483faf4c4e8deea8d743cf801b74910243c58acc6eda3"}, + {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:575d8912dca808edd9acd6f7795199332696d3469665ef26163cd090fa1f8bfa"}, + {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c4ed2ff6760e98d262e0cc9c9a7f7b8a9f61aa4d47c58835cdaf7b0b8811bb"}, + {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e621b0246192d3b9cb1dc62c78cfa4c6f6d2ddc0ec207d43c0dedecb914f152a"}, + {file = "Pillow-9.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8f127e7b028900421cad64f51f75c051b628db17fb00e099eb148761eed598c9"}, + {file = "Pillow-9.4.0.tar.gz", hash = "sha256:a1c2d7780448eb93fbcc3789bf3916aa5720d942e37945f4056680317f1cd23e"}, +] [package.extras] docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"] tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +[[package]] +name = "pluggy" +version = "1.0.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pydantic" +version = "1.10.5" +description = "Data validation and settings management using python type hints" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-1.10.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5920824fe1e21cbb3e38cf0f3dd24857c8959801d1031ce1fac1d50857a03bfb"}, + {file = "pydantic-1.10.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3bb99cf9655b377db1a9e47fa4479e3330ea96f4123c6c8200e482704bf1eda2"}, + {file = "pydantic-1.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2185a3b3d98ab4506a3f6707569802d2d92c3a7ba3a9a35683a7709ea6c2aaa2"}, + {file = "pydantic-1.10.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f582cac9d11c227c652d3ce8ee223d94eb06f4228b52a8adaafa9fa62e73d5c9"}, + {file = "pydantic-1.10.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c9e5b778b6842f135902e2d82624008c6a79710207e28e86966cd136c621bfee"}, + {file = "pydantic-1.10.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72ef3783be8cbdef6bca034606a5de3862be6b72415dc5cb1fb8ddbac110049a"}, + {file = "pydantic-1.10.5-cp310-cp310-win_amd64.whl", hash = "sha256:45edea10b75d3da43cfda12f3792833a3fa70b6eee4db1ed6aed528cef17c74e"}, + {file = "pydantic-1.10.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:63200cd8af1af2c07964546b7bc8f217e8bda9d0a2ef0ee0c797b36353914984"}, + {file = "pydantic-1.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:305d0376c516b0dfa1dbefeae8c21042b57b496892d721905a6ec6b79494a66d"}, + {file = "pydantic-1.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fd326aff5d6c36f05735c7c9b3d5b0e933b4ca52ad0b6e4b38038d82703d35b"}, + {file = "pydantic-1.10.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6bb0452d7b8516178c969d305d9630a3c9b8cf16fcf4713261c9ebd465af0d73"}, + {file = "pydantic-1.10.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9a9d9155e2a9f38b2eb9374c88f02fd4d6851ae17b65ee786a87d032f87008f8"}, + {file = "pydantic-1.10.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f836444b4c5ece128b23ec36a446c9ab7f9b0f7981d0d27e13a7c366ee163f8a"}, + {file = "pydantic-1.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:8481dca324e1c7b715ce091a698b181054d22072e848b6fc7895cd86f79b4449"}, + {file = "pydantic-1.10.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:87f831e81ea0589cd18257f84386bf30154c5f4bed373b7b75e5cb0b5d53ea87"}, + {file = "pydantic-1.10.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ce1612e98c6326f10888df951a26ec1a577d8df49ddcaea87773bfbe23ba5cc"}, + {file = "pydantic-1.10.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58e41dd1e977531ac6073b11baac8c013f3cd8706a01d3dc74e86955be8b2c0c"}, + {file = "pydantic-1.10.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6a4b0aab29061262065bbdede617ef99cc5914d1bf0ddc8bcd8e3d7928d85bd6"}, + {file = "pydantic-1.10.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:36e44a4de37b8aecffa81c081dbfe42c4d2bf9f6dff34d03dce157ec65eb0f15"}, + {file = "pydantic-1.10.5-cp37-cp37m-win_amd64.whl", hash = "sha256:261f357f0aecda005934e413dfd7aa4077004a174dafe414a8325e6098a8e419"}, + {file = "pydantic-1.10.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b429f7c457aebb7fbe7cd69c418d1cd7c6fdc4d3c8697f45af78b8d5a7955760"}, + {file = "pydantic-1.10.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:663d2dd78596c5fa3eb996bc3f34b8c2a592648ad10008f98d1348be7ae212fb"}, + {file = "pydantic-1.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51782fd81f09edcf265823c3bf43ff36d00db246eca39ee765ef58dc8421a642"}, + {file = "pydantic-1.10.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c428c0f64a86661fb4873495c4fac430ec7a7cef2b8c1c28f3d1a7277f9ea5ab"}, + {file = "pydantic-1.10.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:76c930ad0746c70f0368c4596020b736ab65b473c1f9b3872310a835d852eb19"}, + {file = "pydantic-1.10.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3257bd714de9db2102b742570a56bf7978e90441193acac109b1f500290f5718"}, + {file = "pydantic-1.10.5-cp38-cp38-win_amd64.whl", hash = "sha256:f5bee6c523d13944a1fdc6f0525bc86dbbd94372f17b83fa6331aabacc8fd08e"}, + {file = "pydantic-1.10.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:532e97c35719f137ee5405bd3eeddc5c06eb91a032bc755a44e34a712420daf3"}, + {file = "pydantic-1.10.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ca9075ab3de9e48b75fa8ccb897c34ccc1519177ad8841d99f7fd74cf43be5bf"}, + {file = "pydantic-1.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd46a0e6296346c477e59a954da57beaf9c538da37b9df482e50f836e4a7d4bb"}, + {file = "pydantic-1.10.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3353072625ea2a9a6c81ad01b91e5c07fa70deb06368c71307529abf70d23325"}, + {file = "pydantic-1.10.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3f9d9b2be177c3cb6027cd67fbf323586417868c06c3c85d0d101703136e6b31"}, + {file = "pydantic-1.10.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b473d00ccd5c2061fd896ac127b7755baad233f8d996ea288af14ae09f8e0d1e"}, + {file = "pydantic-1.10.5-cp39-cp39-win_amd64.whl", hash = "sha256:5f3bc8f103b56a8c88021d481410874b1f13edf6e838da607dcb57ecff9b4594"}, + {file = "pydantic-1.10.5-py3-none-any.whl", hash = "sha256:7c5b94d598c90f2f46b3a983ffb46ab806a67099d118ae0da7ef21a2a4033b28"}, + {file = "pydantic-1.10.5.tar.gz", hash = "sha256:9e337ac83686645a46db0e825acceea8e02fca4062483f40e9ae178e8bd1103a"}, +] + +[package.dependencies] +typing-extensions = ">=4.2.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "pytest" +version = "7.2.1" +description = "pytest: simple powerful testing with Python" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.2.1-py3-none-any.whl", hash = "sha256:c7c6ca206e93355074ae32f7403e8ea12163b1163c976fee7d4d84027c162be5"}, + {file = "pytest-7.2.1.tar.gz", hash = "sha256:d45e0952f3727241918b8fd0f376f5ff6b301cc0777c6f9a556935c92d8a7d42"}, +] + +[package.dependencies] +attrs = ">=19.2.0" +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] + [[package]] name = "rfc3986" version = "1.5.0" @@ -104,9 +376,13 @@ description = "Validating URI References per RFC 3986" category = "main" optional = false python-versions = "*" +files = [ + {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, + {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, +] [package.dependencies] -idna = { version = "*", optional = true, markers = "extra == \"idna2008\"" } +idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} [package.extras] idna2008 = ["idna"] @@ -118,20 +394,48 @@ description = "Sniff out which async library your code is running under" category = "main" optional = false python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tomlkit" +version = "0.11.6" +description = "Style preserving TOML library" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "tomlkit-0.11.6-py3-none-any.whl", hash = "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b"}, + {file = "tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"}, +] + +[[package]] +name = "typing-extensions" +version = "4.5.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, + {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, +] [metadata] -lock-version = "1.1" +lock-version = "2.0" python-versions = "^3.8" -content-hash = "9c96663101daae49ee8fadcb9f485d78cd7c5cd42955f03f8768da7265bb91e4" - -[metadata.files] -aiofiles = [] -anyio = [] -certifi = [] -h11 = [] -httpcore = [] -httpx = [] -idna = [] -pillow = [] -rfc3986 = [] -sniffio = [] +content-hash = "5414ac88b345a10105dc93b406ecf759f44356157ee87f0fe44367daecf44fc5" diff --git a/pyproject.toml b/pyproject.toml index 9b9c582..c3d15fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,9 +10,14 @@ python = "^3.8" Pillow = "^9.4.0" httpx = "^0.23.3" aiofiles = "^22.1.0" +pydantic = "^1.10.5" +tomlkit = "^0.11.6" [tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] +pytest = "^7.2.1" + [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" From aa486ed08f56ae5943cc423d5a8c13ab0fae103d Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Sat, 4 Mar 2023 22:52:08 +0800 Subject: [PATCH 11/13] =?UTF-8?q?=F0=9F=9B=BB=20=E9=87=8D=E5=91=BD?= =?UTF-8?q?=E5=90=8Dtweaks.py=E4=B8=BA=E6=9B=B4=E8=A7=84=E8=8C=83=E7=9A=84?= =?UTF-8?q?utils.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/almanac/{tweaks.py => utils.py} | 46 +++++++++++++++++++---------- src/utils.py | 26 ++++++++++++++++ 2 files changed, 57 insertions(+), 15 deletions(-) rename src/almanac/{tweaks.py => utils.py} (58%) diff --git a/src/almanac/tweaks.py b/src/almanac/utils.py similarity index 58% rename from src/almanac/tweaks.py rename to src/almanac/utils.py index e924d80..70f39bb 100644 --- a/src/almanac/tweaks.py +++ b/src/almanac/utils.py @@ -1,10 +1,11 @@ import base64 import json -import os +import uuid import time +from pathlib import Path from io import BytesIO -jsondb_template = { +TEMPLATE = { "10001": { "time": "2021-06-04", "pos": "二八" @@ -19,15 +20,30 @@ def text_r90(t): return tmp -class jsondb: - def __init__(self, filepath): - if not os.path.exists(filepath): - with open(filepath, 'w', encoding="UTF-8") as f: - json.dump(jsondb_template, f, ensure_ascii=False, sort_keys=True, indent=4) - dbfile = open(filepath, "r", encoding="UTF-8") - self.db = json.loads(dbfile.read()) - self.path = filepath - dbfile.close() +class SimpleJsonDB: + def _load(self): + with open(self.path, 'r', encoding='utf8') as json_file: + self._database = json.load(json_file) + + def find(self, filters: dict): + for k, v in filters.items(): + for _ in self._database: + + + def __init__(self, db_path: Path): + if not isinstance(db_path, Path): + db_path = Path(db_path) + if not db_path.exists(): + with open(db_path, 'w', encoding="UTF-8") as f: + json.dump(TEMPLATE, f, ensure_ascii=False, sort_keys=True, indent=4) + self.path = db_path + self._database = [ + { + "_id": "uuid4-uuid4-uuid4-uuid4", + "uid": 10001, + "time": "2023-02-10" + } + ] def add_user(self, uid): uid = str(uid) @@ -50,13 +66,13 @@ def save(self): def user(self, uid): uid = str(uid) try: - return user_info(self.db[uid]) + return UserInfo(self.db[uid]) except KeyError: self.add_user(uid) - return user_info(self.db[uid]) + return UserInfo(self.db[uid]) -class user_info: +class UserInfo: def __init__(self, db): self.db = db self.time = db["time"] @@ -80,6 +96,6 @@ def get_time(): if __name__ == "__main__": - jdb = jsondb("t.json") + jdb = SimpleJsonDB("t.json") user = jdb.user(2632324507) print(user.db["time"] == get_time()) diff --git a/src/utils.py b/src/utils.py index 65534eb..0a358d6 100644 --- a/src/utils.py +++ b/src/utils.py @@ -7,6 +7,32 @@ logging.Formatter('[%(asctime)s %(name)s] %(levelname)s: %(message)s')) logger.addHandler(default_handler) + +class DictSpace: + def __parse_item(self, __obj, loo: bool = False): + if isinstance(__obj, dict): + return DictSpace(__obj, list_of_obj=loo) + if isinstance(__obj, list) and loo: + return self.__parse_list(__obj, loo=loo) + return __obj + + def __parse_list(self, __list: list, loo: bool = False): + return [self.__parse_item(item_, loo=loo) for item_ in __list] + + def __init__(self, __obj: dict, list_of_obj: bool = False): + for k, v in __obj.items(): + setattr(self, k, self.__parse_item(v, loo=list_of_obj)) + + def __repr__(self): + _keys = list(filter(lambda x: not x.startswith('__'), self.__dir__())) + if len(_keys) > 3: + _formatted = ' '.join(f'{k}: {getattr(self, k)}' for k in _keys[:3]) + ' ...' + else: + _formatted = ' '.join(f'{k}: {getattr(self, k)}' for k in _keys) + return f'' + + __all__ = [ 'logger', + 'DictSpace' ] From 8d43ffddc197edf0921f3282aab4c6275b5f91a2 Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Sat, 4 Mar 2023 22:53:04 +0800 Subject: [PATCH 12/13] =?UTF-8?q?=F0=9F=93=9D=20=E6=9B=B4=E6=96=B0README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index 3ffa420..a462e84 100644 --- a/README.md +++ b/README.md @@ -19,14 +19,6 @@ > >这是一个[HoshinoBot](https://github.com/Ice-Cirno/HoshinoBot)和[nonebot2](https://github.com/nonebot/nonebot2)的原神相关插件 -~~这个项目目前正在扩展,加入更多原神相关娱乐和信息查询功能,敬请期待~~ - -#### 因原作者弃坑/nonebot进入beta时代/米游社API变动/多维度地图等诸多原因导致难以在原有版本上进行修改,将于不久后* - -*停止对该版本功能的增加**并完全转向下一个版本;加群了解更多 [GI Bot Group](https://jq.qq.com/?_wv=1027&k=1faV2txy) - -讨论群[GI Bot Group](https://jq.qq.com/?_wv=1027&k=1faV2txy) - ## 简介 这个插件帮助群员在QQ群内进行诸如查询资源点位等功能。 From 3a3383bcdee519bb9c44dfb44831e04aa1364679 Mon Sep 17 00:00:00 2001 From: Wansn <2632324507@qq.com> Date: Sun, 5 Mar 2023 22:19:21 +0800 Subject: [PATCH 13/13] =?UTF-8?q?=E2=9C=A8=20=E4=B8=8B=E8=BD=BD=E5=99=A8&?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E7=B4=A2=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 下载器 * 重写DownloadItem * 自动校验url可用性 * 优化文件名获取逻辑 * 重写部分下载逻辑 * 添加重写本地文件参数 * 资源索引 * 实现AssetIndex和OnlineAssetIndex * OnlineAssetIndex支持多个url * 对多个AssetIndex url使用异步下载 --- src/asset_index.py | 42 ++++++++-------- src/downloader.py | 117 +++++++++++++++++++++++++++------------------ src/utils.py | 78 +++++++++++++++++++++++++++++- 3 files changed, 169 insertions(+), 68 deletions(-) diff --git a/src/asset_index.py b/src/asset_index.py index 84e2439..e307062 100644 --- a/src/asset_index.py +++ b/src/asset_index.py @@ -2,37 +2,39 @@ from enum import Enum from typing import Sequence, Union +import httpx from httpx import URL +from .utils import AssetIndex, OnlineAssetIndex, logger from .asset_manager import DownloadItem __all__ = ['BuiltinAssets'] -class BuiltinAssetBase(UserList): - type: str - description: str +class CharacterAndWeaponsIndex(OnlineAssetIndex): + def _convert_index(self) -> list: + _data = self.raw_index[0] + return [ + DownloadItem(url=res["icon"], dest=res_type, name=res["item_id"]) + for res_type in _data.keys() for res in _data[res_type] + ] + def __init__(self): + super().__init__( + name='Character&Weapon', description='AssetIndex of characters and weapons', + index_url='https://waf-api-takumi.mihoyo.com/common/map_user/ys_obc/v1/map/' + 'game_item?map_id=2&app_sn=ys_obc&lang=zh-cn' + ) -class BuiltinAssetGroup(BuiltinAssetBase): - def __init__(self, asset_type: str, description: str, urls: Sequence[Union[str, URL, DownloadItem]]): - self.type = asset_type - self.description = description - super().__init__(urls) - -class GameItems( - BuiltinAssetBase): # use https://waf-api-takumi.mihoyo.com/common/map_user/ys_obc/v1/map/game_item?map_id=2&app_sn=ys_obc&lang=zh-cn - def _fetch_index(self): - ... - - -class GameMaps( - BuiltinAssetBase): # use https://api-static.mihoyo.com/common/map_user/ys_obc/v1/map/info?map_id=2&app_sn=ys_obc&lang=zh-cn - def _get_map_index(self): - ... +class GameMaps(OnlineAssetIndex): # use https://api-static.mihoyo.com/common/map_user/ys_obc/v1/map/info?map_id=2&app_sn=ys_obc&lang=zh-cn + def __init__(self): + super().__init__( + name='Resource_Maps', description='background of map', + index_url=[] + ) class BuiltinAssets(Enum): - game_item_all = GameItems() + game_item_all = CharacterAndWeaponsIndex() map = GameMaps() diff --git a/src/downloader.py b/src/downloader.py index 97836a4..30e00a3 100644 --- a/src/downloader.py +++ b/src/downloader.py @@ -5,7 +5,7 @@ from logging import Logger from pathlib import Path from sys import stdout -from typing import List, Union +from typing import Iterable, List, Optional, Union, Set, Any import aiofiles import httpx @@ -13,19 +13,33 @@ from .utils import logger +__all__ = ['DownloadItem', 'Downloader', 'convert_url'] + + +def convert_url(url: Union[str, tuple, URL, httpx.URL]) -> Union['DownloadItem', None]: + if isinstance(url, tuple): + if len(url) < 1: + return None + if len(url) == 1: + return DownloadItem(url=url[0]) + if len(url) >= 2: + return DownloadItem(*url[:2]) + return DownloadItem(url=url) + class DownloadItem: - def __init__(self, url: Union[str, URL], dest: Union[str, Path, None] = None, **kwargs): + def __init__(self, url: Union[str, URL], dest: Optional[Union[str, Path, None]] = None, + overwrite: Optional[bool] = True, name: Optional[Union[Any, None]] = None): if isinstance(url, str): url = URL(url=url) if isinstance(dest, str): dest = Path(dest) + assert self.validate() self.url: URL = url + self.name = name if isinstance(name, str) else str(name) self.trace_id = uuid.uuid4() self.dest: Union[Path, None] = dest - if kwargs: - for k, v in kwargs.values(): - setattr(self, k, v) + self.overwrite = overwrite def validate(self): if self.url.scheme in ['http', 'https']: @@ -47,24 +61,21 @@ def _clear_prev_line(): @staticmethod def _guess_if_file(__item: DownloadItem) -> bool: if '.' in __item.url.path: - return True + if len(__item.url.path.split('.')) >= 2: + return True return False @staticmethod def _get_filename(__item: DownloadItem): + if __item.name: + if any(len(_item_name) == 0 for _item_name in __item.name.split('.')): + _filename = '.'.join([*__item.name.split('.')[:-1], __item.url.path.split('/')[-1].split('.')[-1]]) + if __item.name.startswith('.'): + return f'.{_filename}' + return _filename + return __item.name return __item.url.path.split('/')[-1] - @staticmethod - def _convert_url(url: Union[str, tuple, URL, httpx.URL]) -> Union[DownloadItem, None]: - if isinstance(url, tuple): - if len(url) < 1: - return None - if len(url) == 1: - return DownloadItem(url=url[0]) - if len(url) >= 2: - return DownloadItem(*url[:2]) - return DownloadItem(url=url) - def _get_dest_folder(self, dest: Union[str, Path]): if isinstance(dest, str): dest = Path(dest) @@ -89,7 +100,7 @@ def _update_term_progress(self, filename: str): def _progress_upd(self): self.finish_count += 1 - def _download(self, dl_item: DownloadItem): + def _download(self, dl_item: DownloadItem) -> Union[httpx.Response, None]: with httpx.Client(follow_redirects=True) as client_: _filename = self._get_filename(dl_item) _resp = client_.get(dl_item.url) @@ -97,25 +108,29 @@ def _download(self, dl_item: DownloadItem): self._progress_upd() self._update_term_progress(_filename) if _resp.status_code != 200: - return False + return None dest = self._get_dest_folder(dl_item.dest) if dl_item is not None else self.dest_path + if dest.exists() and not self.overwrite_dest: + return _resp with open(dest / _filename, 'rb') as file_: file_.write(_resp.read()) - return True + return _resp - async def _async_download(self, dl_item: DownloadItem): + async def _async_download(self, dl_item: DownloadItem) -> Union[httpx.Response, None]: async with httpx.AsyncClient(follow_redirects=True) as client_: _filename = self._get_filename(dl_item) - resp_ = await client_.get(dl_item.url) + _resp = await client_.get(dl_item.url) with self.lock: self._progress_upd() self._update_term_progress(_filename) - if resp_.status_code != 200: - return False + if _resp.status_code != 200: + return None dest = self._get_dest_folder(dl_item.dest) if dl_item is not None else self.dest_path + if dest.exists() and not self.overwrite_dest: + return _resp with aiofiles.open(dest / _filename, 'rb') as file_: - await file_.write(resp_.read()) - return True + await file_.write(_resp.read()) + return _resp @property def len(self): @@ -131,40 +146,48 @@ def multi_download(self, max_connections: int = 5): # 多线程下载 max_conn result_state = [r.done() for r in _result] success_count = result_state.count(True) if not all(result_state): - self.logger.warning(f'下载完毕。| 成功: {success_count} 失败: {len(result_state) - success_count}') + self.logger.warning(f'[多线程]下载完毕。| 成功: {success_count} 失败: {len(result_state) - success_count}') return False - self.logger.info(f'下载完毕。已完成 {success_count} 个下载任务。') + self.logger.info(f'[多线程]下载完毕。已完成 {success_count} 个下载任务。') return True def async_multi_download(self, max_connections: int = 5): # 异步下载 - _tasks = [] - for item_ in self.task_list: - _tasks.append(asyncio.create_task(self._async_download(item_))) - chunks = self._get_connection_slice(_tasks, max_connections) - for chunk in chunks: - _ = asyncio.gather(*chunk) - - def __init__(self, file_list: List[Union[str, tuple, URL, DownloadItem]], dest: Union[str, Path] = '', + _tasks = [asyncio.create_task(self._async_download(item_)) for item_ in self.task_list] + _chunks = self._get_connection_slice(_tasks, max_connections) + _results = [] + for chunk in _chunks: + _results.append(await asyncio.gather(*chunk, return_exceptions=True)) + result_state = [r is not None for r in _results] + success_count = result_state.count(True) + if not all(result_state): + self.logger.warning(f'[异步]下载完毕。| 成功: {success_count} 失败: {len(result_state) - success_count}') + return False + self.logger.info(f'[异步]下载完毕。已完成 {success_count} 个下载任务。') + return True + + def __init__(self, name: Optional[str] = 'Downloader', dest: Union[str, Path] = '', progress_fmt: str = '{filename}|{bar}', progress_char: str = '■', bar_width: int = 10, - overwrite_dest: bool = False, __logger: Logger = logger): + overwrite_dest: bool = False, __logger: Logger = logger, *url: Union[str, tuple, URL, DownloadItem]): + if not isinstance(dest, Path): + dest = Path(dest) + self.name = name self.cache = {} - self.task_list: List[DownloadItem] = [] self.dest_path = dest + self.overwrite_dest = overwrite_dest + self.task_list: Set[DownloadItem] = set() + self.bar_width = bar_width self.progress_fmt = progress_fmt self.progress_char = progress_char self.finish_count = 0 + self.logger: Logger = __logger self.lock = threading.Lock() - for file in file_list: - _item = self._convert_url(file) - if not _item.validate(): - continue - self.task_list.append(_item) + self.task_list.update(convert_url(url_) for url_ in url if not isinstance(url_, DownloadItem)) def __iadd__(self, other): - if not isinstance(other, (str, URL, httpx.URL)): - return - _item = DownloadItem(url=other) - self.task_list.append(_item) + if isinstance(other, Iterable): + self.task_list.update(convert_url(url) for url in other) + if isinstance(other, (str, URL, httpx.URL)): + self.task_list.add(DownloadItem(url=other)) diff --git a/src/utils.py b/src/utils.py index 0a358d6..a514c74 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,5 +1,14 @@ +import asyncio import logging import sys +from abc import ABC +from pathlib import Path +from collections import UserList +from typing import List, Sequence, Tuple, Union, Optional + +import httpx +from httpx import URL +from .downloader import convert_url, DownloadItem logger: logging.Logger = logging.getLogger('GI Bot') default_handler = logging.StreamHandler(sys.stdout) @@ -32,7 +41,74 @@ def __repr__(self): return f'' +class AssetIndexBase(UserList): + name: str + description: str + + +class AssetIndex(AssetIndexBase): + def __init__(self, name: Optional[str] = '', description: Optional[str] = '', + *url: Union[str, URL, DownloadItem, Tuple[Union[str, URL, DownloadItem], Union[str, Path]]]): + self.name = name + self.description = description + if not all(isinstance(u_, DownloadItem) for u_ in url): + url = [convert_url(u) for u in url if not isinstance(u, DownloadItem)] + super().__init__(url) + + +class OnlineAssetIndex(AssetIndexBase): + def __init__(self, name: Optional[str] = '', description: Optional[str] = '', + index_url: Union[str, URL, Sequence[Union[str, URL]], None] = None): + self.name = name + self.description = description + _urls = index_url if not isinstance(index_url, (str, URL)) else [index_url] + self.index_url = [ + url if isinstance(index_url, URL) else URL(url) for url in _urls + ] + if not index_url: + super().__init__() + else: + super().__init__(self._convert_index()) + + @property + def raw_index(self) -> List[httpx.Response]: + """ + fetch data from `index_url` + :return: json of response or empty dict + """ + if len(set(url.host for url in self.index_url)): # the same host + _base_url = self.index_url[0] + async with httpx.AsyncClient(follow_redirects=True, + base_url=f'{_base_url.scheme}://{_base_url.host}') as client_: + async def fetch_index(url_path: str, __pos=0) -> httpx.Response: + if len(self.index_url) == 1: + logger.info(f"获取资源索引中: {self.name} ...") + else: + logger.info(f"获取资源索引中: {self.name}[{pos + 1}/{len(self.index_url)}] ...") + return await client_.get(url_path) + + tasks = [fetch_index(url, pos) for pos, url in enumerate(self.index_url)] + return list(await asyncio.gather(*tasks, return_exceptions=True)) + + _result = [] + for pos, url_ in enumerate(self.index_url): + if len(self.index_url) == 1: + logger.info(f"获取资源索引中: {self.name} ...") + else: + logger.info(f"获取资源索引中: {self.name}[{pos + 1}/{len(self.index_url)}] ...") + _resp = httpx.get(url_) + if _resp.status_code != 200: + continue + _result.append(_resp) + return _result + + def _convert_index(self) -> list: + return list(*r for r in self.raw_index) + + __all__ = [ 'logger', - 'DictSpace' + 'DictSpace', + 'AssetIndex', + 'OnlineAssetIndex' ]