-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgen_github_pdf.py
More file actions
259 lines (224 loc) · 8.92 KB
/
Copy pathgen_github_pdf.py
File metadata and controls
259 lines (224 loc) · 8.92 KB
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
"""生成 GitHub 上传记录证明材料 PDF"""
import os, re, json, subprocess
from pathlib import Path
from fpdf import FPDF
BASE = Path(r"C:\Users\29117\.openclaw\workspace\study-planner")
OUT_DIR = BASE / "软著材料"
OUT_DIR.mkdir(exist_ok=True)
REPO = "Cosmossssssssssss/AstroStudy"
def find_chinese_font():
candidates = [
r"C:\Windows\Fonts\simsun.ttc",
r"C:\Windows\Fonts\msyh.ttc",
r"C:\Windows\Fonts\msyhbd.ttc",
r"C:\Windows\Fonts\simhei.ttf",
]
for p in candidates:
if os.path.exists(p):
return p
return None
def gh(*args):
cmd = ["gh", "api"] + list(args)
r = subprocess.run(cmd, capture_output=True, text=True)
if r.returncode != 0:
raise RuntimeError(f"gh api failed: {r.stderr}")
return r.stdout
def strip_md(text):
text = re.sub(r'\*\*(.+?)\*\*', r'\1', text)
text = re.sub(r'`(.+?)`', r'\1', text)
text = re.sub(r'\[(.+?)\]\(.+?\)', r'\1', text)
return text
def main():
ch_font = find_chinese_font()
if not ch_font:
print("未找到中文字体")
return
# 获取数据
repo = json.loads(gh(f"repos/{REPO}", "--jq", "{name, description, created_at, pushed_at, html_url, default_branch, private, stargazers_count, language}"))
commits_raw = gh(f"repos/{REPO}/commits", "--jq", ".[] | {date: .commit.author.date, message: .commit.message}")
# parse commit list manually since each is one line
commits = []
for line in commits_raw.strip().split("\n"):
commits.append(json.loads(line))
files_raw = gh(f"repos/{REPO}/git/trees/main?recursive=1", "--jq", ".tree[].path")
files = [f for f in files_raw.strip().split("\n") if f]
pdf = FPDF(orientation="P", unit="mm", format="A4")
pdf.set_auto_page_break(auto=True, margin=20)
pdf.add_font("CN", "", ch_font)
# ─── 封面 ───
pdf.add_page()
pdf.ln(45)
pdf.set_font("CN", "", 22)
pdf.cell(0, 12, "软件著作权申请", align="C")
pdf.ln(10)
pdf.set_font("CN", "", 16)
pdf.cell(0, 10, "GitHub 开源发布证明材料", align="C")
pdf.ln(12)
pdf.set_draw_color(60, 60, 60)
pdf.set_line_width(0.3)
pdf.line(55, pdf.get_y(), 155, pdf.get_y())
pdf.ln(10)
pdf.set_font("CN", "", 13)
pdf.cell(0, 9, "AstroStudy 学习备考助手", align="C")
pdf.ln(9)
pdf.set_font("CN", "", 11)
pdf.cell(0, 8, f"仓库地址: {repo['html_url']}", align="C")
pdf.ln(25)
pdf.set_font("CN", "", 10)
pdf.cell(0, 7, "2026 年 5 月", align="C")
# ─── 第 1 页:仓库概述 ───
pdf.add_page()
pdf.set_font("CN", "", 16)
pdf.cell(0, 10, "一、仓库基本信息")
pdf.ln(14)
info_items = [
("仓库名称", repo['name']),
("仓库地址", repo['html_url']),
("默认分支", repo['default_branch']),
("创建时间", repo['created_at']),
("最后推送", repo['pushed_at']),
("公开状态", "公开 (Public)" if not repo['private'] else "私有 (Private)"),
("主要语言", repo['language']),
("星标数", str(repo['stargazers_count'])),
]
pdf.set_font("CN", "", 11)
for label, value in info_items:
pdf.set_x(pdf.l_margin + 10)
pdf.cell(35, 8, label + ":")
pdf.set_font("CN", "", 11)
pdf.cell(0, 8, value)
pdf.ln(8)
pdf.ln(6)
pdf.set_font("CN", "", 11)
pdf.set_x(pdf.l_margin + 5)
pdf.multi_cell(pdf.w - pdf.r_margin - pdf.l_margin - 10, 7,
"上述仓库于 2026 年 5 月 9 日创建并完成首次代码上传,"
"公开可见,包含 AstroStudy 学习备考助手软件的完整源代码。"
"以下为提交记录和文件清单,作为软件原创开发与公开发布的证明材料。")
# ─── 第 2 页:提交记录 ───
pdf.add_page()
pdf.set_font("CN", "", 16)
pdf.cell(0, 10, "二、提交记录 (Commits)")
pdf.ln(14)
pdf.set_font("CN", "", 10)
pdf.set_x(pdf.l_margin + 5)
pdf.cell(0, 7, f"共计 {len(commits)} 次提交:")
pdf.ln(10)
for idx, c in enumerate(commits, 1):
# 检查是否需要换页
if pdf.get_y() > pdf.h - 40:
pdf.add_page()
pdf.set_font("CN", "", 10)
date_str = c['date'].replace("T", " ").replace("Z", " UTC")
msg_lines = c['message'].split("\n")
title = strip_md(msg_lines[0])
pdf.set_font("CN", "", 10)
pdf.set_x(pdf.l_margin + 8)
pdf.cell(8, 7, f"#{idx}")
pdf.set_font("CN", "", 9)
pdf.set_text_color(100, 100, 100)
pdf.cell(50, 7, date_str)
pdf.set_text_color(0, 0, 0)
pdf.ln(7)
pdf.set_font("CN", "", 10)
pdf.set_x(pdf.l_margin + 16)
pdf.multi_cell(pdf.w - pdf.r_margin - pdf.l_margin - 20, 6.5, title)
pdf.ln(1)
for detail in msg_lines[1:]:
detail = detail.strip()
if detail and not detail.startswith("Co-authored"):
pdf.set_font("CN", "", 8)
pdf.set_x(pdf.l_margin + 20)
pdf.set_text_color(80, 80, 80)
pdf.cell(0, 5.5, strip_md(detail))
pdf.ln(5.5)
pdf.set_text_color(0, 0, 0)
pdf.ln(4)
# ─── 文件清单 ───
pdf.add_page()
pdf.set_font("CN", "", 16)
pdf.cell(0, 10, "三、仓库文件清单")
pdf.ln(12)
pdf.set_font("CN", "", 10)
pdf.set_x(pdf.l_margin + 5)
pdf.cell(0, 7, f"仓库包含 {len(files)} 个文件。其中源代码文件(.py / .html / .js)共 "
f"{sum(1 for f in files if f.endswith(('.py','.html','.js')))} 个。")
pdf.ln(10)
# 分组显示
groups = {}
for f in files:
parts = f.split("/")
group = parts[0] if len(parts) > 1 else "(根目录)"
groups.setdefault(group, []).append(f)
pdf.set_font("CN", "", 10)
order = [k for k in ["(根目录)", "blueprints", "templates", "static", "static/vendor", "static/riv", "static/vendor/rive", "static/vendor/toastui-editor"] if k in groups]
order += [k for k in groups if k not in order]
col_w = (pdf.w - pdf.l_margin - pdf.r_margin - 30) / 2
for group in order:
if pdf.get_y() > pdf.h - 40:
pdf.add_page()
pdf.set_font("CN", "", 10)
file_list = groups[group]
pdf.set_font("CN", "", 11)
pdf.set_x(pdf.l_margin + 5)
pdf.cell(0, 8, f"目录: {group}/ ({len(file_list)} 个文件)")
pdf.ln(9)
pdf.set_font("CN", "", 9)
for j, fpath in enumerate(file_list):
fname = fpath.split("/")[-1]
col = j % 2
y0 = pdf.get_y()
x = pdf.l_margin + 10 + col * (col_w + 15)
pdf.set_xy(x, y0)
ext = os.path.splitext(fname)[1]
if ext in ('.py', '.html', '.js', '.css'):
pdf.set_text_color(20, 80, 160)
else:
pdf.set_text_color(80, 80, 80)
pdf.cell(col_w, 6, fname)
pdf.set_text_color(0, 0, 0)
if col == 1:
pdf.ln(6)
if len(file_list) % 2 == 1:
pdf.ln(6)
pdf.ln(3)
# ─── 声明 ───
pdf.add_page()
pdf.set_font("CN", "", 16)
pdf.cell(0, 10, "四、声明")
pdf.ln(16)
statements = [
f"1. 本仓库 ( {repo['html_url']} ) 于 {repo['created_at'].replace('T', ' ').replace('Z', '')} (UTC) 创建,"
f"目前为公开状态,任何人均可访问和查看。",
"2. 仓库中的全部源代码由软件著作权申请人独立开发完成,"
"未抄袭、未使用未授权的第三方代码(第三方依赖库按开源协议引用)。",
f"3. 仓库共有 {len(commits)} 次提交记录,"
f"首次提交时间为 {commits[-1]['date'].replace('T', ' ').replace('Z', '')} (UTC),"
f"最后一次提交时间为 {commits[0]['date'].replace('T', ' ').replace('Z', '')} (UTC)。"
"提交记录具有时间戳的不可篡改性,可作为软件著作权申请中"
"开发时间节点的有效佐证。",
"4. 本材料为软件著作权申请的辅助证明材料,"
"用于证明该软件已公开发布于 GitHub 平台,"
"且有明确的时间戳记录可追溯。",
]
pdf.set_font("CN", "", 11)
for s in statements:
pdf.set_x(pdf.l_margin + 5)
pdf.multi_cell(pdf.w - pdf.r_margin - pdf.l_margin - 10, 7.5, s)
pdf.ln(6)
pdf.ln(20)
pdf.set_font("CN", "", 10)
pdf.set_x(pdf.l_margin + 5)
pdf.cell(0, 7, "申请人: Cosmossssssssssss")
pdf.ln(8)
pdf.set_x(pdf.l_margin + 5)
pdf.cell(0, 7, "日期: 2026 年 5 月 16 日")
# 输出
out = OUT_DIR / "AstroStudy_GitHub上传记录.pdf"
pdf.output(str(out))
print(f"GitHub 记录 PDF -> {out.name}")
print(f" 仓库: {repo['html_url']}")
print(f" 提交: {len(commits)} 次")
print(f" 文件: {len(files)} 个")
if __name__ == "__main__":
main()