GitHub Action commited on
Commit
c8babf9
·
1 Parent(s): ce09a51

Sync from GitHub with Git LFS

Browse files
Files changed (1) hide show
  1. scripts/publish_to_blogger.py +79 -74
scripts/publish_to_blogger.py CHANGED
@@ -1,100 +1,105 @@
1
- #!/usr/bin/env python3
2
  import os
3
  import json
4
  import hashlib
5
  import time
 
 
 
 
6
  from googleapiclient.discovery import build
 
 
7
  from google.oauth2.credentials import Credentials
8
- import argparse
9
 
10
- # === Настройки ===
11
- SITE_DIR = "site" # HTML-файлы после mkdocs build
 
12
  PUBLISHED_FILE = "published_posts.json"
13
- SLEEP_BETWEEN_POSTS = 60 # секунд
14
- BLOG_ID = os.environ.get("BLOG_ID")
15
- TOKEN_FILE = os.environ.get("TOKEN_FILE", "token.pkl")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
- # === Утилиты ===
18
- def md5sum(path):
19
- with open(path, "rb") as f:
20
- return hashlib.md5(f.read()).hexdigest()
21
 
22
  def load_published():
23
- if os.path.exists(PUBLISHED_FILE):
24
  with open(PUBLISHED_FILE, "r", encoding="utf-8") as f:
25
  return json.load(f)
26
  print("⚠ published_posts.json не найден — начинаем с нуля.")
27
  return {}
28
 
 
29
  def save_published(data):
30
  with open(PUBLISHED_FILE, "w", encoding="utf-8") as f:
31
  json.dump(data, f, ensure_ascii=False, indent=2)
32
 
33
- def get_service():
 
 
 
 
 
34
  creds = Credentials.from_authorized_user_file(TOKEN_FILE)
35
- return build("blogger", "v3", credentials=creds)
36
 
37
- # === Основная логика ===
38
- def publish_site():
39
- service = get_service()
40
  published = load_published()
41
 
42
- # собираем все html-файлы
43
- html_files = []
44
- for root, _, files in os.walk(SITE_DIR):
45
- for name in files:
46
- if name.endswith(".html"):
47
- path = os.path.join(root, name)
48
- rel_path = os.path.relpath(path, SITE_DIR) # ключ
49
- html_files.append((rel_path, path))
50
-
51
- for rel_path, path in html_files:
52
- content_hash = md5sum(path)
53
- post_meta = published.get(rel_path)
54
-
55
- # читаем содержимое html
56
- with open(path, "r", encoding="utf-8") as f:
57
- html_content = f.read()
58
-
59
- if post_meta and post_meta["hash"] == content_hash:
60
- print(f"⏭ Пропускаем {rel_path} — без изменений")
61
- continue
62
-
63
- title = os.path.splitext(os.path.basename(rel_path))[0]
64
-
65
- if post_meta: # обновление поста
66
- post_id = post_meta["id"]
67
- print(f"🔄 Обновляем пост {rel_path}")
68
- post = (
69
- service.posts()
70
- .update(
71
- blogId=BLOG_ID,
72
- postId=post_id,
73
- body={"title": title, "content": html_content},
74
- )
75
- .execute()
76
- )
77
- else: # новый пост
78
- print(f"🆕 Публикуем новый пост {rel_path}")
79
- post = (
80
- service.posts()
81
- .insert(
82
- blogId=BLOG_ID,
83
- body={"title": title, "content": html_content},
84
- )
85
- .execute()
86
- )
87
-
88
- url = post.get("url")
89
- post_id = post.get("id")
90
- print(f"✅ {rel_path} → {url}")
91
-
92
- # сохраняем метаданные
93
- published[rel_path] = {"id": post_id, "hash": content_hash}
94
- save_published(published)
95
-
96
- print(f"⏱ Пауза {SLEEP_BETWEEN_POSTS} секунд перед следующим постом…")
97
- time.sleep(SLEEP_BETWEEN_POSTS)
98
 
99
  if __name__ == "__main__":
