git仓库当作博客图床

git仓库当作博客图床

网上找了一堆博客图床,但是都没有一个本地和云同步的工具,只有git仓库可以,但是手动截图,转换连接相当麻烦,于是自动化这些操作.

程序在这里

mark

mark

步骤如下

  1. 创建一个仓库,ssh连接,本地上能对这个仓库上传下载

  2. py监控这个本地文件夹,如果这个文件夹有文件变动,新建的文件后缀名为gif,png,jpg,那么自动上传到git

  3. 这里需要一个截图工具,能够自动输出截图到这个文件夹,sharexsnipast都支持,我使用snipast的.

    地址在这里

py代码

本人萌新,python学过两三天,所以代码风格和风范完全没有,编程思路完全没有,所以某位大大看到了之后可以改进下这个工具就好了.

需要三个python库

1
2
3
watchdog
ctypes
GitPython

完整的代码如下,python3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from watchdog.observers import Observer
from watchdog.events import *
import time
from ctypes import *
from git import Repo


class FileEventHandler(FileSystemEventHandler):
def __init__(self):
FileSystemEventHandler.__init__(self)
self.user32 = windll.user32
self.kernel32 = windll.kernel32
self.markdown_url_pre="![mark](https://gitee.com/layty/pic/raw/master/root/"
self.markdown_url= ""
self.picname=""
self.picpath=""
self.gitlocalpath="E:\GitRepo\Pic"

def on_moved(self, event):
if event.is_directory:
pass
# print("directory moved from {0} to {1}".format(event.src_path,event.dest_path))
else:
pass
# print("file moved from {0} to {1}".format(event.src_path,event.dest_path))

def on_created(self, event):
if event.is_directory:
pass
# print("directory created:{0}".format(event.src_path))
else:
# print("file created:{0}".format(event.src_path))

self.picpath=event.src_path
self.picname=self.picpath.split("\\")[-1]

if self.picname.endswith('png') or self.picname.endswith('jpg') or self.picname.endswith('gif'):
print(self.picname)
print(len(self.picname))
self.empty_clipboard()
if(True==self.gitdo()):
self.markdown_url=self.markdown_url_pre+self.picname+")"
self.set_clipboard(self.markdown_url)
print(self.markdown_url)


def on_deleted(self, event):
if event.is_directory:
pass
# print("directory deleted:{0}".format(event.src_path))
else:
pass
# print("file deleted:{0}".format(event.src_path))

def on_modified(self, event):
if event.is_directory:
pass
# print("directory modified:{0}".format(event.src_path))
else:
pass
# print("file modified:{0}".format(event.src_path))

# for clipboard dosomething
def get_clipboard(self,):
self.user32.OpenClipboard(c_int(0))
contents = c_char_p(self.user32.GetClipboardData(c_int(1))).value
self.user32.CloseClipboard()
return contents
def empty_clipboard(self):
self.user32.OpenClipboard(c_int(0))
self.user32.EmptyClipboard()
self.user32.CloseClipboard()
def set_clipboard(self,data):
self.user32.OpenClipboard(c_int(0))
self.user32.EmptyClipboard()
alloc = self.kernel32.GlobalAlloc(0x2000, len(bytes(data, encoding='utf_8'))+1)
# alloc = kernel32.GlobalAlloc(0x2000, len(data)+1)
lock = self.kernel32.GlobalLock(alloc)
cdll.msvcrt.strcpy(c_char_p(lock),bytes(data, encoding='utf_8'))
# cdll.msvcrt.strcpy(c_char_p(lock), data)
self.kernel32.GlobalUnlock(alloc)
self.user32.SetClipboardData(c_int(1),alloc)
self.user32.CloseClipboard()

def gitdo(self):
pass
try:
repo = Repo(self.gitlocalpath)
index = repo.index
filepath =self.picpath
index.add([filepath])
index.commit('this is a test')
# # 获取默认版本库 origin
remote = repo.remote()
# # 从远程版本库拉取分支
# # remote.pull()
# # 推送本地分支到远程版本库
remote.push()
return True
except:
return False


if __name__ == "__main__":
observer = Observer()
event_handler = FileEventHandler()
observer.schedule(event_handler,"E:\GitRepo",True)
observer.start()
try:
while True:
time.sleep(0.1)
except KeyboardInterrupt:
observer.stop()
observer.join()

打包exe

  • 打包exe需要提取出参数,这里使用ini读取配置,模块用到了configparser
  • 打包命令是pyinstaller -F pic_markdown_get.py
  • 这里改进了一下,增加了一个自动关闭的弹窗提示git push 完成,0x00020000参数表示最前端显示
1
windll.user32.MessageBoxTimeoutW(0, 'push over', 'git', 0x00020000, 0, 200)

mark

参考链接

python操作git

python操作剪切板

操作剪切板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
'''
操作剪切板:读取剪切板的字符串;清空剪切板;向剪切板中写入字符串(只能写入 ascii 字符)。
win10, python3,
'''
from ctypes import *


