download-flow-enmu 0.1.0__tar.gz → 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/PKG-INFO +1 -1
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/cli/download_cmd.py +30 -10
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/cli/main.py +1 -1
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/download_flow_enmu.egg-info/PKG-INFO +1 -1
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/pyproject.toml +1 -1
- download_flow_enmu-0.1.1/strategy/downloader/attchment.py +45 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/strategy/provider/ali_provider.py +1 -1
- download_flow_enmu-0.1.0/strategy/downloader/attchment.py +0 -41
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/README.md +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/cli/__init__.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/cli/root.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/config/__init__.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/config/loader.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/data/bill_profile.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/download_flow_enmu.egg-info/SOURCES.txt +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/download_flow_enmu.egg-info/dependency_links.txt +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/download_flow_enmu.egg-info/entry_points.txt +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/download_flow_enmu.egg-info/requires.txt +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/download_flow_enmu.egg-info/top_level.txt +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/factory/downloader_factory.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/factory/email_factory.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/factory/provider_factory.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/package/__init__.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/package/downfile.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/setup.cfg +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/strategy/downloader/__init__.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/strategy/downloader/provider.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/strategy/email/__init__.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/strategy/email/email_provider.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/strategy/email/gmail.py +0 -0
- {download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/strategy/provider/provider.py +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import typer
|
|
2
|
-
import json
|
|
3
2
|
import logging
|
|
3
|
+
import sys
|
|
4
|
+
import json
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from pydantic import TypeAdapter
|
|
6
7
|
from factory import downloader_factory, email_factory, provider_factory
|
|
@@ -12,22 +13,21 @@ from cli.root import app
|
|
|
12
13
|
def run(provider: str):
|
|
13
14
|
# 配置日志
|
|
14
15
|
logging.basicConfig(
|
|
15
|
-
level=logging.
|
|
16
|
-
format='%(levelname)s: %(message)s'
|
|
16
|
+
level=logging.ERROR, stream=sys.stderr, format="%(levelname)s: %(message)s"
|
|
17
17
|
)
|
|
18
|
-
|
|
19
18
|
config_path = Path.home() / ".flow" / "config.json"
|
|
20
|
-
|
|
19
|
+
|
|
21
20
|
logging.info(f"开始下载 {provider} 账单...")
|
|
22
21
|
logging.info(f"配置文件路径: {config_path}")
|
|
23
22
|
|
|
24
23
|
try:
|
|
25
24
|
# 使用 ConfigLoader 加载配置(支持环境变量替换)
|
|
26
|
-
from config.loader import load_config
|
|
25
|
+
from config.loader import load_config
|
|
26
|
+
|
|
27
27
|
config_json = load_config(config_path)
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
logging.info(f"配置加载成功")
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
adapter = TypeAdapter(PayConfig)
|
|
32
32
|
config_obj = adapter.validate_python(config_json[provider])
|
|
33
33
|
downloader = downloader_factory.creat_downloader(config_obj.download)
|
|
@@ -41,9 +41,22 @@ def run(provider: str):
|
|
|
41
41
|
provider_obj.bill = config_obj.profile
|
|
42
42
|
|
|
43
43
|
logging.info(f"开始执行下载...")
|
|
44
|
-
provider_obj.process_bills()
|
|
44
|
+
is_success = provider_obj.process_bills()
|
|
45
|
+
|
|
45
46
|
logging.info(f"✅ 下载完成!")
|
|
46
47
|
|
|
48
|
+
if is_success:
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
"status": "success",
|
|
52
|
+
"provider": provider,
|
|
53
|
+
}
|
|
54
|
+
else:
|
|
55
|
+
return {
|
|
56
|
+
"status": "fail",
|
|
57
|
+
"provider": provider,
|
|
58
|
+
}
|
|
59
|
+
|
|
47
60
|
except FileNotFoundError as e:
|
|
48
61
|
logging.error(f"配置文件未找到: {config_path}")
|
|
49
62
|
raise
|
|
@@ -61,4 +74,11 @@ def download(
|
|
|
61
74
|
str, typer.Option("--provider", "-p", help="config file")
|
|
62
75
|
] = "alipay",
|
|
63
76
|
):
|
|
64
|
-
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
result = run(provider)
|
|
80
|
+
typer.echo(json.dumps(result, ensure_ascii=False))
|
|
81
|
+
except Exception as e:
|
|
82
|
+
error_result = {"status": "error", "provider": provider, "message": str(e)}
|
|
83
|
+
typer.echo(json.dumps(error_result, ensure_ascii=False))
|
|
84
|
+
raise typer.Exit(code=1)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from imap_tools import MailBox, AND
|
|
5
|
+
|
|
6
|
+
from strategy.downloader.provider import Downloader
|
|
7
|
+
from typing import override
|
|
8
|
+
from data.bill_profile import BillProfile
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AttchmentDownloader(Downloader):
|
|
12
|
+
@override
|
|
13
|
+
def download(self, mail: MailBox, bill: BillProfile):
|
|
14
|
+
|
|
15
|
+
criteria = AND(
|
|
16
|
+
from_=bill.sender_email,
|
|
17
|
+
date=datetime.date.today(),
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
downloaded_count = 0
|
|
21
|
+
|
|
22
|
+
for msg in mail.fetch(criteria=criteria):
|
|
23
|
+
logging.info(f"找到邮件: {msg.subject}") # 添加这一行
|
|
24
|
+
|
|
25
|
+
if bill.search_subject not in msg.subject:
|
|
26
|
+
continue
|
|
27
|
+
for att in msg.attachments:
|
|
28
|
+
if not att.filename.lower().endswith(bill.file_suffix):
|
|
29
|
+
continue
|
|
30
|
+
bill.save_subdir.mkdir(parents=True, exist_ok=True)
|
|
31
|
+
filepath = (
|
|
32
|
+
bill.save_subdir / f"{datetime.date.today()}.{bill.file_suffix}"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
if bill.file_suffix in ["zip", "7z", "rar"]:
|
|
37
|
+
filepath.write_bytes(att.payload)
|
|
38
|
+
else:
|
|
39
|
+
content_str = att.payload.decode(bill.encoding)
|
|
40
|
+
filepath.write_text(content_str, encoding="utf-8")
|
|
41
|
+
downloaded_count += 1
|
|
42
|
+
except UnicodeDecodeError:
|
|
43
|
+
logging.error(" ✗ 转码失败")
|
|
44
|
+
continue
|
|
45
|
+
return downloaded_count > 0
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
import logging
|
|
3
|
-
|
|
4
|
-
from imap_tools import MailBox, AND
|
|
5
|
-
|
|
6
|
-
from strategy.downloader.provider import Downloader
|
|
7
|
-
from typing import override
|
|
8
|
-
from data.bill_profile import BillProfile
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class AttchmentDownloader(Downloader):
|
|
12
|
-
@override
|
|
13
|
-
def download(self, mail: MailBox, bill: BillProfile):
|
|
14
|
-
|
|
15
|
-
criteria = AND(
|
|
16
|
-
from_=bill.sender_email,
|
|
17
|
-
date=datetime.date.today(),
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
for msg in mail.fetch(criteria=criteria):
|
|
21
|
-
logging.info(f"找到邮件: {msg.subject}") # 添加这一行
|
|
22
|
-
|
|
23
|
-
if bill.search_subject not in msg.subject:
|
|
24
|
-
continue
|
|
25
|
-
for att in msg.attachments:
|
|
26
|
-
if att.filename.lower().endswith(bill.file_suffix):
|
|
27
|
-
bill.save_subdir.mkdir(parents=True, exist_ok=True)
|
|
28
|
-
filepath = (
|
|
29
|
-
bill.save_subdir / f"{datetime.date.today()}.{bill.file_suffix}"
|
|
30
|
-
) # 改这里:加扩展名
|
|
31
|
-
|
|
32
|
-
try:
|
|
33
|
-
if bill.file_suffix in ["zip", "7z", "rar"]:
|
|
34
|
-
filepath.write_bytes(att.payload)
|
|
35
|
-
else:
|
|
36
|
-
content_str = att.payload.decode(bill.encoding)
|
|
37
|
-
filepath.write_text(content_str, encoding="utf-8")
|
|
38
|
-
except UnicodeDecodeError:
|
|
39
|
-
logging.error(" ✗ 转码失败")
|
|
40
|
-
else:
|
|
41
|
-
logging.info(f"✗ 附件类型不匹配 (期望后缀: {bill.file_suffix})")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/download_flow_enmu.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/download_flow_enmu.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/download_flow_enmu.egg-info/requires.txt
RENAMED
|
File without changes
|
{download_flow_enmu-0.1.0 → download_flow_enmu-0.1.1}/download_flow_enmu.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|