Skip to content

Commit e28e540

Browse files
committed
add tencent cloud support
1 parent 219623f commit e28e540

File tree

8 files changed

+136
-18
lines changed

8 files changed

+136
-18
lines changed

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
2525
- 因为`sm.ms`图床接口有调用限制,如果出现图片上传出错的情况,可能是上传频繁导致,请等待1分钟以上时间后重新使用本程序。
2626

27+
- 已添加腾讯云对象存储作为图床,使用时需要输入相应的必须参数用于连接,具体参数获取可以阅读[**腾讯云对象存储的相关文档**](https://cloud.tencent.com/document/product/436/7751#.E6.9C.AF.E8.AF.AD.E4.BF.A1.E6.81.AF),此外还需要将对象存储服务设置为私有写公有读。
28+
2729
- 目前本程序只支持windows。
2830

2931
> 理论上支持所有能运行Python的平台,但目前并没有在其它平台测试过。
@@ -89,12 +91,13 @@ pip install --upgrade markdown-img-icexmoon
8991

9092
可以切换图床服务,以备某个图床不可用或者访问不稳定。
9193

92-
目前支持的图床有[**sm.ms**](https://sm.ms/)、阿里、[**如优**](https://img.rruu.net/)[**Vim-CN**](https://img.vim-cn.com/)[**遇见**](https://www.hualigs.cn/)
94+
目前支持的图床有[**sm.ms**](https://sm.ms/)、阿里、[**如优**](https://img.rruu.net/)[**Vim-CN**](https://img.vim-cn.com/)[**遇见**](https://www.hualigs.cn/)[**腾讯云对象存储(推广链接)**](https://curl.qcloud.com/empEScHz)
9395

9496
1. 执行`python -m markdown_img -i ali`
9597

9698
> - 具体的图床标识可以查看帮助文档。
9799
> - 需要访问令牌的图床服务切换后使用中会提示输入相应的访问令牌。
100+
> - 使用腾讯云OSS需要一些必要信息,具体请阅读注意事项。
98101
99102
### 更新图床访问令牌
100103

@@ -194,5 +197,8 @@ python -m markdown_img -m refresh
194197
### 0.2.3
195198

196199
- 修复了目录下有无图片的md文件会导致异常的问题。
200+
- 添加版本显示功能。
201+
202+
### 0.2.4
197203

198-
- 添加版本显示功能
204+
添加了腾讯云对象存储作为图床

setup.cfg

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = markdown-img-icexmoon
3-
version = 0.2.3
3+
version = 0.2.4
44
author = icexmoon
55
author_email = [email protected]
66
description = A program for find and upload images in markdown file and will replace them.
@@ -23,6 +23,7 @@ python_requires = >=3.6
2323
install_requires =
2424
requests
2525
futures
26+
cos-python-sdk-v5
2627

2728
[options.package_data]
2829
* = *.info

src/markdown_img/config.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,19 @@ class Config():
88
PARAM_RRUU_TOKEN = 'rruu_token'
99
PARAM_IMG_SERVICE = 'img_service'
1010
PARAM_YUJIAN_TOKEN = 'yujian_token'
11+
PARAM_QCLOUD_INFO = 'qcloud_info'
12+
QCLOUD_INFO_SECRET_KEY = 'secret_key'
13+
QCLOUD_INFO_SECRET_ID = 'secret_id'
14+
QCLOUD_INFO_REGION = 'region'
15+
QCLOUD_INFO_BUCKET = 'bucket'
16+
QCLOUD_INFO_DES_DIR = 'des_dir'
1117
IMG_SERVICE_YUJIAN = 'yujian'
1218
IMG_SERVICE_SMMS = 'smms'
1319
IMG_SERVICE_RRUU = 'rruu'
1420
IMG_SERVICE_ALI = 'ali'
1521
IMG_SERVICE_ALI2 = 'ali2'
1622
IMG_SERVICE_VIMCN = 'vimcn'
23+
IMG_SERVICE_QCLOUD = 'qcloud'
1724
smmsTokenFile = ""
1825
configFile = ""
1926
mainConfig = {}
@@ -97,6 +104,12 @@ def getSmmsToken(self):
97104
raise UserException(UserException.CODE_NO_SMMS_TOKEN)
98105
return token
99106

107+
def getQCloudInfo(self):
108+
info = self.getConfigParam(Config.PARAM_QCLOUD_INFO)
109+
if info == '':
110+
raise UserException(UserException.CODE_NO_QCLOUD_INFO)
111+
return info
112+
100113
def writeSmmsToken(self, token: str):
101114
with open(file=self.getSmmsTokenFile(), mode='w') as configFileOpen:
102115
print(token, file=configFileOpen)

src/markdown_img/help.info

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
rruu 如优图床。
1212
vimcn Vim-CN图床,访问速度偏慢。
1313
yujian 遇见图床。
14+
qcloud 腾讯云对象存储(需要提供必要连接信息,如果不知道如何获取,请阅读https://cloud.tencent.com/document/product/436/7751#.E6.9C.AF.E8.AF.AD.E4.BF.A1.E6.81.AF)
1415
-c --change_token 替换图床访问令牌
1516
rruu 如优图床。
1617
smms sm.ms图床。
1718
yujian 遇见图床。
19+
qcloud 腾讯云对象存储
1820
-s --scan 扫描当前目录的图片并生成网络图床索引

src/markdown_img/main.py

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,18 @@ def dealUserException(self, userExp: UserException):
152152
sysConfig.setConfigParam(Config.PARAM_YUJIAN_TOKEN, token)
153153
sysConfig.writeMainConfig()
154154
print("访问令牌已保存,请重新运行程序")
155+
elif userExp.getErrorCode() == UserException.CODE_NO_QCLOUD_INFO:
156+
qcloudInfo = {}
157+
print("缺少腾讯云OSS必须的连接信息,请按提示逐一输入:")
158+
qcloudInfo[Config.QCLOUD_INFO_SECRET_ID] = input("请输入secret_id:")
159+
qcloudInfo[Config.QCLOUD_INFO_SECRET_KEY] = input(
160+
"请输入secret_key:")
161+
qcloudInfo[Config.QCLOUD_INFO_REGION] = input("请输入region:")
162+
qcloudInfo[Config.QCLOUD_INFO_BUCKET] = input("请输入bucket:")
163+
qcloudInfo[Config.QCLOUD_INFO_DES_DIR] = input("请输入目标存储目录:")
164+
sysConfig.setConfigParam(Config.PARAM_QCLOUD_INFO, qcloudInfo)
165+
sysConfig.writeMainConfig()
166+
print("腾讯云OSS信息已保存,请重新运行程序")
155167
else:
156168
print("未定义错误,请联系开发者")
157169
exit()
@@ -223,7 +235,8 @@ def recoveryImgsInMarkdown(self, copyFilePath: 'copied markdown file path', orig
223235
return False
224236

225237
def changeImgService(self, selectedService):
226-
supportedService = {'smms', 'ali', 'rruu', 'vimcn', 'yujian', 'ali2'}
238+
supportedService = {'smms', 'ali', 'rruu',
239+
'vimcn', 'yujian', 'ali2', 'qcloud'}
227240
if selectedService not in supportedService:
228241
print('不支持的图床服务', selectedService)
229242
return False
@@ -243,6 +256,9 @@ def changeImgService(self, selectedService):
243256
elif selectedService == 'yujian':
244257
sysConfig.setConfigParam(
245258
Config.PARAM_IMG_SERVICE, Config.IMG_SERVICE_YUJIAN)
259+
elif selectedService == 'qcloud':
260+
sysConfig.setConfigParam(
261+
Config.PARAM_IMG_SERVICE, Config.IMG_SERVICE_QCLOUD)
246262
else:
247263
sysConfig.setConfigParam(
248264
Config.PARAM_IMG_SERVICE, Config.IMG_SERVICE_SMMS)
@@ -251,20 +267,30 @@ def changeImgService(self, selectedService):
251267
return True
252268

253269
def changeToken(self, imgService):
254-
tokenImgServices = {'rruu', 'smms', 'yujian'}
270+
tokenImgServices = {'rruu', 'smms', 'yujian','qcloud'}
255271
if imgService not in tokenImgServices:
256272
print('不是合法的图床', imgService)
257273
return False
258-
token = input("请输入新的访问令牌:")
259274
sysConfig = Config()
260-
if imgService == 'rruu':
261-
sysConfig.setConfigParam(Config.PARAM_RRUU_TOKEN, token)
262-
elif imgService == 'smms':
263-
sysConfig.setConfigParam(Config.PARAM_SMMS_TOKEN, token)
264-
elif imgService == 'yujian':
265-
sysConfig.setConfigParam(Config.PARAM_YUJIAN_TOKEN, token)
275+
if imgService != 'qcloud':
276+
token = input("请输入新的访问令牌:")
277+
if imgService == 'rruu':
278+
sysConfig.setConfigParam(Config.PARAM_RRUU_TOKEN, token)
279+
elif imgService == 'smms':
280+
sysConfig.setConfigParam(Config.PARAM_SMMS_TOKEN, token)
281+
elif imgService == 'yujian':
282+
sysConfig.setConfigParam(Config.PARAM_YUJIAN_TOKEN, token)
283+
else:
284+
pass
266285
else:
267-
pass
286+
qcloudInfo = {}
287+
qcloudInfo[Config.QCLOUD_INFO_SECRET_ID] = input("请输入新的secret_id:")
288+
qcloudInfo[Config.QCLOUD_INFO_SECRET_KEY] = input(
289+
"请输入新的secret_key:")
290+
qcloudInfo[Config.QCLOUD_INFO_REGION] = input("请输入新的region:")
291+
qcloudInfo[Config.QCLOUD_INFO_BUCKET] = input("请输入新的bucket:")
292+
qcloudInfo[Config.QCLOUD_INFO_DES_DIR] = input("请输入新的目标存储目录:")
293+
sysConfig.setConfigParam(Config.PARAM_QCLOUD_INFO, qcloudInfo)
268294
sysConfig.writeMainConfig()
269295
print("已成功更新访问令牌")
270296
return True

src/markdown_img/qcloud_client.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from qcloud_cos import CosConfig
2+
from qcloud_cos import CosS3Client
3+
import sys
4+
import logging
5+
import os
6+
import qcloud_cos
7+
8+
9+
class QcloudClient():
10+
def __init__(self, secretId, secretKey, region, bucket) -> None:
11+
# -*- coding=utf-8
12+
# appid 已在配置中移除,请在参数 Bucket 中带上 appid。Bucket 由 BucketName-APPID 组成
13+
# 1. 设置用户配置, 包括 secretId,secretKey 以及 Region
14+
logging.basicConfig(level=logging.ERROR, stream=sys.stdout)
15+
secret_id = secretId # 替换为用户的 secretId
16+
secret_key = secretKey # 替换为用户的 secretKey
17+
self.region = region # 替换为用户的 Region
18+
token = None # 使用临时密钥需要传入 Token,默认为空,可不填
19+
scheme = 'https' # 指定使用 http/https 协议来访问 COS,默认为 https,可不填
20+
config = CosConfig(Region=self.region, SecretId=secret_id,
21+
SecretKey=secret_key, Token=token, Scheme=scheme)
22+
# 2. 获取客户端对象
23+
self.client = CosS3Client(config)
24+
# 参照下文的描述。或者参照 Demo 程序,详见 https://github.com/tencentyun/cos-python-sdk-v5/blob/master/qcloud_cos/demo.py
25+
self.bucket = bucket
26+
27+
def upload(self, path: str, desPath: str):
28+
# 文件流简单上传(不支持超过5G的文件,推荐使用下方高级上传接口)
29+
# 强烈建议您以二进制模式(binary mode)打开文件,否则可能会导致错误
30+
fileName = os.path.basename(path)
31+
with open(path, 'rb') as fp:
32+
try:
33+
response = self.client.put_object(
34+
Bucket=self.bucket,
35+
Body=fp,
36+
Key="{}/{}".format(desPath, fileName),
37+
StorageClass='STANDARD',
38+
EnableMD5=False
39+
)
40+
except qcloud_cos.cos_exception.CosServiceError as e:
41+
raise e
42+
url = "https://{}.cos.{}.myqcloud.com/{}/{}".format(
43+
self.bucket, self.region, desPath, fileName)
44+
return url

src/markdown_img/smms_img.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,30 @@
33
import requests
44
import json
55
from concurrent import futures
6+
import qcloud_cos.cos_exception
7+
from .qcloud_client import QcloudClient
68

79

810
class SmmsImg():
911
def __init__(self):
1012
self.sysConfig = Config()
11-
pass
13+
self.qclient = None
14+
15+
def uploadToQCloud(self, path: str) -> str:
16+
'''上传到腾讯云'''
17+
clientInfo = self.sysConfig.getQCloudInfo()
18+
if self.qclient == None:
19+
# print(clientInfo)
20+
# exit()
21+
self.qclient = QcloudClient(clientInfo[Config.QCLOUD_INFO_SECRET_ID], clientInfo[Config.QCLOUD_INFO_SECRET_KEY],
22+
clientInfo[Config.QCLOUD_INFO_REGION], clientInfo[Config.QCLOUD_INFO_BUCKET])
23+
try:
24+
url = self.qclient.upload(
25+
path, clientInfo[Config.QCLOUD_INFO_DES_DIR])
26+
except qcloud_cos.cos_exception.CosServiceError as e:
27+
self.sysConfig.writeErrorLog(str(e))
28+
return False
29+
return url
1230

1331
def uploadToSmms(self, path: str) -> str:
1432
'''上传本地图片到smms,并返回网络图片地址'''
@@ -94,24 +112,29 @@ def multiUploadImage(self, images: list, results: dict):
94112
MAX_SAME_TIME_DEAL = 10
95113
if len(images) <= MAX_SAME_TIME_DEAL:
96114
maxThreadWorks = min(len(images), MAX_SAME_TIME_DEAL)
97-
#fixed 如果有没有图片的md文件,直接不做处理。
115+
# fixed 如果有没有图片的md文件,直接不做处理。
98116
if maxThreadWorks > 0:
99117
with futures.ThreadPoolExecutor(max_workers=maxThreadWorks) as futuresExecutor:
100118
futureMap = {}
101119
for localImg in images:
102-
future = futuresExecutor.submit(self.uploadOne,localImg)
120+
future = futuresExecutor.submit(
121+
self.uploadOne, localImg)
103122
futureMap[future] = localImg
104123
futureDone = futures.as_completed(futureMap)
105124
for future in futureDone:
106-
webImage = future.result()
125+
try:
126+
webImage = future.result()
127+
except UserException as e:
128+
raise e
107129
if webImage == False:
108130
raise UserException(
109131
UserException.CODE_UPLOAD_ERROR, "文件上传出错")
110132
else:
111133
results[futureMap[future]] = webImage
112134
else:
113135
self.multiUploadImage(images[0:MAX_SAME_TIME_DEAL], results)
114-
self.multiUploadImage(images[MAX_SAME_TIME_DEAL:len(images)], results)
136+
self.multiUploadImage(
137+
images[MAX_SAME_TIME_DEAL:len(images)], results)
115138

116139
def uploadOne(self, localImg):
117140
imgService = self.sysConfig.getConfigParam(
@@ -127,6 +150,8 @@ def uploadOne(self, localImg):
127150
webImage = self.uploadToVimCn(localImg)
128151
elif imgService == Config.IMG_SERVICE_YUJIAN:
129152
webImage = self.uploadToYujian(localImg)
153+
elif imgService == Config.IMG_SERVICE_QCLOUD:
154+
webImage = self.uploadToQCloud(localImg)
130155
else:
131156
webImage = self.uploadToSmms(localImg)
132157
return webImage

src/markdown_img/user_exception.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class UserException (Exception):
66
CODE_NO_SMMS_TOKEN = 4
77
CODE_NO_RRUU_TOKEN = 5
88
CODE_NO_YUJIAN_TOKEN = 6
9+
CODE_NO_QCLOUD_INFO = 7
910

1011
def __init__(self, errorCode: int, errorMsg: str = ""):
1112
self.errorCode = errorCode

0 commit comments

Comments
 (0)