# -*- coding: utf-8 -*- import os import json import time import datetime import shutil import urllib import requests import argparse from github import Github from xpinyin import Pinyin from feedgen.feed import FeedGenerator from jinja2 import Environment, FileSystemLoader ###################################################################################### i18n={"Search":"搜索","switchTheme":"切换主题","link":"友情链接","home":"首页","comments":"评论","run":"网站运行","days":"天"} ###################################################################################### class GMEEK(): def __init__(self,options): self.options=options self.root_dir='docs/' self.post_folder='post/' self.backup_dir='backup/' self.post_dir=self.root_dir+self.post_folder user = Github(self.options.github_token) self.repo = self.get_repo(user, options.repo_name) self.feed = FeedGenerator() self.labelColorDict=json.loads('{}') for label in self.repo.get_labels(): self.labelColorDict[label.name]='#'+label.color print(self.labelColorDict) config=json.loads(open('config.json', 'r', encoding='utf-8').read()) self.blogBase=config.copy() self.blogBase["GMEEK_VERSION"]=options.Gmeek_version self.blogBase["postListJson"]=json.loads('{}') def cleanFile(self): if os.path.exists(self.backup_dir): shutil.rmtree(self.backup_dir) if os.path.exists(self.root_dir): shutil.rmtree(self.root_dir) os.mkdir(self.backup_dir) os.mkdir(self.root_dir) os.mkdir(self.post_dir) def get_repo(self,user:Github, repo:str): return user.get_repo(repo) def markdown2html(self,mdstr): payload = {"text": mdstr, "mode": "markdown"} ret=requests.post("https://api.github.com/markdown", json=payload,headers={"Authorzation":"token {}".format(self.options.github_token)}) if ret.status_code==200: return ret.text else: raise Exception("markdown2html error status_code=%d"%(ret.status_code)) def createPostHtml(self,issue): if issue["label"] in self.blogBase["singlePage"]: gen_Html = 'docs/{}.html'.format(issue["label"]) else: gen_Html = self.post_dir+'{}.html'.format(Pinyin().get_pinyin(issue["postTitle"])) f = open("backup/"+issue["postTitle"]+".md", 'r', encoding='UTF-8') post_body=self.markdown2html(f.read()) f.close() postBase=json.loads('{}') postBase["postTitle"]=issue["postTitle"] postBase["postBody"]=post_body postBase["title"]=self.blogBase["title"] postBase["homeUrl"]=self.blogBase["homeUrl"] postBase["postSourceUrl"]=issue["postSourceUrl"] postBase["faviconUrl"]=self.blogBase["faviconUrl"] postBase["filingNum"]=self.blogBase["filingNum"] postBase["startSite"]=self.blogBase["startSite"] postBase["i18n"]=self.blogBase["i18n"] postBase["commentNum"]=issue["commentNum"] postBase["fontSize"]=issue["fontSize"] postBase["top"]=issue["top"] postBase["repoName"]=options.repo_name postBase["GMEEK_VERSION"]=options.Gmeek_version file_loader = FileSystemLoader('templates') env = Environment(loader=file_loader) template = env.get_template('post.html') output = template.render(blogBase=postBase,i18n=i18n) f = open(gen_Html, 'w', encoding='UTF-8') f.write(output) f.close() print("create postPage title=%s file=%s " % (issue["postTitle"],gen_Html)) def createPlistHtml(self): self.blogBase["postListJson"]=dict(sorted(self.blogBase["postListJson"].items(),key=lambda x:(x[1]["top"],x[1]["createdAt"]),reverse=True))#使列表由时间排序 file_loader = FileSystemLoader('templates') env = Environment(loader=file_loader) template = env.get_template('plist.html') output = template.render(blogBase=self.blogBase,postListJson=self.blogBase["postListJson"],i18n=i18n) f = open(self.root_dir+"index.html", 'w', encoding='UTF-8') f.write(output) f.close() print("create docs/index.html") def createFeedXml(self): self.blogBase["postListJson"]=dict(sorted(self.blogBase["postListJson"].items(),key=lambda x:x[1]["createdAt"],reverse=False))#使列表由时间排序 feed = FeedGenerator() feed.title(self.blogBase["title"]) feed.description(self.blogBase["subTitle"]) feed.link(href=self.blogBase["homeUrl"]) feed.image(url=self.blogBase["avatarUrl"],title="avatar", link=self.blogBase["homeUrl"]) feed.pubDate(time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())) feed.copyright(self.blogBase["title"]) feed.managingEditor(self.blogBase["title"]) feed.webMaster(self.blogBase["title"]) feed.ttl("60") for num in self.blogBase["postListJson"]: item=feed.add_item() item.guid(self.blogBase["homeUrl"]+"/"+self.blogBase["postListJson"][num]["postUrl"],permalink=True) item.title(self.blogBase["postListJson"][num]["postTitle"]) item.description(self.blogBase["postListJson"][num]["description"]) item.link(href=self.blogBase["homeUrl"]+"/"+self.blogBase["postListJson"][num]["postUrl"]) item.pubDate(time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(self.blogBase["postListJson"][num]["createdAt"]))) feed.rss_file(self.root_dir+'rss.xml') def addOnePostJson(self,issue): if len(issue.labels)==1: postNum="P"+str(issue.number) self.blogBase["postListJson"][postNum]=json.loads('{}') self.blogBase["postListJson"][postNum]["label"]=issue.labels[0].name self.blogBase["postListJson"][postNum]["labelColor"]=self.labelColorDict[issue.labels[0].name] self.blogBase["postListJson"][postNum]["postTitle"]=issue.title self.blogBase["postListJson"][postNum]["postUrl"]=urllib.parse.quote(self.post_folder+'{}.html'.format(Pinyin().get_pinyin(issue.title))) self.blogBase["postListJson"][postNum]["postSourceUrl"]="https://github.com/"+options.repo_name+"/issues/"+str(issue.number) self.blogBase["postListJson"][postNum]["commentNum"]=issue.get_comments().totalCount if self.blogBase["i18n"]=="CN": period="。" else: period="." self.blogBase["postListJson"][postNum]["description"]=issue.body.split(period)[0]+period self.blogBase["postListJson"][postNum]["top"]=0 for event in issue.get_events(): if event.event=="pinned": self.blogBase["postListJson"][postNum]["top"]=1 break elif event.event=="unpinned": break try: postConfig=json.loads(issue.body.split("\r\n")[-1:][0].split("##")[1]) print("Has Custom JSON parameters") print(postConfig) except: postConfig={} if "timestamp" in postConfig: self.blogBase["postListJson"][postNum]["createdAt"]=postConfig["timestamp"] else: self.blogBase["postListJson"][postNum]["createdAt"]=int(time.mktime(issue.created_at.timetuple())) if "fontSize" in postConfig: self.blogBase["postListJson"][postNum]["fontSize"]=str(postConfig["fontSize"]) else: self.blogBase["postListJson"][postNum]["fontSize"]="" thisTime=datetime.datetime.fromtimestamp(self.blogBase["postListJson"][postNum]["createdAt"]) thisYear=thisTime.year self.blogBase["postListJson"][postNum]["createdDate"]=thisTime.strftime("%Y-%m-%d") self.blogBase["postListJson"][postNum]["dateLabelColor"]=self.blogBase["yearColorList"][int(thisYear)%len(self.blogBase["yearColorList"])] f = open("backup/"+issue.title+".md", 'w', encoding='UTF-8') f.write(issue.body) f.close() def runAll(self): print("====== start create static html ======") self.cleanFile() issues=self.repo.get_issues() for issue in issues: self.addOnePostJson(issue) for issue in self.blogBase["postListJson"].values(): self.createPostHtml(issue) self.createPlistHtml() self.createFeedXml() print("====== create static html end ======") def runOne(self,number_str): print("====== start create static html ======") issue=self.repo.get_issue(int(number_str)) self.addOnePostJson(issue) self.createPostHtml(self.blogBase["postListJson"]["P"+number_str]) self.createPlistHtml() self.createFeedXml() print("====== create static html end ======") ###################################################################################### parser = argparse.ArgumentParser() parser.add_argument("github_token", help="github_token") parser.add_argument("repo_name", help="repo_name") parser.add_argument("Gmeek_version", help="Gmeek_version") parser.add_argument("--issue_number", help="issue_number", default=0, required=False) options = parser.parse_args() blog=GMEEK(options) if not os.path.exists("blogBase.json"): print("blogBase is not exists, runAll") blog.runAll() else: if options.issue_number=="0" or options.issue_number=="": print("issue_number=='0', runAll") blog.runAll() else: f=open("blogBase.json","r") print("blogBase is exists and issue_number!=0, runOne") blog.blogBase=json.loads(f.read()) f.close() blog.runOne(options.issue_number) listFile=open("blogBase.json","w") listFile.write(json.dumps(blog.blogBase)) listFile.close() ######################################################################################