user32 = windll.user32
kernel32 = windll.kernel32
def get_clipboard():
user32.OpenClipboard(c_int(0))
contents = c_char_p(user32.GetClipboardData(c_int(1))).value
user32.CloseClipboard()
return contents
def empty_clipboard():
user32.OpenClipboard(c_int(0))
user32.EmptyClipboard()
user32.CloseClipboard()

def set_clipboard(data):
user32.OpenClipboard(c_int(0))
user32.EmptyClipboard()
alloc = kernel32.GlobalAlloc(0x2000, len(bytes(data, encoding='utf_8'))+1)
# alloc = kernel32.GlobalAlloc(0x2000, len(data)+1)
lock = kernel32.GlobalLock(alloc)
cdll.msvcrt.strcpy(c_char_p(lock),bytes(data, encoding='utf_8'))
# cdll.msvcrt.strcpy(c_char_p(lock), data)
kernel32.GlobalUnlock(alloc)
user32.SetClipboardData(c_int(1),alloc)
user32.CloseClipboard()

获取剪切板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if __name__ == '__main__':
# 获取剪切板内字符串
text_raw = get_clipboard()
print('{0} {1}'.format(text_raw, type(text_raw)))

try:
text_str = text_raw.decode('utf_8')
print('{0} {1}'.format(text_str, type(text_str)))
except:
print('剪切板为空。')



剪切板为空时,输出结果为:
None <class 'NoneType'>
剪切板为空。

复制一个字符串后运行上面的测试代码(在这里我复制了 python ),输出结果为:
b'Python' <class 'bytes'>
Python <class 'str'>

剪切板中无数据时,get_clipboard() 返回 None。
当剪切板中有数据时,get_clipboard() 将其以 bytes 格式返回;

使用 text_str = text_raw.decode('utf_8')将 bytes 转化为 str。

调用 empty_clipboard() 清空剪切板

1
2
3
4
5
6
7
8
if __name__ == '__main__':
# 清空剪切板
empty_clipboard()
text = get_clipboard()
print(text)

复制一个字符串后运行代码,输出结果为:
None

调用 set_clipboard() 写入剪切板

1
2
3
4
5
6
7
8
if __name__ == '__main__':
# 向剪切板内写入 ascii 字符串
set_clipboard('py!')
text = get_clipboard()
print(text)

输出结果为:
b'py!'

操作git

GitPython 是一个用于操作 Git 版本库的 python 包,
它提供了一系列的对象模型(库 - Repo、树 - Tree、提交 - Commit等)
用于操作版本库中的相应对象。

版本库对象 - Repo

首先,使用包含 .git 文件夹的版本库路径创建 git.Repo 对象

1
2
3
from git import Repo
# 创建版本库对象
repo = git.Repo(r'E:\Notes')

然后便可以使用这个 Repo 对象对版本库进行操作,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 版本库是否为空版本库
repo.bare

# 当前工作区是否干净
repo.is_dirty()

# 版本库中未跟踪的文件列表
repo.untracked_files

# 克隆版本库
repo.clone('clone_path')

# 压缩版本库到 tar 文件
with open('repo.tar', 'wb') as fp:
repo.archive(fp)

# 新建分支
repo.create_head('branchname')

# 查看当前分支
repo.active_branch

索引/暂存区对象 - Index

Git 术语中,index 表示暂存区,为下次将要提交到版本库里的文件,
GitPython 提供 Repo.Index 来操作暂存区,如添加、提交操作

1
2
3
4
index = repo.index
index.add(['new.txt'])
index.remove(['old.txt'])
index.commit('this is a test')

远程版本库操作 - Remotes

Remotes 用于操作远程版本库,可以通过 Repo.remote 方法获取远程版本库,
Repo.Remotes 属性获取远程版本库列表

1
2
3
4
5
6
7
8
# 获取默认版本库 origin
remote = repo.remote()
# 从远程版本库拉取分支
remote.pull()
# 推送本地分支到远程版本库
remote.push()
# 重命名远程分支
# remote.rename('new_origin')

直接执行 Git 命令

一般我们在工作目录做了改变之后,就会调用 git add 命令添加文件到暂存区,
然后调用 git commit 命令提交更改,Repo 虽然没有添加、提交方法,
但取而代之提供了一个 git.cmd.Git 对象实现对 Git 命令的调用,
通过 Repo.git 来进行 Git 命令操作。

1
2
3
git = repo.git
git.add('test1.txt') # git add test1.txt
git.commit('-m', 'this is a test') # git commit -m 'this is a test'

Repo.git.[command] 即相当于调用对应的 git 命令,而调用对应命令方法所用的参数,
会被转换成跟在命令后的参数。

而调用命令方法所用的命名参数会被转换成对应的完整参数,如:git.command(flag=True)
会被转换成 git command --flag 命令执行

总结

基本的 Git 操作可以概括如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 新建版本库对象
repo = Repo(r'E:\Notes')

# 进行文件修改操作

# 获取版本库暂存区
index = repo.index
# 添加修改文件
index.add(['new.txt'])
# 提交修改到本地仓库
index.commit('this is a test')

# 获取远程仓库
remote = repo.remote()
# 推送本地修改到远程仓库
remote.push()

参考链接:

https://my.oschina.net/hopeMan/blog/141221

http://gitpython.readthedocs.io/en/stable/tutorial.html