def index_route(page_index=1): page_url = "/index/{0}/".format(page_index) localtime = time.localtime(time.time()) global last_build_year if last_build_year != localtime[0]: last_build_year = localtime[0] cache_index.clear() cache_post.clear() if page_url in cache_index: console.log("Success", "Get cache Success: {0}".format(page_url)) return cache_index[page_url] console.log("Info", "Trying to build: {0}".format(page_url)) page_row = page.get_page_row(system_config["Paging"], len(page_list)) if page_index == 0 or page_index > page_row: abort(404) result = page.build_index(page_index, page_row, system_config, page_list, menu_list, template_config, i18n) if result is None: abort(404) console.log("Info", "Writing to cache: {0}".format(page_url)) if len(cache_index) >= 50: page_keys = sorted(cache_index.keys()) console.log("Info", "Delete cache: {0}".format(page_keys[0])) del cache_index[page_keys[0]] cache_index[page_url] = result console.log("Success", "Get success: {0}".format(page_url)) return result
def new_post_init(config, independent=False): title = config["title"] name = get.filter_name(config["name"]) if not os.path.exists("./document/{}.md".format(name)): editor = system_info["Editor"] os.system("{0} ./document/{1}.md".format(editor, name)) post_info = {"name": name, "title": title, "time": time.time()} if not os.path.exists("./document/{}.md".format(name)): console.log("Error", "Cannot find [./document/{}.md] file".format(name)) return if not independent: excerpt = get.get_excerpt("./document/{}.md".format(name)) post_info["excerpt"] = excerpt write_json = post_info page_config = "./document/{}.json".format(name) if not independent: write_json = json.loads(file.read_file("./config/page.json")) write_json.insert(0, post_info) page_config = "./config/page.json" file.write_file( page_config, json.dumps(write_json, indent=4, sort_keys=False, ensure_ascii=False)) console.log("Success", "Create a new article successfully!")
def get_orgs_list(): console.log("info", "Getting the list of theme...") try: return requests.get("https://api.github.com/orgs/silverblogtheme/repos").json() except requests.exceptions.RequestException: console.log("Error", "Get the theme list error.") exit(1)
def write_post_cache(page_url, content): console.log("Info", "Writing to cache: {0}".format(page_url)) if len(cache_post) >= 50: page_keys = sorted(cache_post.keys()) console.log("Info", "Delete cache: {0}".format(page_keys[0])) del cache_post[page_keys[0]] cache_post[page_url] = content
def post_route(file_name=None): if file_name is None or not os.path.exists( "./document/{0}.md".format(file_name)): abort(404) page_url = "/post/{0}/".format(file_name) global last_build_year localtime = time.localtime(time.time()) if last_build_year != localtime[0]: console.log("Info", "Found a year change, cache cleanup.") last_build_year = localtime[0] cache_index.clear() cache_post.clear() if page_url in cache_post: console.log("Success", "Get cache Success: {0}".format(page_url)) return cache_post[page_url] page_info = None if file_name in page_name_list: this_page_index = page_name_list.index(file_name) page_info = page_list[this_page_index] result = page.build_page(file_name, system_config, page_info, menu_list, template_config, i18n) console.log("Info", "Writing to cache: {0}".format(page_url)) if len(cache_post) >= 50: page_keys = sorted(cache_post.keys()) console.log("Info", "Delete cache: {0}".format(page_keys[0])) del cache_post[page_keys[0]] cache_post[page_url] = result console.log("Success", "Get success: {0}".format(page_url)) return result
def edit_post(post_list, post_index, config, editor=None, is_menu=False): safe_name = get.filter_name(config["name"]) if post_list[post_index]["name"] is not config["name"]: shutil.move("./document/{}.md".format(post_list[post_index]["name"]), "./document/{}.md".format(safe_name)) if os.path.exists("./document/{}.json".format( post_list[post_index]["name"])): shutil.move( "./document/{}.json".format(post_list[post_index]["name"]), "./document/{}.json".format(safe_name)) config_file = json.loads( file.read_file("./document/{}.json".format(safe_name))) config_file["title"] = config["title"] if "time" in config: config_file = config["time"] file.write_file("./document/{}.json".format(safe_name), file.json_format_dump(config_file)) post_list[post_index]["name"] = safe_name if editor is not None: os.system("{0} ./document/{1}.md".format(editor, safe_name)) post_list[post_index]["title"] = config["title"] file_url = "./config/page.json" if is_menu: file_url = "./config/menu.json" file.write_file(file_url, file.json_format_dump(post_list)) console.log("Success", "Edit a new article successfully!")
def new_post(config, independent=False): system_info = json.loads(file.read_file("./config/system.json")) title = config["title"] name = get.filter_name(config["name"]) post_uuid = str(uuid.uuid5(uuid.NAMESPACE_URL, name)) if "uuid" in config: post_uuid = config["uuid"] if not os.path.exists("./document/{}.md".format(name)): editor = system_info["Editor"] os.system("{0} ./document/{1}.md".format(editor, name)) post_info = { "uuid": post_uuid, "name": name, "title": title, "time": round(time.time()) } if not os.path.exists("./document/{}.md".format(name)): console.log("Error", "Cannot find [./document/{}.md]".format(name)) exit(1) if not independent: excerpt = get.get_excerpt("./document/{}.md".format(name)) post_info["excerpt"] = excerpt write_json = post_info page_config = "./document/{}.json".format(name) if not independent: write_json = json.loads(file.read_file("./config/page.json")) write_json.insert(0, post_info) page_config = "./config/page.json" file.write_file(page_config, file.json_format_dump(write_json)) console.log("Success", "Create a new article successfully!")
def get_system_config(): global system_config, template_config, i18n load_file = yield from file.async_read_file("./config/system.json") system_config = yield from async_json_loads(load_file) del system_config["API_Password"] if len(system_config["Theme"]) == 0: console.log( "Error", "If you do not get the Theme you installed, check your configuration file and the Theme installation." ) exit(78) if os.path.exists("./templates/{0}/config.json".format( system_config["Theme"])): template_config_file = yield from file.async_read_file( "./templates/{0}/config.json".format(system_config["Theme"])) template_config = yield from async_json_loads(template_config_file) if os.path.exists("./templates/{}/i18n".format(system_config["Theme"])): i18n_name = "en-US" if "i18n" in system_config and len(system_config["i18n"]) != 0: i18n_name = system_config["i18n"] i18n_filename = "./templates/{0}/i18n/{1}.json".format( system_config["Theme"], i18n_name) if os.path.exists(i18n_filename): i18n_file = yield from file.async_read_file(i18n_filename) i18n = yield from async_json_loads(i18n_file)
def remove_theme(theme_name): static_symlink = "./templates/static/{}".format(theme_name) if os.path.exists(static_symlink): os.remove(static_symlink) shutil.rmtree("./templates/" + theme_name) console.log("Success", "The theme is removed successfully!")
def get_system_config(): global system_config, template_config, i18n, static_file_dict load_file = yield from file.async_read_file("./config/system.json") system_config = yield from async_json_loads(load_file) if len(system_config["Theme"]) == 0: console.log("Error", "If you do not get the Theme you installed, check your configuration file and the Theme installation.") exit(1) template_location = "./templates/{0}/".format(system_config["Theme"]) if os.path.exists(template_location + "config.json"): template_config_file = yield from file.async_read_file(template_location + "config.json") template_config = yield from async_json_loads(template_config_file) if os.path.exists(template_location + "cdn"): cdn_config_file = None if os.path.exists(template_location + "cdn/custom.json"): cdn_config_file = template_location + "cdn/custom.json" if cdn_config_file is None: cdn_config_file = template_location + "cdn/local.json" if system_config["Use_CDN"]: cdn_config_file = template_location + "cdn/cdn.json" cdn_file = yield from file.async_read_file(cdn_config_file) static_file_dict = yield from async_json_loads(cdn_file) if os.path.exists("./templates/{}/i18n".format(system_config["Theme"])): i18n_name = "en-US" if "i18n" in system_config and len(system_config["i18n"]) != 0: i18n_name = system_config["i18n"] i18n_filename = "./templates/{0}/i18n/{1}.json".format(system_config["Theme"], i18n_name) if os.path.exists(i18n_filename): i18n_file = yield from file.async_read_file(i18n_filename) i18n = yield from async_json_loads(i18n_file)
def use_text_mode(args): if args.command == "qrcode": system_config = json.loads(file.read_file("./config/system.json")) from common import install_module install_module.install_and_import("qrcode_terminal") import qrcode_terminal if len(system_config["API_Password"]) == 0 or len(system_config["Project_URL"]) == 0: console.log("Error", "Check the API_Password and Project_URL configuration items") exit(1) try: password_md5 = json.loads(system_config["API_Password"])["hash_password"] except (ValueError, KeyError, TypeError): exit(1) console.log("Info", "Please use the client to scan the following QR Code") config_json = json.dumps({"url": system_config["Project_URL"], "password": password_md5}) qrcode_terminal.draw(config_json) exit(0) if args.command == "upgrade": from manage import upgrade if upgrade.upgrade_check(): if not args.yes: start_to_pull = input('Find new version, do you want to upgrade? [y/N]') if start_to_pull.lower() == 'yes' or start_to_pull.lower() == 'y' or args.yes: upgrade.upgrade_pull() exit(0) console.log("Info", "No upgrade found") exit(0) if args.command == "build-page": from manage import build_static_page build_static_page.publish() exit(0) from manage import build_rss, post_manage if args.command == "new": config = None if args.config is not None: config = json.loads(file.read_file(args.config)) if config is None: print("Please enter the title of the article:") title = input().strip() if len(title) == 0: console.log("Error", "The title can not be blank.") exit(1) name = get.get_name(title) print("Please enter the slug [{}]:".format(name)) name2 = input().strip() if len(name2) != 0: name = get.filter_name(name2) if os.path.exists("./document/{}.md".format(name)): console.log("Error", "File [./document/{}.md] already exists".format(name)) exit(1) if len(name) != 0 and len(title) != 0: config = {"title": title, "name": name} post_manage.new_post(config, args.independent) build_rss.build_rss() exit(0) if args.command == "update": if post_manage.update_post(): build_rss.build_rss() exit(0)
def check_build_year(): global last_build_year localtime = time.localtime(time.time()) if last_build_year != localtime[0]: console.log("Info", "Found a year change, cache cleanup.") last_build_year = localtime[0] cache_index.clear() cache_post.clear()
def get_readme(theme_name): console.log("Info", "Getting the readme of theme...") try: r = requests.get( "https://raw.githubusercontent.com/silverblog-theme/{}/master/README.md" .format(theme_name)) return r.text except requests.exceptions.RequestException: console.log("Error", "Get the readme error.") exit(1)
def install_and_import(package): try: importlib.import_module(package) except ImportError: console.log("Error", "Please install the [{}] package to support this feature".format(package)) install_dependency = input('Do you want to install [{}] now? [y/N]'.format(package)) if install_dependency.lower() == 'yes' or install_dependency.lower() == 'y': install_package(package) finally: globals()[package] = importlib.import_module(package)
def build_rss(): system_config = json.loads(file.read_file("./config/system.json")) system_config["Lazyload"] = False page_list = json.loads(file.read_file("./config/page.json")) file.write_file( "./document/rss.xml", make_rss(system_config["Project_Name"], system_config["Project_URL"], system_config["Project_Description"], page_list, system_config)) console.log("Success", "Build rss success!")
def build_rss(): system_config = json.loads(file.read_file("./config/system.json")) page_list = json.loads(file.read_file("./config/page.json")) if "Rss_Full_Content" in system_config: full_content = system_config["Rss_Full_Content"] file.write_file( "./document/rss.xml", make_rss(system_config["Project_Name"], system_config["Project_URL"], system_config["Project_Description"], page_list, system_config)) console.log("Success", "Build Rss Success!")
def get_gravatar(author_name): import requests console.log("info", "Get Gravatar URL...") gravatar_hash = "" try: r = requests.get( "https://en.gravatar.com/{0}.json".format(author_name)).json() gravatar_hash = r["entry"][0]["hash"] except (TypeError, ValueError, requests.exceptions.RequestException): console.log("Error", "Get Gravatar URL error,use default avatar.") return "https://secure.gravatar.com/avatar/{0}".format(gravatar_hash)
def build_post_page(filename, page_name_list, page_list, system_config, menu_list, template_config, i18n): file_name = os.path.basename(filename).replace(".md", "") console.log("Build", "Processing file: ./static_page/post/{0}.html".format(file_name)) page_info = None if file_name in page_name_list: this_page_index = page_name_list.index(file_name) page_info = page_list[this_page_index] content = yield from async_build_page(file_name, system_config, page_info, menu_list, template_config, i18n) if content is not None: yield from file.async_write_file("./static_page/post/{0}.html".format(file_name), content)
def upgrade_data(): if current_data_version != new_data_version: from manage import backup backup.backup(str(current_data_version)) for index in range(current_data_version, new_data_version): if os.path.exists("./upgrade/upgrade_from_{}.py".format(index)): upgrade_item = importlib.import_module( "upgrade.upgrade_from_{}".format(index), __package__) upgrade_item.main() file.write_file("./upgrade/current_version.json", json.dumps({"current_data_version": new_data_version})) console.log("Success", "Upgrade data Successful!")
def build_excerpt(item): global page_list processing_file = "./document/{}.md".format(item["name"]) console.log("Build", "Processing file: {}".format(processing_file)) custom_config_file = "./document/{}.json".format(item["name"]) if os.path.exists(custom_config_file): console.log("Build", "Processing file: {}".format(custom_config_file)) custom_config_content = yield from file.async_read_file(custom_config_file) custom_config = json.loads(custom_config_content) page_list[page_list.index(item)].update(custom_config) if "excerpt" in custom_config: return page_list[page_list.index(item)]["excerpt"] = yield from async_get_excerpt(processing_file)
def upgrade_pull(): if not os.path.exists("./.git"): console.log("Error", "Not a git repository.") return False repo, remote = git_init() console.log("Info", "On branch {}".format(repo.active_branch)) if repo.is_dirty(): console.log("Error", "The current warehouse is modified and can not be upgraded automatically.") checkout_repo = input('Do you want to restore these changes? [y/N]') if checkout_repo.lower() == 'yes' or checkout_repo.lower() == 'y': repo.index.checkout(force=True) if repo.is_dirty(): exit(1) remote.pull() if current_env_version != new_env_version: os.system("cd ./install && bash install_python_dependency.sh") file.write_file("./upgrade/current_version.json", json.dumps({"current_data_version": new_data_version, "current_env_version": new_env_version})) if current_data_version != new_data_version and os.path.exists( "./upgrade/upgrade_from_{}.py".format(current_data_version)): os.system("python3 ./upgrade/upgrade_from_{}.py".format(current_data_version)) file.write_file("./upgrade/current_version.json", json.dumps({"current_data_version": new_data_version, "current_env_version": new_env_version})) console.log("Success", "Upgrade Successful!") exit(0)
def index_route(page_index=1): page_url = "/index/{0}/".format(page_index) result = get_index_cache(page_url) if result is None: page_row = page.get_page_row(system_config["Paging"], len(page_list)) if page_index == 0 or page_index > page_row: abort(404) result = page.build_index(page_index, page_row, system_config, page_list, menu_list, template_config, i18n, static_file_dict) if result is None: abort(404) write_index_cache(page_url, result) console.log("Success", "Get success: {0}".format(page_url)) return result
def upgrade_check(fetch=True): if not os.path.exists("./.git"): if fetch: console.log("Error", "Not a git repository.") return False repo, remote = git_init() if fetch: remote.fetch(repo.active_branch) try: if repo.rev_parse("HEAD") != repo.rev_parse("FETCH_HEAD"): return True except: pass if current_data_version != new_data_version: return True return False
def post_route(file_name=None): if file_name is None or not os.path.exists( "./document/{0}.md".format(file_name)): abort(404) page_url = "/post/{0}/".format(file_name) result = get_post_cache(page_url) if result is None: page_info = None if file_name in page_name_list: this_page_index = page_name_list.index(file_name) page_info = page_list[this_page_index] result = page.build_page(file_name, system_config, page_info, menu_list, template_config, i18n, static_file_dict) write_post_cache(page_url, result) console.log("Success", "Get success: {0}".format(page_url)) return result
def article_manager(): from manage import build_rss, post_manage while True: dialog.title = "Article manager" menu_list = [ "New", "Update", "Edit", "Delete", "=" * 25, "Back", "Exit" ] result = dialog.menu("Please select an action", menu_list) if result == "Exit": exit(0) if result == "Back": break if result == "New": dialog.title = "New post" post_info = get_post_info() if os.path.exists("./document/{}.md".format(post_info["name"])): console.log( "Error", "File [./document/{}.md] already exists".format( post_info["name"])) exit(1) if post_info["name"] is not None: post_manage.new_post( post_info, dialog.confirm("Is this an independent page?", "no")) if result == "Edit": dialog.title = "Edit post" page_list, post_index = select_list("./config/page.json") if page_list: config = get_post_info(page_list[post_index]["title"], page_list[post_index]["name"], page_list[post_index]["time"]) system_info = json.loads( file.read_file("./config/system.json")) post_manage.edit_post(page_list, post_index, config, system_info["Editor"]) post_manage.update_post() if result == "Delete": page_list, post_index = select_list("./config/page.json") if page_list and dialog.confirm( "Are you sure you want to delete this article?", "no"): post_manage.delete_post(page_list, post_index) if result == "Update": post_manage.update_post() build_rss.build_rss() time.sleep(0.5)
def upgrade_check(fetch=True): if not check_is_git(): if fetch: console.log("Error", "Not a git repository.") exit(1) return False repo = git.Repo("./") remote = repo.remote() if fetch: remote.fetch(repo.active_branch) try: if repo.rev_parse("HEAD") != repo.rev_parse("FETCH_HEAD"): return True except git.BadObject: pass if current_data_version != new_data_version: return True return False
def install_theme(theme_name, custom): import git if not os.path.exists("./templates/static"): os.mkdir("./templates/static") repo_dir = "./templates/{}".format(theme_name) if os.path.exists(repo_dir): console.log("Error", "This theme has been installed.") exit(1) console.log("Info", "Get the theme repository...") git_repo = "https://github.com/silverblog-theme/{}.git".format(theme_name) if custom: git_repo = theme_name try: git.Repo.clone_from(url=git_repo, to_path=repo_dir, depth=1) except git.exc.GitCommandError: console.log("Error", "Unable to clone theme repository.") exit(1) if os.path.exists("{}/package-metadata.json".format(repo_dir)): config_example_file = "{}/config.example.json".format(repo_dir) static_symlink = "./templates/static/{}".format(theme_name) if not os.path.exists(static_symlink): os.symlink( "{}/templates/{}/static".format(os.getcwd(), theme_name), static_symlink) if os.path.exists(config_example_file): shutil.copyfile(config_example_file, "{}/config.json".format(repo_dir)) download_static_file(theme_name) if not os.path.exists( "{}/package-metadata.json".format(repo_dir)) and os.path.exists( "{}/install.sh".format(repo_dir)): result_code = os.system( "cd templates && bash {}/install.sh".format(theme_name)) if (result_code >> 8) != 0: console.log( "Error", "An error occurred while executing the install script.") exit(1) console.log("Success", "The theme is install successfully!")
def edit(page_list, post_index, config, editor=None, is_menu=False): if page_list[post_index]["name"] is not config["name"]: safe_name = get.filter_name(config["name"]) shutil.move("./document/{}.md".format(page_list[post_index]["name"]), "./document/{}.md".format(safe_name)) if os.path.exists("./document/{}.json".format(page_list[post_index]["name"])): shutil.move("./document/{}.json".format(page_list[post_index]["name"]), "./document/{}.json".format(safe_name)) config_file = json.loads(file.read_file("./document/{}.json".format(safe_name))) config_file["title"] = config["title"] file.write_file("./document/{}.json".format(safe_name), json.dumps(config_file, indent=4, sort_keys=False, ensure_ascii=False)) page_list[post_index]["name"] = safe_name if editor is not None: os.system("{0} ./document/{1}.md".format(editor, safe_name)) page_list[post_index]["title"] = config["title"] file_url = "./config/page.json" if is_menu: file_url = "./config/menu.json" file.write_file(file_url, json.dumps(page_list, indent=4, sort_keys=False, ensure_ascii=False)) console.log("Success", "Edit a new article successfully!")
def update(): global page_list, page_list_file page_list_file = json.loads(file.read_file("./config/page.json")) if len(page_list_file) == 0: console.log("Error", "The page list can not be blank.") return False page_list = page_list_file for item in page_list_file: processing_file = "./document/{0}.md".format(item["name"]) file_exists = os.path.exists(processing_file) if not file_exists: console.log("Remove", "Removing from list: {0}".format(processing_file)) del page_list[item] loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) tasks = [build_excerpt(item) for item in page_list] loop.run_until_complete(asyncio.wait(tasks)) loop.close() file.write_file( "./config/page.json", json.dumps(page_list, ensure_ascii=False, indent=4, sort_keys=False)) console.log("Success", "Update article metadata is successful!") return True
def use_whiptail_mode(): dialog.title = "SilverBlog management tool" menu_list = ["Article manager", "Menu manager", "Build static page", "Setting", "=========================", "Exit"] upgrade_text = None if os.path.exists("./.git"): upgrade_text = "Upgrade" upgrade_check = False last_fetch_time = 0 if os.path.exists("./upgrade/last_fetch_time.json"): last_fetch_time = json.loads(file.read_file("./upgrade/last_fetch_time.json"))["last_fetch_time"] if upgrade.upgrade_check(False): upgrade_text = "⚠ Upgrade" upgrade_check = True if (time.time() - last_fetch_time) > 259200 and not upgrade_check: console.log("Info", "Checking for updates...") file.write_file("./upgrade/last_fetch_time.json", json.dumps({"last_fetch_time": time.time()})) if upgrade.upgrade_check(): upgrade_text = "⚠ Upgrade" menu_list = ["Article manager", "Menu manager", "Build static page", upgrade_text, "Setting", "=========================", "Exit"] while True: result = dialog.menu("Please select an action", menu_list) if result == "Exit": exit(0) if result == "Article manager": article_manager() if result == "Menu manager": menu_manager() if upgrade_text is not None: if result == upgrade_text: upgrade_system() if result == "Build static page": from manage import build_static_page dialog.title = "Build static page" build_static_page.publish() time.sleep(0.5) if result == "Setting": from manage import setting setting.setting_menu()