def delete_local_html_of_book(source_folder_path): build_folder_path = os.path.join(source_folder_path, "_build") logger.info(f"Build Folder: {build_folder_path}") if os.path.exists(build_folder_path): logger.info( f"Removing old version of build folder: {build_folder_path}") shutil.rmtree(build_folder_path)
def gen_jupyter_book(source_folder_path, cwd=None): cmd_string = f"jupyter-book build {source_folder_path}" result = subprocess.run(cmd_string, shell=True, cwd=cwd) st_code = result.returncode logger.info(f"jupyter-book build STATUS CODE = {st_code}") if st_code != OK_CODE: print("Error in creating Jupyter Book.") exit(1)
def upload_to_aws_s3(s3, local_file_path, bucket, s3_file_key): try: s3.upload_file(local_file_path, bucket, s3_file_key, ExtraArgs={"ACL": "public-read"}) logger.info(f"{local_file_path}: Upload Successful") return True except Exception as e: logger.error(f"{local_file_path}: Some Error occured uploading. \n", e, "\n") return False
def cli(ctx, debug, source_dir, destination_dir, config_file): # click.echo(f"Debug mode is {'on' if debug else 'off'}") logger.info(f"Source dir is: {source_dir}") logger.info(f"Destination dir is: {destination_dir}") ctx.ensure_object(dict) ctx.obj["debug"] = debug ctx.obj["source_dir"] = os.path.abspath(source_dir) ctx.obj["destination_dir"] = os.path.abspath(destination_dir) if os.path.exists(config_file): ctx.obj["config_file"] = os.path.abspath(config_file) else: ctx.obj["config_file"] = None click.echo(pprint(ctx.obj))
def read_toc_yaml(yaml_file): logger.info(f"Reading TOC yaml file: {yaml_file}") toc_dict = {} # tie yaml read in try+except to return empty if there is an error. try: with open(yaml_file, "r") as f: toc_dict = yaml.load(f, Loader=yaml.FullLoader) logger.debug(f"TOC dict: {toc_dict}") except Exception as e: logger.exception( f"Exception occured while reading TOC yaml file: {yaml_file}\n Exception: {e}" ) exit(1) return toc_dict
def setup_section_on_zendesk(hc, section_name, zendesk_category_id): data_dict = { "section": { "position": 0, "locale": "en-us", "name": section_name } } try: resp = hc.create_section(zendesk_category_id, json.dumps(data_dict), locale="en-us") logger.info(f"Created new section on Zendesk:\n {resp}") return resp except: logger.error( f"Error in creating section_name: {section_name} on Zendesk") return NOT_FOUND
def handle_sections_on_zendesk(hc, html_files_list, zendesk_category_id): # will check if all sections exist on Zendesk in the category # if not, will create the section on Zendesk # will update sections_resp = hc.list_all_sections() html_files_for_zendesk = [] for item in html_files_list: section_name = item["section_name"] section_id = find_section_name_in_list(section_name, sections_resp, zendesk_category_id) if section_id == NOT_FOUND: # set up section on zendesk section_resp = setup_section_on_zendesk(hc, section_name, zendesk_category_id) if section_resp == NOT_FOUND: logger.error( f"Could not create section name: {section_name} on Zendesk. Please check, cleanup and retry" ) exit(1) else: # logger.info(sections_resp) logger.info("Here is 1 section") # logger.info(cpprint(section_resp)) try: sections_resp["sections"].append(section_resp["section"]) section_id = section_resp["section"]["id"] except Exception as e: logger.warn("Exception adding section id") logger.exception(e) html_files_for_zendesk.append({ "section_name": item["section_name"], "section_id": section_id, "html_file_path": item["html_file_path"], }) return html_files_for_zendesk
def archive_book_from_zendesk(hc, zendesk_json_pre, zendesk_file_path): articles = zendesk_json_pre["articles"] if len(articles) < 1: logger.info("No articles found in the zendesk.json file to Archive") return for article in articles: article_id = article["article_id"] html_file_path = article["html_file_path"] logger.info( f"Archiving: {html_file_path} at Zendesk, Article ID:{article_id}") resp = hc.archive_article(article_id, locale="en-us") status_code = resp["status_code"] if status_code == 204: logger.info(f"{article_id} Successfully Archived") else: logger.warning( f"Error occured in Archiving: {article_id}. HTTP Code = {status_code}" ) open(zendesk_file_path, "w").close() # will rewrite zendesk.json to zero bytes logger.info( f"Book archived at Zendesk. You can delete it manually from the Admin UI" )
def check_category_on_zendesk(hc, zendesk_category_name): # check if category exists on zendesk. If not create it. logger.info(f"Category Name: {zendesk_category_name}") zendesk_categories = hc.list_all_categories() for cat in zendesk_categories["categories"]: if zendesk_category_name == cat["name"]: logger.info(f"Category_ID: {cat['id']}") return cat["id"] data_dict = { "category": { "position": 0, "locale": "en-us", "name": zendesk_category_name, } } try: resp = hc.create_category(json.dumps(data_dict)) logger.info(f"Created new Category on Zendesk:\n {resp}") return resp["id"] except: logger.error( f"Error in creating Category: {zendesk_category_name} on Zendesk") return NOT_FOUND
def command_sync(ctx, archive, draft, public): ctx.obj["archive_flag"] = archive ctx.obj["draft"] = draft ctx.obj["public"] = public logger.info("Syncing the Jupyterbook to ZenDesk") sync_to_zendesk.sync(ctx)
def command_build(ctx): """Console script for jupyterbook_to_zendesk.""" logger.info("Building the jupyterbook") build_jupyterbook.build(ctx)
def sync(ctx): """Sync the jupyterbook to zendesk""" # 0. Initialize Zendesk router & S3 App = md.Config(ctx.obj["config_file"]) hc = md.HelpCenter(App.get("url"), App.get("username"), App.get("token")) try: hc.get_me() except Exception as e: logger.warn("Error authenticating as the ZenDesk User") logger.exception(e) exit(1) logger.info("Init s3 configuration") try: s3 = boto3.client( "s3", aws_access_key_id=App.get("aws_access_key"), aws_secret_access_key=App.get("aws_secret"), ) except Exception as e: logger.warn("Error calling boto3.client") logger.exception(e) exit(1) # TODO add check that s3 bucket exists aws_s3_bucket = App.get("aws_s3_bucket") # check if user exists on Zendesk and can do something on it. md.check_user_on_zendesk(hc) # load any previous zendesk activity on this source folder zendesk_file_path = os.path.join(ctx.obj["destination_dir"], md.ZENDESK_FILE) category_id = md.check_category_on_zendesk( hc=hc, zendesk_category_name=App.get("zendesk_category_name")) zendesk_json_pre = hc.list_articles_by_category(category_id=category_id) if ctx.obj["archive_flag"]: # archive the book on Zendesk and exit OK. md.archive_book_from_zendesk(hc, zendesk_json_pre, zendesk_file_path) md.delete_local_html_of_book(ctx.obj["destination_dir"]) exit(0) aws_s3_bucket = App.get("aws_s3_bucket") try: html_files_for_zendesk = md.gen_list_of_sections_and_html_files( source_folder_path=ctx.obj["source_dir"]) except Exception as e: logger.warn("Error creating html files for zendesk") logger.exception(e) exit(1) html_files_for_zendesk = md.handle_sections_on_zendesk( hc=hc, html_files_list=html_files_for_zendesk, zendesk_category_id=category_id) zendesk_json_pre = hc.list_articles_by_category(category_id=category_id) # now we iterate over list of files for f in html_files_for_zendesk: logger.info(f"Processing: {f}") article_dict = md.update_article_dict(f["html_file_path"], s3, aws_s3_bucket) section_id = f["section_id"] # article exists on zendesk # if article with same title and section_id is found # then article exists logger.info("Checking to see if article exists") article_info = md.article_exists( articles=zendesk_json_pre, title=article_dict["article"]["title"], section_id=section_id, ) logger.info(f"Article Exists: {cpprint(article_info)}") if ctx.obj["public"]: article_dict["article"]["user_segment_id"] = None if not article_info: logger.info("Creating the article") response_json = hc.create_article(section_id, json.dumps(article_dict)) article_id = response_json["article"]["id"] f.update({"article_id": article_id}) article_html_url = response_json["article"]["html_url"] f.update({"article_html_url": article_html_url}) md.logger.info( f"Article ID: {article_id}, Article URL: {article_html_url}") else: # update_article logger.info("Updating the article") article_id = article_info["id"] article_html_url = article_info["html_url"] translation_dict = { "article": { "user_segment_id": article_dict["article"]["user_segment_id"] }, "translation": { "title": article_dict["article"]["title"], "body": article_dict["article"]["body"], }, } response_json = hc.update_article_metadata( article_id=article_id, data=json.dumps(article_dict["article"]), locale="en-us", ) f.update({"article_id": article_id}) f.update({"article_html_url": article_html_url}) # 2nd pass to fix URLs for f in html_files_for_zendesk: logging.info(f"Processing (2nd Pass): {f}") article_dict = md.update_urls_in_article_dict( f["html_file_path"], html_files_for_zendesk, ) draft = ctx.obj["draft"] article_dict["article"]["draft"] = draft if ctx.obj["public"]: article_dict["article"]["user_segment_id"] = None translation_dict = { "translation": { "title": article_dict["article"]["title"], "body": article_dict["article"]["body"], "draft": article_dict["article"]["draft"], } } logging.info("Syncing the jupyterbook to zendesk...") response_json = hc.update_article_metadata( article_id=article_id, data=json.dumps(article_dict["article"]), locale="en-us", ) logging.info("Updating article visibility") logging.debug(cpprint(response_json)) response_json = hc.update_article_translation( f["article_id"], json.dumps(translation_dict), locale="en-us") # get useful output del response_json["translation"]["body"] logging.debug(cpprint(response_json)) # add the rest of the sync commands here return 0