diff --git a/vreader/api/common.py b/vreader/api/common.py index 9eb8768..9ba438a 100644 --- a/vreader/api/common.py +++ b/vreader/api/common.py @@ -25,20 +25,13 @@ def main_entry(): # Get Files directory = str(Config.DATA_PATH) all_files = os.listdir(directory) + + # Sort Files markdown_files = [file for file in all_files if file.endswith(".md")] + markdown_files = sorted(markdown_files, reverse=True) - # Get Create Time - file_info_list = [] - for filename in markdown_files: - file_path = os.path.join(directory, filename) - creation_time = os.path.getctime(file_path) - file_info_list.append((filename, creation_time)) - - # Sort Create Time (Recent First) - file_info_list.sort(key=lambda x: x[1], reverse=True) - - # Get Articles - articles = [parse_filename(item[0]) for item in file_info_list] + # Get Article Metadata + articles = [get_article_metadata(filename, directory) for filename in markdown_files] return make_response(render_template("index.html", articles=articles)) @@ -51,7 +44,7 @@ def article_item(id): render_template("error.html", status=404, message="Invalid Article") ), 404 - metadata = get_article_metadata(id) + metadata = find_article(id) if not metadata: return make_response( render_template("error.html", status=404, message="Invalid Article") @@ -72,23 +65,23 @@ def article_item(id): ), 404 -def get_article_metadata(id): +def find_article(id): directory = str(Config.DATA_PATH) files = os.listdir(directory) - for file_name in files: - if file_name.startswith(id) and file_name.endswith(".md"): - file_path = os.path.join(directory, file_name) - metadata = parse_filename(file_name) - metadata["filepath"] = file_path - return metadata - return None + + # Find Filename + filename = next((x for x in files if x[15:26] == id and x.endswith(".md")), None) + if filename is None: + return None + + # Normalize File Info + return get_article_metadata(filename, directory) -def parse_filename(filename): - video_id = filename[:11] - title = filename[12:][:-3] - +def get_article_metadata(filename, directory): return { - "video_id": video_id, - "title": title + "date": filename[:14], + "video_id": filename[15:26], + "title": filename[27:][:-3], + "filepath": os.path.join(directory, filename) } diff --git a/vreader/api/v1.py b/vreader/api/v1.py index 025341e..9de733d 100644 --- a/vreader/api/v1.py +++ b/vreader/api/v1.py @@ -1,4 +1,5 @@ import os +from datetime import datetime from os import path from flask import Blueprint, request from vreader.config import Config @@ -21,7 +22,7 @@ def generate(): if len(video) != 11: return {"error": "Invalid VideoID"} - metadata = get_article_metadata(video) + metadata = find_article(video) if metadata is not None: return {"video": video} @@ -35,36 +36,37 @@ def generate(): directory = str(Config.DATA_PATH) title = resp.get("title") content = resp.get("content") + date = datetime.strftime(datetime.utcnow(), "%Y%m%d%H%M%S") # Derive Filename - new_title = f"{video}_{title}" - file_path = path.join(directory, f"{new_title}.md") + new_title = f"{date}_{video}_{title}" + filepath = path.join(directory, f"{new_title}.md") # Write File - file = open(file_path, 'w', encoding='utf-8') + file = open(filepath, 'w', encoding='utf-8') file.write(content) file.close() return { "title": resp["title"] } -def get_article_metadata(id): +def find_article(id): directory = str(Config.DATA_PATH) files = os.listdir(directory) - for file_name in files: - if file_name.startswith(id) and file_name.endswith(".md"): - file_path = os.path.join(directory, file_name) - metadata = parse_filename(file_name) - metadata["filepath"] = file_path - return metadata - return None + + # Find Filename + filename = next((x for x in files if x[15:26] == id and x.endswith(".md")), None) + if filename is None: + return None + + # Normalize File Info + return get_article_metadata(filename, directory) -def parse_filename(filename): - video_id = filename[:11] - title = filename[12:][:-3] - +def get_article_metadata(filename, directory): return { - "video_id": video_id, - "title": title + "date": filename[:14], + "video_id": filename[15:26], + "title": filename[27:][:-3], + "filepath": os.path.join(directory, filename) } diff --git a/vreader/oai.py b/vreader/oai.py index 9bd86a0..8f50674 100644 --- a/vreader/oai.py +++ b/vreader/oai.py @@ -5,7 +5,7 @@ import json import openai PROMPT_TEMPLATE = """ -The following is a video transcription. Write a fully comprehensive article in markdown appropriately utilizing subsections. Be sure to only use the following transcription to write the article: +The following is a video transcription. Write a fully comprehensive article in markdown appropriately utilizing subsections. Do not reference the video. Be sure to only use the following transcription to write the article: {context} """ diff --git a/vreader/static/style.css b/vreader/static/style.css index e4204d1..6a6edf9 100644 --- a/vreader/static/style.css +++ b/vreader/static/style.css @@ -15,10 +15,11 @@ html { main { height: calc(100dvh - 4rem - env(safe-area-inset-top)); + overflow: hidden; } #container { - padding-bottom: calc(5em + env(safe-area-inset-bottom) * 2); + padding-bottom: calc(5.5em + env(safe-area-inset-bottom) * 2); } /* No Scrollbar - IE, Edge, Firefox */ diff --git a/vreader/static/tailwind.css b/vreader/static/tailwind.css index 0d176c2..758c2b5 100644 --- a/vreader/static/tailwind.css +++ b/vreader/static/tailwind.css @@ -1 +1 @@ -/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.relative{position:relative}.mx-auto{margin-left:auto;margin-right:auto}.mb-0{margin-bottom:0}.mb-0\.5{margin-bottom:.125rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.mr-6{margin-right:1.5rem}.mt-3{margin-top:.75rem}.flex{display:flex}.h-10{height:2.5rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-32{height:8rem}.h-\[100dvh\]{height:100dvh}.h-screen{height:100vh}.w-11\/12{width:91.666667%}.w-full{width:100%}.w-screen{width:100vw}.max-w-screen-sm{max-width:640px}.max-w-screen-xl{max-width:1280px}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.border-primary{border-color:var(--color-primary)}.bg-primary{background-color:var(--color-primary)}.bg-secondary{background-color:var(--color-secondary)}.bg-tertiary{background-color:var(--color-tertiary)}.p-2{padding:.5rem}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-5{padding-bottom:1.25rem}.text-center{text-align:center}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-7xl{font-size:4.5rem;line-height:1}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.tracking-tight{letter-spacing:-.025em}.text-ptext{color:var(--color-primary-text)}.text-stext{color:var(--color-secondary-text)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.hover\:bg-primary:hover{background-color:var(--color-primary)}.hover\:bg-tertiary:hover{background-color:var(--color-tertiary)}@media (min-width:768px){.md\:w-5\/6{width:83.333333%}.md\:px-6{padding-left:1.5rem;padding-right:1.5rem}.md\:text-4xl{font-size:2.25rem;line-height:2.5rem}}@media (min-width:1024px){.lg\:w-4\/6{width:66.666667%}.lg\:px-6{padding-left:1.5rem;padding-right:1.5rem}.lg\:py-16{padding-top:4rem;padding-bottom:4rem}.lg\:text-9xl{font-size:8rem;line-height:1}} \ No newline at end of file +/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.relative{position:relative}.mx-auto{margin-left:auto;margin-right:auto}.my-3{margin-top:.75rem;margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-8{margin-bottom:2rem}.mr-6{margin-right:1.5rem}.mt-3{margin-top:.75rem}.flex{display:flex}.h-10{height:2.5rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-32{height:8rem}.h-\[100dvh\]{height:100dvh}.h-full{height:100%}.h-screen{height:100vh}.w-11\/12{width:91.666667%}.w-full{width:100%}.w-screen{width:100vw}.max-w-screen-sm{max-width:640px}.max-w-screen-xl{max-width:1280px}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.border-2{border-width:2px}.border-primary{border-color:var(--color-primary)}.bg-primary{background-color:var(--color-primary)}.bg-secondary{background-color:var(--color-secondary)}.bg-tertiary{background-color:var(--color-tertiary)}.p-2{padding:.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pt-6{padding-top:1.5rem}.text-center{text-align:center}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-7xl{font-size:4.5rem;line-height:1}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.italic{font-style:italic}.tracking-tight{letter-spacing:-.025em}.text-ptext{color:var(--color-primary-text)}.text-stext{color:var(--color-secondary-text)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.hover\:bg-primary:hover{background-color:var(--color-primary)}.hover\:bg-tertiary:hover{background-color:var(--color-tertiary)}@media (min-width:768px){.md\:w-5\/6{width:83.333333%}.md\:px-6{padding-left:1.5rem;padding-right:1.5rem}.md\:text-4xl{font-size:2.25rem;line-height:2.5rem}}@media (min-width:1024px){.lg\:w-4\/6{width:66.666667%}.lg\:px-6{padding-left:1.5rem;padding-right:1.5rem}.lg\:py-16{padding-top:4rem;padding-bottom:4rem}.lg\:text-9xl{font-size:8rem;line-height:1}} \ No newline at end of file diff --git a/vreader/templates/article.html b/vreader/templates/article.html index 03009c7..ac6d340 100644 --- a/vreader/templates/article.html +++ b/vreader/templates/article.html @@ -1,5 +1,5 @@ - +
@@ -32,7 +32,7 @@ - +