Skip to content

Commit c1f4ef5

Browse files
committed
new python project
0 parents  commit c1f4ef5

25 files changed

+624
-0
lines changed

LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2018 The Python Packaging Authority
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Markdown-img使用指南
2+
3+
## 用途
4+
5+
本程序用于扫描工作目录下的markdown文件,查找其中的本地图片并自动上传到`sm.ms`图床,并生成一个使用网络图片替换本地图片的markdown副本,存放于`当前工作目录/markdown_image`目录下。
6+
7+
通过以上方式实现自动批量markdown图片处理工作,以方便之后把markdown内容在网络传播。
8+
9+
## 注意事项
10+
11+
- 本程序不会改变原始markdown文件,请放心使用。
12+
- 对于已经生成副本的原始文件,本程序不会再次处理,如果需要重新生成副本,请手动删除相应的已生成副本。
13+
- 本程序依赖于`sm.ms`图床,请自行注册账号并生成token。
14+
- 因为`sm.ms`图床接口有调用限制,如果出现图片上传出错的情况,可能是上传频繁导致,请等待1分钟以上时间后重新使用本程序。
15+
- 目前本程序只支持windows。
16+
- `sm.ms`国内访问不算友好,生成的markdown拷贝立即在网络上发布可能会显示防盗链等图片挂掉的情况,那是因为国内CDN比较慢,等一段时间就好了。
17+
18+
## 安装
19+
20+
```shell
21+
pip install markdown-img-icexmoon
22+
```
23+
24+
## 更新
25+
26+
```shell
27+
pip install --upgrade markdown-img-icexmoon
28+
```
29+
30+
## 使用方式
31+
32+
1. 使用CMD定位到将要处理的markdown文件目录。
33+
2. 执行`python -m markdown_img`
34+
3. 第一次运行程序会提示你输入图床token。
35+
4. 输入后再次执行步骤2。
36+
5. 等待处理。
37+
6. 完毕后查看`工作目录/markdown_img`目录。
38+
39+
> - 图床token存储在程序所在目录的`smms_token.config`文件中,如果需要修改的可以自行修改,也可以删除该配置文件后重新运行程序输入。
40+
> - 稍后会丰富并完善程序的相关命令参数。
41+
42+
43+
44+

build/lib/markdown_img/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import os
2+
import sys
3+
part = __file__.rpartition('\\')
4+
packageDirPath = part[0]
5+
sys.path.append(packageDirPath)
6+
from main import Main
7+
mainProcess = Main()
8+
mainProcess.main()

build/lib/markdown_img/config.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import os
2+
from user_exception import UserException
3+
4+
5+
class Config():
6+
smmsTokenFile = ""
7+
8+
def __init__(self):
9+
pass
10+
11+
def getCurrentDirPath(self):
12+
part = __file__.rpartition('\\')
13+
return part[0]
14+
15+
def getCurrentWorkDirPath(self):
16+
return os.getcwd()
17+
18+
def getMarkdownImgDirPath(self):
19+
'''返回当前工作目录对应的markdown_img目录'''
20+
markdownImgDirPath = self.getCurrentWorkDirPath()+"\\markdown_img"
21+
if not os.path.exists(markdownImgDirPath):
22+
os.mkdir(markdownImgDirPath)
23+
return markdownImgDirPath
24+
25+
def getSmmsTokenFile(self):
26+
if Config.smmsTokenFile == "":
27+
Config.smmsTokenFile = self.getCurrentDirPath()+'\\smms_token.config'
28+
return Config.smmsTokenFile
29+
30+
def getSmmsToken(self):
31+
if not os.path.exists(self.getSmmsTokenFile()):
32+
raise UserException(UserException.CODE_NO_CONFIG)
33+
configFileOpen = open(file=self.getSmmsTokenFile(), mode='r')
34+
token = configFileOpen.readline()
35+
configFileOpen.close()
36+
if len(token) <= 4:
37+
raise UserException(UserException.CODE_NO_CONFIG)
38+
token = token[0:len(token)-1]
39+
return token
40+
41+
def writeSmmsToken(self, token: str):
42+
with open(file=self.getSmmsTokenFile(), mode='w') as configFileOpen:
43+
print(token, file=configFileOpen)
44+
45+
def getErrorLogFilePath(self):
46+
return self.getCurrentDirPath()+'\\error.log'
47+
48+
def writeErrorLog(self, msg: str):
49+
errorLogFilePath = self.getErrorLogFilePath()
50+
with open(file=errorLogFilePath, mode='a', encoding='UTF-8') as logOpen:
51+
print(msg, file=logOpen)