100
- publish_site()
 
 
1
  import os
2
  import json
3
  import hashlib
4
  import time
5
+ import re
6
+ from pathlib import Path
7
+
8
+ import markdown2
9
  from googleapiclient.discovery import build
10
+ from googleapiclient.errors import HttpError
11
+ from google.auth.transport.requests import Request
12
  from google.oauth2.credentials import Credentials
 
13
 
14
+
15
+ BLOG_ID = os.environ["BLOG_ID"]
16
+ TOKEN_FILE = os.environ["TOKEN_FILE"]
17
  PUBLISHED_FILE = "published_posts.json"
18
+ GH_PAGES_BASE = "https://kagvi13.github.io/HMP/"
19
+
20
+
21
+ def convert_md_links(md_text: str) -> str:
22
+ """
23
+ Конвертирует относительные ссылки (*.md) в абсолютные ссылки на GitHub Pages.
24
+ """
25
+ def replacer(match):
26
+ text = match.group(1)
27
+ link = match.group(2)
28
+
29
+ # если это абсолютный URL или не .md — оставляем как есть
30
+ if link.startswith("http://") or link.startswith("https://") or not link.endswith(".md"):
31
+ return match.group(0)
32
+
33
+ abs_link = GH_PAGES_BASE + link.replace(".md", "").lstrip("./")
34
+ return f"[{text}]({abs_link})"
35
+
36
+ return re.sub(r"\[([^\]]+)\]\(([^)]+)\)", replacer, md_text)
37
 
 
 
 
 
38
 
39
  def load_published():
40
+ if Path(PUBLISHED_FILE).exists():
41
  with open(PUBLISHED_FILE, "r", encoding="utf-8") as f:
42
  return json.load(f)
43
  print("⚠ published_posts.json не найден — начинаем с нуля.")
44
  return {}
45
 
46
+
47
  def save_published(data):
48
  with open(PUBLISHED_FILE, "w", encoding="utf-8") as f:
49
  json.dump(data, f, ensure_ascii=False, indent=2)
50
 
51
+
52
+ def file_hash(path):
53
+ return hashlib.md5(Path(path).read_bytes()).hexdigest()
54
+
55
+
56
+ def main():
57
  creds = Credentials.from_authorized_user_file(TOKEN_FILE)
58
+ service = build("blogger", "v3", credentials=creds)
59
 
 
 
 
60
  published = load_published()
61
 
62
+ md_files = list(Path("docs").rglob("*.md"))
63
+ for md_file in md_files:
64
+ name = md_file.stem
65
+ h = file_hash(md_file)
66
+
67
+ if name in published and published[name]["hash"] == h:
68
+ continue # ничего не изменилось
69
+
70
+ print(f"📝 Новый или изменённый пост: {name}")
71
+
72
+ md_text = md_file.read_text(encoding="utf-8")
73
+ md_text = convert_md_links(md_text)
74
+ html_content = markdown2.markdown(md_text)
75
+
76
+ body = {
77
+ "kind": "blogger#post",
78
+ "title": name,
79
+ "content": html_content,
80
+ }
81
+
82
+ try:
83
+ if name in published:
84
+ post_id = published[name]["id"]
85
+ post = service.posts().update(blogId=BLOG_ID, postId=post_id, body=body).execute()
86
+ print(f"♻ Обновлён пост: {post['url']}")
87
+ else:
88
+ post = service.posts().insert(blogId=BLOG_ID, body=body).execute()
89
+ print(f"🆕 Пост опубликован: {post['url']}")
90
+ post_id = post["id"]
91
+
92
+ published[name] = {"id": post_id, "hash": h}
93
+ save_published(published)
94
+
95
+ print("⏱ Пауза 60 секунд перед следующим постом...")
96
+ time.sleep(60)
97
+
98
+ except HttpError as e:
99
+ print(f"❌ Ошибка при публикации {name}: {e}")
100
+ save_published(published)
101
+ break
102
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  if __name__ == "__main__":
105
+ main()