build/lib/markdown_img/main.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from config import Config
2+
import os
3+
from smms_img import SmmsImg
4+
from user_exception import UserException
5+
6+
7+
class Main():
8+
9+
def __init__(self):
10+
pass
11+
12+
def isMarkdownFile(self, fileName: str):
13+
filePart = fileName.rpartition('.')
14+
fileExt = filePart[-1]
15+
return fileExt == 'md'
16+
17+
def isOrigMdFile(self, fileName: str):
18+
'''判断是否为原始markdown文件'''
19+
if not self.isMarkdownFile(fileName):
20+
return False
21+
# 检查文件后缀是否为_image
22+
specialMark = "_image"
23+
filePart = fileName.rpartition('.')
24+
# 如果文件名长度过小,肯定是原始文件
25+
if len(filePart[0]) <= len(specialMark):
26+
return True
27+
# 后缀是否能完全匹配
28+
if filePart[0].endswith(specialMark):
29+
return False
30+
return True
31+
32+
def getCopyFileName(self, fileName: str):
33+
filePart = fileName.rpartition('.')
34+
fileExt = filePart[-1]
35+
newFileName = filePart[0]+'_image.'+fileExt
36+
return newFileName
37+
38+
def getCopyFilePath(self, fileName: str):
39+
copyFileName = self.getCopyFileName(fileName)
40+
SysConfig = Config()
41+
return SysConfig.getMarkdownImgDirPath()+'\\'+copyFileName
42+
43+
def findLocalImageFile(self, line: str, localImages: set):
44+
'''递归查找某段字符串中中括号包裹的内容是否为本地图片'''
45+
linePart = line.partition('(')
46+
if len(linePart[2]) > 0:
47+
secondPart = linePart[2].partition(')')
48+
content = secondPart[0]
49+
if len(content) > 0:
50+
# print(content)
51+
if content.endswith('.png') and os.path.exists(content):
52+
localImages.add(content)
53+
self.findLocalImageFile(content, localImages)
54+
55+
def dealMdFile(self, mdFile: str):
56+
imgDict = dict()
57+
localImages = set()
58+
# 逐行扫描,查找本地图片
59+
with open(file=mdFile, mode='r', encoding='UTF-8') as fopen:
60+
for line in fopen:
61+
# 去除行尾的换行
62+
subLine = line[0:len(line)-1]
63+
self.findLocalImageFile(subLine, localImages)
64+
# 上传本地图片,建立图片映射表
65+
imgServer = SmmsImg()
66+
imgServer.multiUploadImage(list(localImages), imgDict)
67+
# 替换本地图片
68+
# copyFileName = self.getCopyFileName(mdFile)
69+
copyFilePath = self.getCopyFilePath(mdFile)
70+
copyFileOpen = open(file=copyFilePath, mode='w', encoding='UTF-8')
71+
with open(file=mdFile, mode='r', encoding='UTF-8') as fwrite:
72+
for line in fwrite:
73+
for localImg, webImg in imgDict.items():
74+
line = line.replace(localImg, webImg)
75+
copyFileOpen.write(line)
76+
copyFileOpen.close()
77+
78+
def dealUserException(self, userExp: UserException):
79+
sysConfig = Config()
80+
if userExp.getErrorCode() == UserException.CODE_NO_CONFIG:
81+
token = input("缺少你的sm.ms访问令牌,请输入:")
82+
sysConfig.writeSmmsToken(token)
83+
print("访问令牌已保存,请重新运行程序")
84+
exit()
85+
elif userExp.getErrorCode() == UserException.CODE_UPLOAD_ERROR:
86+
print("上传图片到sm.ms失败,请检查日志文件", sysConfig.getErrorLogFilePath())
87+
exit()
88+
else:
89+
print("未定义错误,请联系开发者")
90+
exit()
91+
92+
def main(self):
93+
# 检索当前目录中的markdown文件
94+
for dir in os.listdir():
95+
# print(dir)
96+
if os.path.isfile(dir):
97+
if self.isOrigMdFile(dir):
98+
# 复制一份拷贝,如果有,则不覆盖
99+
# copyFileName = self.getCopyFileName(dir)
100+
copyFilePath = self.getCopyFilePath(dir)
101+
if not os.path.exists(copyFilePath):
102+
# 对拷贝进行处理
103+
try:
104+
self.dealMdFile(dir)
105+
except UserException as e:
106+
self.dealUserException(e)
107+
print("已成功处理markdown文件", dir)
108+
print("所有markdown文档已处理完毕")
109+
exit()

build/lib/markdown_img/smms_img.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from config import Config
2+
from user_exception import UserException
3+
import requests
4+
5+
6+
class SmmsImg():
7+
def __init__(self):
8+
self.sysConfig = Config()
9+
pass
10+
11+
def uploadToSmms(self, path: str) -> str:
12+
'''上传本地图片到smms,并返回网络图片地址'''
13+
token = self.sysConfig.getSmmsToken()
14+
headers = {'Authorization': token}
15+
files = {'smfile': open(path, 'rb')}
16+
url = 'https://sm.ms/api/v2/upload'
17+
res = requests.post(url, files=files, headers=headers).json()
18+
if res['success']:
19+
return res['data']['url']
20+
elif res['code'] == 'image_repeated':
21+
return res['images']
22+
else:
23+
pass
24+
# logOpen = open(file='upload.log', mode='a')
25+
# print(res, file=logOpen)
26+
# logOpen.close()
27+
self.sysConfig.writeErrorLog(str(res))
28+
return False
29+
30+
def multiUploadImage(self, images: list, results: dict):
31+
'''批量上传图片'''
32+
if len(images) <= 10:
33+
for localImg in images:
34+
webImage = self.uploadToSmms(localImg)
35+
if webImage == False:
36+
# print("文件上传出错")
37+
# exit()
38+
raise UserException(
39+
UserException.CODE_UPLOAD_ERROR, "文件上传出错")
40+
else:
41+
results[localImg] = webImage
42+
else:
43+
self.multiUploadImage(images[0:10], results)
44+
self.multiUploadImage(images[10:len(images)], results)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class UserException (Exception):
2+
# 缺少配置文件
3+
CODE_NO_CONFIG = 1
4+
CODE_UPLOAD_ERROR = 2
5+
6+
def __init__(self, errorCode: int, errorMsg: str = ""):
7+
self.errorCode = errorCode
8+
self.errorMsg = errorMsg
9+
10+
def getErrorCode(self):
11+
return self.errorCode
12+
13+
def getErrorMsg(self):
14+
return self.errorMsg
6.04 KB
Binary file not shown.
7.06 KB
Binary file not shown.

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[build-system]
2+
requires = [
3+
"setuptools>=42",
4+
"wheel"
5+
]
6+
build-backend = "setuptools.build_meta"

0 commit comments

Comments
 (0)