<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: David</title>
    <description>The latest articles on Forem by David (@rjsgml).</description>
    <link>https://forem.com/rjsgml</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1155279%2Fe4cf3414-269b-45f9-bfec-3a884a1f8ea1.jpeg</url>
      <title>Forem: David</title>
      <link>https://forem.com/rjsgml</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rjsgml"/>
    <language>en</language>
    <item>
      <title>NFC Board</title>
      <dc:creator>David</dc:creator>
      <pubDate>Thu, 23 Nov 2023 23:00:23 +0000</pubDate>
      <link>https://forem.com/rjsgml/nfc-board-5758</link>
      <guid>https://forem.com/rjsgml/nfc-board-5758</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Starters 🏁&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Welcome back to new series, where I will be going through the development process of a software project conducted by me and my friend. I will post weekly updates on progress, milestones, road blocks, and code review. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What is NFC Board? 🎯&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The inspiration behind NFC board revolves around the innovative use of Near Field Communication (NFC) tags for automating and streamlining data collection and processing tasks. &lt;/p&gt;

&lt;p&gt;Our goal is to develop a dashboard system where NFC tags can be easily initialized and managed for modular design. All the users have to do is set up the dashboard for stat tracking through simply user interface. This approach aims to enhance the user experience by simplifying interactions with the NFC tags.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Our Tech Stack 💻&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Frontend:

&lt;ul&gt;
&lt;li&gt;React, Redux, Next.js (Vercel Later)&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Routing handled by Next.js&lt;/li&gt;
&lt;li&gt;Tailwind&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Backend:

&lt;ul&gt;
&lt;li&gt;Express, Node, Mongo&lt;/li&gt;
&lt;li&gt;Modularly working for now — can add further features later on such as saving user for future access and stat tracking etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Things to consider (for further iterations)

&lt;ul&gt;
&lt;li&gt;JEST (React Testing Library)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Conclusion ⛳️&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thank you for taking the time to read and I would appreciate any suggestions to improve the quality of my blog. Stay tuned for upcoming progress posts on the NFC Board Series. 🤠&lt;/p&gt;

</description>
      <category>programming</category>
      <category>nextjs</category>
      <category>coding</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Video Content Aggregator - MoviePy 🎬</title>
      <dc:creator>David</dc:creator>
      <pubDate>Mon, 02 Oct 2023 08:37:48 +0000</pubDate>
      <link>https://forem.com/rjsgml/video-content-aggregator-moviepy-2b27</link>
      <guid>https://forem.com/rjsgml/video-content-aggregator-moviepy-2b27</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Starters 🏁&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Welcome back to another installment of the "Project" series, where I delve into the technical components of the projects I've undertaken. I apologize for the delays in my posts; the past few weeks have been hectic with school, co-op applications, and just life (haha). &lt;br&gt;
This week, I'll discuss a personal project I made using MoviePy, the YouTube API, and the OpenAI API. If you're unfamiliar with me, please refer to my introductory post. 👇&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/rjsgml" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1155279%2Fe4cf3414-269b-45f9-bfec-3a884a1f8ea1.jpeg" alt="rjsgml"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/rjsgml/pilot-start-of-my-blog-journey-2b04" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Pilot - Start of my blog journey 🛫&lt;/h2&gt;
      &lt;h3&gt;David ・ Sep 7 '23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#computerscience&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#pilot&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#career&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Project Overview (Video Content Aggregator) 🙆&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a personal project, I worked on a tool called the "Video Content Aggregator". This tool, combining the YouTube API, OpenAI API, and MoviePy, aids in the creation of dynamic video content in the form of YouTube Shorts. I leaned on a mix of contemporary APIs and MoviePy to ensure the tool's functionality and reliability. Here's a quick overview of the technologies used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APIs: YouTube, OpenAI, Pexels&lt;/li&gt;
&lt;li&gt;Language: Python&lt;/li&gt;
&lt;li&gt;Video Editing: MoviePy&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Code review 🔍&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
  Requirements ✔️
  &lt;p&gt;The code utilizes several libraries including moviepy, google-api-python-client, openai, gtts, etc. You should ensure that you have these libraries installed, along with their dependencies.&lt;br&gt;
Ensure you have the right API keys and the environment variables are set correctly.&lt;br&gt;
Ensure you have ffmpeg installed as it's a prerequisite for moviepy.&lt;br&gt;
You can check the entire list of requirements at &lt;code&gt;requirements.txt&lt;/code&gt;.&lt;/p&gt;



&lt;/p&gt;

&lt;p&gt;
  OpenAI API 🤖
  &lt;p&gt;The code interacts with the OpenAI API to generate a fact, a title based on the fact, and a main subject noun based on the fact.&lt;br&gt;
These are three distinct interactions with the API: Fact, Title, and Subject noun, which are important components in fetching video data, aggregation, generation, and upload to YouTube.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_fact&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Give me around 75 words based on an interesting fact.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Completion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text-davinci-003&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Based on the generated fact, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, return a short title for the video.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Completion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text-davinci-003&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;video_title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;video_title&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_subject_noun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Based on the generated fact, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, return a main subject noun.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Completion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text-davinci-003&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;p&gt;
  Fetch Video API Calls 🎥
  &lt;p&gt;The code fetches videos from two sources: Pexels and YouTube.&lt;br&gt;
Each fetch function returns up to three videos based on a keyword derived from the generated fact. The keyword is sourced from the &lt;code&gt;generate_subject_noun(fact)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_fetch_pexels_videos&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;videos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch_pexels_videos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed to fetch videos from Pexels&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_fetch_youtube_videos&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;videos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch_youtube_videos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed to fetch videos from YouTube&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;p&gt;
  Aggregate and Generate Videos 🎬
  &lt;p&gt;The code processes the fetched videos and compiles them, adding subtitles and adjusting their lengths. The videos are resized and cropped.&lt;br&gt;
Audio from Google TTS is used as the background for the video.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_tts_audio_clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;gTTS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;en&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tld&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;com.au&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;slow&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;audio_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BytesIO&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;tts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_to_fp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio_bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;audio_bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;temp_audio_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OUTPUT_FOLDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temp_audio.mp3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_audio_filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio_bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;audio_clip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AudioFileClip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temp_audio_filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;audio_clip&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_youtube_videos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;youtube_videos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;audio_clip_duration&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;video_clips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;target_duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;audio_clip_duration&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;video_info&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;youtube_videos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;video_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video_info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;videoId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;video_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;youtube_video_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.youtube.com/watch?v=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;yt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;YouTube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;youtube_video_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;video_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;streams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;progressive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_extension&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;order_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resolution&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;desc&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;video_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;OUTPUT_FOLDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;youtube_video_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;video_stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OUTPUT_FOLDER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                  &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;video_filename&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;video_clip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;VideoFileClip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;video_filename&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subclip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;video_clip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;target_duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;loop_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_duration&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;video_clip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
                &lt;span class="n"&gt;video_clip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;concatenate_videoclips&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;video_clip&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;loop_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;video_clip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;video_clip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;video_clips&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;video_clip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;video_clips&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_subtitles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;final_video_duration&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;fact_parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;textwrap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;subs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;interval_duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.95&lt;/span&gt;
    &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fact_parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;end_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;interval_duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;final_video_duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end_time&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;end_time&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subs&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;annotate_video_with_subtitles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subtitles&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;txt_color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;white&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fontsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Xolonium-Bold&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;txtclip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TextClip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fontsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;fontsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;txt_color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bg_color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;black&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;set_duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;txtclip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;txtclip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_position&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;center&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;center&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;set_duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cvc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CompositeVideoClip&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;txtclip&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cvc&lt;/span&gt;

    &lt;span class="n"&gt;annotated_clips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;annotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subclip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;to_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from_t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_t&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;txt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;subtitles&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;concatenate_videoclips&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;annotated_clips&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;p&gt;
  Upload to YouTube 🍿
  &lt;p&gt;The code uses YouTube's v3 API to authenticate and upload videos.&lt;br&gt;
The video is uploaded with a title derived from the filename and a pre-defined description.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate_youtube&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OAUTHLIB_INSECURE_TRANSPORT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;flow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;google_auth_oauthlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InstalledAppFlow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_client_secrets_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;CLIENT_SECRETS_FILE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OAUTH_SCOPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;credentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_local_server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;youtube&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;googleapiclient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;discovery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;API_SERVICE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;API_VERSION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;youtube&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;upload_video_to_youtube&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;youtube&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;youtube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;videos&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;part&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;snippet,status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;snippet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;categoryId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;22&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;privacyStatus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;private&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;selfDeclaredMadeForKids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;publishAt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2023-08-24T00:00:00.0Z&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;media_body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;MediaFileUpload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mimetype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;video/mp4&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resumable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;p&gt;
  Considerations 🧐
  &lt;p&gt;I should prioritize restructuring the current linear code to be more modular, breaking tasks down into smaller functions. Handling potential errors is essential, especially in cases where video fetching might yield no results or if there's an unexpected response from the OpenAI API. It's also crucial to manage rate limits and any potential hiccups when interfacing with third-party APIs. Given the concurrent nature of the video processing, I must ensure all resources, like video clips, are appropriately closed after use. Lastly, implementing error handling mechanisms, particularly try-except blocks, in the critical sections will be essential to maintain the stability of the program.&lt;/p&gt;



&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Conclusion ⛳️&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thank you for taking the time to read and I would appreciate any suggestions to improve the quality of my blog. Stay tuned for future posts. 🤠&lt;br&gt;
Check out the &lt;a href="https://www.youtube.com/@QuickUniqueFacts" rel="noopener noreferrer"&gt;YouTube channel&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Check out the project embedded repository below! 👇&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/gdcho" rel="noopener noreferrer"&gt;
        gdcho
      &lt;/a&gt; / &lt;a href="https://github.com/gdcho/vc_aggregator" rel="noopener noreferrer"&gt;
        vc_aggregator
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Generate engaging video content utilizing the YouTube API, OpenAI API, and MoviePy. Harness the power of AI and Python automation to craft dynamic YouTube Shorts  🎬
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;

  Table of Contents
  &lt;ol&gt;
    &lt;li&gt;
      &lt;a href="https://github.com/gdcho/vc_aggregator#technology-used" rel="noopener noreferrer"&gt;Technology used&lt;/a&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/gdcho/vc_aggregator#getting-started" rel="noopener noreferrer"&gt;Getting started&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/gdcho/vc_aggregator#file-contents-of-folder" rel="noopener noreferrer"&gt;File Contents of folder&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/gdcho/vc_aggregator#learn-more" rel="noopener noreferrer"&gt;Learn More&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/gdcho/vc_aggregator#references" rel="noopener noreferrer"&gt;References&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;

&lt;br&gt;
&lt;div&gt;
  &lt;a href="https://github.com/gdcho/vc_aggregator" rel="noopener noreferrer"&gt;
    &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fgdcho%2Fvc_aggregator%2Fimg%2Fvca.png" alt="Logo" width="300" height="300"&gt;
  &lt;/a&gt;
  &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Video Content Aggregator&lt;/h3&gt;
&lt;/div&gt;


&lt;p&gt;&lt;br&gt;
    Video Content Generator with YouTube API, OpenAI API, and MoviePy. Create dynamic video content with a vc aggregator&lt;br&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;a href="https://github.com/gdcho/vc_aggregator" rel="noopener noreferrer"&gt;&lt;strong&gt;Explore the docs »&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;br&gt;&lt;br&gt;&lt;br&gt;
    &lt;a href="https://www.youtube.com/@QuickUniqueFacts" rel="nofollow noopener noreferrer"&gt;View Clips&lt;/a&gt;&lt;br&gt;
    ·&lt;br&gt;
    &lt;a href="https://github.com/gdcho/vc_aggregator/issues" rel="noopener noreferrer"&gt;Report Bug&lt;/a&gt;&lt;br&gt;
    ·&lt;br&gt;
    &lt;a href="https://github.com/gdcho/vc_aggregator/issues" rel="noopener noreferrer"&gt;Request Feature&lt;/a&gt;&lt;br&gt;
  &lt;/p&gt;
&lt;br&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Technology used&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/dac4143c83db76146f684a5c10c52016b3867277781120852b95973bbb15e85e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d3337373641423f6c6f676f3d707974686f6e266c6f676f436f6c6f723d666666267374796c653d666f722d7468652d6261646765"&gt;&lt;img src="https://camo.githubusercontent.com/dac4143c83db76146f684a5c10c52016b3867277781120852b95973bbb15e85e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d3337373641423f6c6f676f3d707974686f6e266c6f676f436f6c6f723d666666267374796c653d666f722d7468652d6261646765" alt="Python Badge"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/cd2dc7f8082758c6c961f08a449054ca3a8bd1ae09c8065fedebc3fa1edc245c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4f70656e41492532304150492d3030413637453f7374796c653d666f722d7468652d6261646765266c6f676f3d6f70656e6169266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/cd2dc7f8082758c6c961f08a449054ca3a8bd1ae09c8065fedebc3fa1edc245c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4f70656e41492532304150492d3030413637453f7374796c653d666f722d7468652d6261646765266c6f676f3d6f70656e6169266c6f676f436f6c6f723d7768697465" alt="OpenAI API"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/6d7af61b38142335369eb1db9a30a0b6e6a1700b364f153e3dc0443c31f800f2/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f596f75547562652532304150492d4646303030303f7374796c653d666f722d7468652d6261646765266c6f676f3d796f7574756265266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/6d7af61b38142335369eb1db9a30a0b6e6a1700b364f153e3dc0443c31f800f2/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f596f75547562652532304150492d4646303030303f7374796c653d666f722d7468652d6261646765266c6f676f3d796f7574756265266c6f676f436f6c6f723d7768697465" alt="YouTube API"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/69f3102003c2c437ba71adfaef435ee90257b826c84fd1f4ffb0682af8fc4cbe/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506578656c2532304150492d3035413038313f7374796c653d666f722d7468652d6261646765266c6f676f3d706578656c73266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/69f3102003c2c437ba71adfaef435ee90257b826c84fd1f4ffb0682af8fc4cbe/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506578656c2532304150492d3035413038313f7374796c653d666f722d7468652d6261646765266c6f676f3d706578656c73266c6f676f436f6c6f723d7768697465" alt="Pexel API"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/1c0b807f6f029f66c345a8e9ec775753411dc51d315997328538780039dae270/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f476f6f676c65253230436c6f7564253230506c6174666f726d2d3432383546343f7374796c653d666f722d7468652d6261646765266c6f676f3d676f6f676c652d636c6f7564266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/1c0b807f6f029f66c345a8e9ec775753411dc51d315997328538780039dae270/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f476f6f676c65253230436c6f7564253230506c6174666f726d2d3432383546343f7374796c653d666f722d7468652d6261646765266c6f676f3d676f6f676c652d636c6f7564266c6f676f436f6c6f723d7768697465" alt="Google Cloud Platform"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/22880b06c699d202619779b0f86afc7c198a360752d720c64059f0b552d685d7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d6f76696550792d3030303030303f7374796c653d666f722d7468652d6261646765266c6f676f3d707974686f6e266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/22880b06c699d202619779b0f86afc7c198a360752d720c64059f0b552d685d7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d6f76696550792d3030303030303f7374796c653d666f722d7468652d6261646765266c6f676f3d707974686f6e266c6f676f436f6c6f723d7768697465" alt="MoviePy"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/34cd36b1e10338e6a8a9d014b6a2f52fede2e7f7470a75ff0d5fa708fb17fc7f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46466d7065672d3030374143433f7374796c653d666f722d7468652d6261646765266c6f676f3d66666d706567266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/34cd36b1e10338e6a8a9d014b6a2f52fede2e7f7470a75ff0d5fa708fb17fc7f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46466d7065672d3030374143433f7374796c653d666f722d7468652d6261646765266c6f676f3d66666d706567266c6f676f436f6c6f723d7768697465" alt="FFmpeg"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/fb44904727a70ab5fe093851d2f9a770d158ae6dbfb85a404ec2528512a020ca/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f476f6f676c65253230417574682d3432383546343f7374796c653d666f722d7468652d6261646765266c6f676f3d676f6f676c65266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/fb44904727a70ab5fe093851d2f9a770d158ae6dbfb85a404ec2528512a020ca/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f476f6f676c65253230417574682d3432383546343f7374796c653d666f722d7468652d6261646765266c6f676f3d676f6f676c65266c6f676f436f6c6f723d7768697465" alt="Google Auth"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Getting Started&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Clone the repo&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/gdcho/algo_v&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Obtain API keys from &lt;a href="https://developers.google.com/youtube/v3/getting-started" rel="nofollow noopener noreferrer"&gt;YouTube&lt;/a&gt;, &lt;a href="https://beta.openai.com/" rel="nofollow noopener noreferrer"&gt;OpenAI&lt;/a&gt;, and &lt;a href="https://www.pexels.com/api/new/" rel="nofollow noopener noreferrer"&gt;Pexels&lt;/a&gt; and save them in .env file&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install Python requirements&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;pip install -r requirements.txt&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Obtain OAuth Client Secret from &lt;a href="https://console.cloud.google.com/apis/credentials" rel="nofollow noopener noreferrer"&gt;Google Cloud Platform&lt;/a&gt; and create yt_client_secret.json&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the python script&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt; python3 main.py&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;File Contents of folder&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;📦
├── README.md
├── __pycache__
│   ├── aggregate_fv2.cpython-311.pyc
│   └── upload_yt.cpython-311.pyc
├── aggregate_fv2.py
├── environment_variables.py
├── img
│   ├── logo.png
│   └── vca.png
├── main.py
├── output_folder
│   └── note.txt
├── requirements.txt
├── test_api
│   ├── gpt_prompt.py
│   └── youtube_video_data.py
├── test_script
│   └── test_aggregate.py
├── upload_yt.py
└── yt_client_secret.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/gdcho/vc_aggregator" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>python</category>
      <category>api</category>
      <category>youtube</category>
      <category>ai</category>
    </item>
    <item>
      <title>COMP 2800 - Collaborative Story Telling Platform 🤖</title>
      <dc:creator>David</dc:creator>
      <pubDate>Sun, 17 Sep 2023 04:18:35 +0000</pubDate>
      <link>https://forem.com/rjsgml/comp-2800-collaborative-story-telling-platform-1epd</link>
      <guid>https://forem.com/rjsgml/comp-2800-collaborative-story-telling-platform-1epd</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Starters 🏁&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Welcome back to another series of the "Project" series, where I delve into the technical components of the projects I've undertaken. This week, I'll discuss a course project I completed for COMP 2800 at BCIT. If you're unfamiliar with me, please refer to my introductory post.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/rjsgml" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1155279%2Fe4cf3414-269b-45f9-bfec-3a884a1f8ea1.jpeg" alt="rjsgml"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/rjsgml/pilot-start-of-my-blog-journey-2b04" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Pilot - Start of my blog journey 🛫&lt;/h2&gt;
      &lt;h3&gt;David ・ Sep 7 '23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#computerscience&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#pilot&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#career&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;COMP 2800 🤖&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;COMP 2800 is a five-week-long project course for all first and second-term Computer Systems Technology (CST) students at the British Columbia Institute of Technology (BCIT). This year, the project theme was &lt;strong&gt;Impactful Intelligence - AI Powered Web Solutions&lt;/strong&gt;, challenging students to harness artificial intelligence for benevolent purposes or assistance. You can read the full project details &lt;a href="https://bcit-cst.notion.site/COMP-2800-2023-Project-Theme-and-Challenge-a5ad37d0a6dc4e9f9af6370f1531e095" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Agile scrum methodology 🔄&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For this project, we adopted the agile scrum methodology, a blend of agile philosophy and the scrum framework. "Agile" denotes an incremental approach, allowing teams to develop projects in small increments. Scrum, a specific type of agile methodology, is renowned for segmenting projects into sizable chunks known as "sprints." In essence, we employed the agile methodology through weekly sprints and daily scrum meetings.&lt;br&gt;
To learn more about the agile methodology, please refer here 👇&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/rjsgml" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1155279%2Fe4cf3414-269b-45f9-bfec-3a884a1f8ea1.jpeg" alt="rjsgml"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/rjsgml/comp-1800-a-simple-full-stack-wep-application-5b4h" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;COMP 1800 - A Simple Full-Stack Web Application 🌱&lt;/h2&gt;
      &lt;h3&gt;David ・ Sep 11 '23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Project overview 🙆&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Our team, comprising four members (including myself), chose to develop a community platform connecting writers and readers. This platform facilitates the crafting of unique stories with the assistance of the OpenAI API. We opted to use the modern technology framework, Next.js. Below, I've outlined our entire tech stack for the project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Language: JavaScript&lt;/li&gt;
&lt;li&gt;Frameworks: Next.js, Node.js, Prisma ORM&lt;/li&gt;
&lt;li&gt;Database: MongoDB&lt;/li&gt;
&lt;li&gt;Hosting: Vercel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggofkusibzzibt5rezsg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggofkusibzzibt5rezsg.png" alt="Technology &amp;amp; Framework" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Code review 🔍&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
  Backend
  &lt;ul&gt;
&lt;li&gt;Prisma ORM
Initially, we selected Prisma as the ORM for our MongoDB database.
&lt;strong&gt;What is an ORM?&lt;/strong&gt; ORM (Object-relational mapping) serves as a "bridge" between object-oriented programs and relational databases, streamlining CRUD operations. For instance, an SQL query fetching specific user information might look like:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt; &lt;span class="nv"&gt;"SELECT id, name, email, country, phone_number FROM users WHERE id = 20"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;However, using ORM, we can simplify that process, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq0gkwlt0vanwnynf3bvj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq0gkwlt0vanwnynf3bvj.png" alt="Prisma" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prisma Schema&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prisma's journey begins with its schema, where we define database models and their relationships using the Prisma schema language. One can either craft the Prisma schema from scratch or link it to an existing database. Below is an example of a user model crafted with the Prisma schema.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model User {
  id            String    @id @default(auto()) @map("_id") @db.ObjectId
  name          String?
  penName       String     @default("")
  email         String?    @unique
  emailVerified DateTime?
  image         String?
  voteBranchThreads String[] @default([])
  likeThreads   Json @default("{}")
  accounts      Account[]
  sessions      Session[]
  mainThread    MainThread[]
  branchThread  BranchThread[]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Based on the established Prisma schema, we can commence our database queries using the ORM. I'll delve deeper into this in the API routes section.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API routes (Prisma client utility functions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this project, I was tasked with backend responsibilities. This involved crafting database queries in form of utility function using the Prisma ORM and developing API route handlers for various HTTP methods. I specifically focused on the branch queries and route handlers. Below, I'll present examples of (1) returning main threads and (2) returning main threads by user id.&lt;/p&gt;

&lt;p&gt;(1) Returning main threads&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * getMainThreads
 *
 * @returns {Promise&amp;lt;{threads: any}&amp;gt;}
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getMainThreads&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;threads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mainThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;branchThread&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;threads&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;(2) Returning main threads by userId&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * getMainThreadsById
 *
 * @param {ObjectId} id
 * @returns {Promise&amp;lt;{mainThreads}&amp;gt;}
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getMainThreadsById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mainThreads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mainThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mainThreads&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As evident, the components of these two codes encompass the function signature (name, parameters, return type), functionality (e.g., findMany, include, where), and error handling. For (1) Returning main threads, it's clear that it doesn't require parameters, unlike (2) Returning main threads by userId, which necessitates the userId parameter. Additionally, the database query employs findMany, distinguishing between the 'include' option (which fetches related data) and the 'where' option (filtering based on the provided parameter).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API Route Handlers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From the utility functions created, such as createMainThread, I had to create handlers for the API route. In our repository, we organized the api routes in &lt;code&gt;pages/api&lt;/code&gt; folder. Below, I will provide an example of an api route handler using createMainThread utility function. To begin, we have to import the necessary utility function.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;createMainThread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getRandomMainThreads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getSearchMainThreads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/lib/prisma/mainThreads&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then we have to declare the request and respond of our api route which involves the HTTP method. For example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;genreParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;genre&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tagParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getMainThread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nx"&gt;searchParam&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;genreParam&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;tagParam&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;getSearchMainThreads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchParam&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;genreParam&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tagParam&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getRandomMainThreads&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;randomMainThreads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;getMainThread&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;randomMainThreads&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this code, if the request method is GET, the queries for search, genre, and tag are executed.&lt;br&gt;
&lt;code&gt;const {randomMainThreads, error} = await getMainThread;&lt;/code&gt;&lt;br&gt;
This line awaits the result of the getMainThread function, which is expected to return a Promise. It then destructures the result to extract the randomMainThreads and error properties. If any errors are present, an error message will be returned. If there are no errors, the function sends a response with a status code of 200 (OK) and a JSON body containing the randomMainThreads data.&lt;/p&gt;



&lt;/p&gt;

&lt;p&gt;
  Frontend
  &lt;p&gt;As I was mainly tasked with backend, I did not contribute much to the design in the frontend. However, there was a few that I worked on, such as the easter eggs, and the main thread renders, and OpenAI API calls.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React hooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the render react hooks, the key points are the useState, useEffect, and useCallback hooks. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;useState - useState is a hook that lets you add state management to functional components in React.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mainThread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setMainThread&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;useEffect - useEffect is a hook that lets you perform side effects in functional components. It can be thought of as componentDidMount, componentDidUpdate, and componentWillUnmount combined from class components.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mainThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phase&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;handleAIGenreGenerate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;mainThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phase&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;useCallback - useCallback is a hook that returns a memoized version of the callback function that only changes if one of the dependencies has changed. It's useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleAIGenreGenerate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contentBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mainThread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentBody&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.openai.com/v1/completions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_OPENAI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ada:ft-personal-2023-05-02-07-34-38&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;contentBody&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; \n\n###\n\n`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;API calls (OpenAI)
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleAIGenreGenerate = useCallback(async () =&amp;gt; {
    const contentBody = mainThread.contentBody;
    const endpoint = "https://api.openai.com/v1/completions";

    const options = {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${process.env.NEXT_PUBLIC_OPENAI_API_KEY}`,
      },
      body: JSON.stringify({
        model: "ada:ft-personal-2023-05-02-07-34-38",
        prompt: `${contentBody} \n\n###\n\n`,
        temperature: 0.5,
        max_tokens: 2000,
      }),
    };

    const response = await fetch(endpoint, options);

    const { choices, error } = await response.json();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Breakdown of the code above:&lt;br&gt;
&lt;strong&gt;Endpoint&lt;/strong&gt;: The function targets the &lt;a href="https://api.openai.com/v1/completions" rel="noopener noreferrer"&gt;https://api.openai.com/v1/completions&lt;/a&gt; URL, which is OpenAI's endpoint for generating completions based on a given prompt.&lt;br&gt;
&lt;strong&gt;Headers &amp;amp; Body&lt;/strong&gt;: The request method is POST. The headers specify the content type as application/json and include an authorization token from the environment variables. The body of the request contains a JSON string with several parameters.&lt;br&gt;
&lt;strong&gt;Fetching Data&lt;/strong&gt;: The function uses the fetch API to make the request to the endpoint with the specified options. Once the response is received, it is converted to JSON format.&lt;br&gt;
&lt;strong&gt;Response Handling&lt;/strong&gt;: The function extracts choices and error from the JSON response. The choices typically contain the generated text from OpenAI, while error would contain any error messages if the request failed.&lt;/p&gt;



&lt;/p&gt;

&lt;p&gt;
  Finetuning
  &lt;ul&gt;
&lt;li&gt;&lt;p&gt;Kaggle dataset&lt;br&gt;
One of the requirements for the project was to make use of a dataset. Since our application was based on story building, we decide to use book genre dataset to implement genre prediction. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OpenAI GPT&lt;br&gt;
For finetuning based on the dataset, I followed the &lt;a href="https://platform.openai.com/docs/guides/fine-tuning" rel="noopener noreferrer"&gt;documentations&lt;/a&gt;. &lt;br&gt;
The steps in fine-tuning involve:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Installation of openai using pip install&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Obtaining API key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prepare training data in JSONL format and in "prompt", "completion" format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CLI data prepartion and upload&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fine-tuning.&lt;br&gt;
For more information on finetuning, you can check out my research &lt;a href="https://github.com/MiSaengg/gunhee-RnD-space" rel="noopener noreferrer"&gt;repository&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Conclusion ⛳️&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thank you for taking the time to read and I would appreciate any suggestions to improve the quality of my blog. Stay tuned for future posts. 🤠&lt;br&gt;
Check out the project embedded repository below! 👇&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/MiSaengg" rel="noopener noreferrer"&gt;
        MiSaengg
      &lt;/a&gt; / &lt;a href="https://github.com/MiSaengg/2800-202310BBY19" rel="noopener noreferrer"&gt;
        2800-202310BBY19
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A community platform that connects writers and readers, enabling the creation of unique stories with the help of the OpenAI API  🤖 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;

  Table of Contents
  &lt;ol&gt;
    &lt;li&gt;
        &lt;a href="https://github.com/MiSaengg/2800-202310BBY19#contributors" rel="noopener noreferrer"&gt;Contributors&lt;/a&gt;
    &lt;/li&gt;
    &lt;li&gt;
      &lt;a href="https://github.com/MiSaengg/2800-202310BBY19#technology-used" rel="noopener noreferrer"&gt;Technology used&lt;/a&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/MiSaengg/2800-202310BBY19#how-did-we-use-ai" rel="noopener noreferrer"&gt;How did we use AI&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/MiSaengg/2800-202310BBY19#getting-started" rel="noopener noreferrer"&gt;Getting started&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/MiSaengg/2800-202310BBY19#file-contents-of-folder" rel="noopener noreferrer"&gt;File Contents of folder&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/MiSaengg/2800-202310BBY19#learn-more" rel="noopener noreferrer"&gt;Learn More&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/MiSaengg/2800-202310BBY19#references" rel="noopener noreferrer"&gt;References&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/MiSaengg/2800-202310BBY19#credits" rel="noopener noreferrer"&gt;Credits&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/MiSaengg/2800-202310BBY19#licence" rel="noopener noreferrer"&gt;Licence&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;

&lt;br&gt;
&lt;div&gt;
  &lt;a href="https://github.com/MiSaengg/2800-202310BBY19" rel="noopener noreferrer"&gt;
    &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F63331153%2F241055297-632c888a-0b47-49d0-b889-69714ac606b2.png" alt="Logo" width="200" height="200"&gt;
  &lt;/a&gt;
  &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Stories of Million&lt;/h3&gt;

&lt;/div&gt;


&lt;p&gt;&lt;br&gt;
    A community platform that connects writers and readers, fosters collaboration, provides feedback, and assists in creating unique stories leveraging the OpenAI API.&lt;br&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;a href="https://github.com/MiSaengg/2800-202310BBY19" rel="noopener noreferrer"&gt;&lt;strong&gt;Explore the docs »&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;br&gt;&lt;br&gt;
    &lt;a href="https://2800-202310-bby-19.vercel.app/" rel="nofollow noopener noreferrer"&gt;See Project&lt;/a&gt;&lt;br&gt;
    ·&lt;br&gt;
    &lt;a href="https://github.com/MiSaengg/2800-202310BBY19/issues" rel="noopener noreferrer"&gt;Report Bug&lt;/a&gt;&lt;br&gt;
    ·&lt;br&gt;
    &lt;a href="https://github.com/MiSaengg/2800-202310BBY19/issues" rel="noopener noreferrer"&gt;Request Feature&lt;/a&gt;&lt;br&gt;
  &lt;/p&gt;
&lt;br&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Contributors&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;br&gt;
&lt;thead&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;th&gt;Jasper&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;David&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;Noel&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;Juan&lt;/th&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/thead&gt;
&lt;br&gt;
&lt;tbody&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;_Hi, My name is Jasper, Let's do this! _&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;_Hi, my name is David, time to harness the power of AI :D _&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;_Hi, my name is Noel, We got this o2o _&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;_Hi, my name is Juan! _&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;&lt;code&gt;Team Lead Fullstack&lt;/code&gt;&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;&lt;code&gt;Fullstack&lt;/code&gt;&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;&lt;code&gt;Fullstack&lt;/code&gt;&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;&lt;code&gt;Fullstack&lt;/code&gt;&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/tbody&gt;
&lt;br&gt;
&lt;/table&gt;&lt;/div&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How to use?&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;br&gt;
&lt;thead&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;th&gt;1. Create New story&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;2. Collaborate to story&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;3. Merge the story&lt;/th&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/thead&gt;
&lt;br&gt;
&lt;tbody&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/111412548/241064059-6648a2ec-c6b6-4da9-855d-d7c2ee88b066.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F111412548%2F241064059-6648a2ec-c6b6-4da9-855d-d7c2ee88b066.gif" width="100%" height="300"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/111412548/241064042-aafbe5df-c271-4199-8ceb-25c21e22e955.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F111412548%2F241064042-aafbe5df-c271-4199-8ceb-25c21e22e955.gif" width="100%" height="300"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/111412548/241064069-ae3429a1-c9d0-40ff-8ac8-e1b43218f2c0.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F111412548%2F241064069-ae3429a1-c9d0-40ff-8ac8-e1b43218f2c0.gif" width="100%" height="300"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/tbody&gt;
&lt;br&gt;
&lt;/table&gt;&lt;/div&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Technology used&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/63331153/241052172-540c6ca9-2f07-4a00-bc50-85104ec67bbb.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F63331153%2F241052172-540c6ca9-2f07-4a00-bc50-85104ec67bbb.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/43962ea76518cc3d0819b0206791ae36c28ccc369f99f412379914f42431c025/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f76657263656c2d2532333030303030302e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d76657263656c266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/43962ea76518cc3d0819b0206791ae36c28ccc369f99f412379914f42431c025/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f76657263656c2d2532333030303030302e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d76657263656c266c6f676f436f6c6f723d7768697465" alt="Vercel"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/cda83240a14c79779abcb42c304a24a00deb52c2f3441ea36fa27278f06e6f25/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507269736d61253545342e31332e302d3339383243453f7374796c653d666f722d7468652d6261646765266c6f676f3d507269736d61266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/cda83240a14c79779abcb42c304a24a00deb52c2f3441ea36fa27278f06e6f25/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507269736d61253545342e31332e302d3339383243453f7374796c653d666f722d7468652d6261646765266c6f676f3d507269736d61266c6f676f436f6c6f723d7768697465" alt="Prisma"&gt;&lt;/a&gt;
&lt;a href="https://javascript.info/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/6f196ac01fa814729a02e7d4331b5280422ba8355433f64e40a13c672c69d56e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4a6176615363726970742d4637444631453f7374796c653d666f722d7468652d6261646765266c6f676f3d4a617661536372697074266c6f676f436f6c6f723d7768697465" alt="JavaScript Badge"&gt;&lt;/a&gt;
&lt;a href="https://javascript.info/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8d2dde0f614101199d98e4331ca4f349ea994437190dae63353a1823929e95da/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e6f64652e6a732d3333393933333f7374796c653d666f722d7468652d6261646765266c6f676f3d6e6f6465646f746a73266c6f676f436f6c6f723d7768697465" alt="Node Badge"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/ad6849aa1ffccc39e7efc8c189c35c66b19ddeb66997e26053467c140098023d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e65787425354531332e332e322d626c61636b3f7374796c653d666f722d7468652d6261646765266c6f676f3d6e6578742e6a73266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/ad6849aa1ffccc39e7efc8c189c35c66b19ddeb66997e26053467c140098023d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e65787425354531332e332e322d626c61636b3f7374796c653d666f722d7468652d6261646765266c6f676f3d6e6578742e6a73266c6f676f436f6c6f723d7768697465" alt="Next JS"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/e9e912b8d72adb87dffa8dd24cf85202bddf66b011cb2efffda99e8716eecab4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7461696c77696e64637373253545332e332e322d2532333338423241432e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d7461696c77696e642d637373266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/e9e912b8d72adb87dffa8dd24cf85202bddf66b011cb2efffda99e8716eecab4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7461696c77696e64637373253545332e332e322d2532333338423241432e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d7461696c77696e642d637373266c6f676f436f6c6f723d7768697465" alt="TailwindCSS"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/efcee9c912e112d1388bb7490e7250d1ab1c3da863f29585c17523d59aa7470e/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f342f34642f4f70656e41495f4c6f676f2e737667"&gt;&lt;img src="https://camo.githubusercontent.com/efcee9c912e112d1388bb7490e7250d1ab1c3da863f29585c17523d59aa7470e/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f342f34642f4f70656e41495f4c6f676f2e737667" height="20px"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/996e8495faaf011916e3fd948b88a7578c409f1cfa13e5b64a30f90edde3a334/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d6f6e676f4442253545362e302d2532333465613934622e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d6d6f6e676f6462266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/996e8495faaf011916e3fd948b88a7578c409f1cfa13e5b64a30f90edde3a334/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4d6f6e676f4442253545362e302d2532333465613934622e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d6d6f6e676f6462266c6f676f436f6c6f723d7768697465" alt="MongoDB"&gt;&lt;/a&gt;
&lt;a href="https://javascript.info/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/3b0acf8c281dd7cf74cf4b9d601c2b6f8b91775cc4bd3a9c68c3eeffc3a73558/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5653436f64652d3030373844343f7374796c653d666f722d7468652d6261646765266c6f676f3d76697375616c25323073747564696f253230636f6465266c6f676f436f6c6f723d7768697465" alt="VScode Badge"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How did we use AI?&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;AI played a pivotal role in the creation of our app, particularly in the coding phase. We employed OpenAI's…&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/MiSaengg/2800-202310BBY19" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>openai</category>
    </item>
    <item>
      <title>COMP 1800 - A Simple Full-Stack Web Application 🌱</title>
      <dc:creator>David</dc:creator>
      <pubDate>Mon, 11 Sep 2023 04:59:16 +0000</pubDate>
      <link>https://forem.com/rjsgml/comp-1800-a-simple-full-stack-wep-application-5b4h</link>
      <guid>https://forem.com/rjsgml/comp-1800-a-simple-full-stack-wep-application-5b4h</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Starters 🏁&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This blog post delves into my project experience with COMP 1800. If you're unfamiliar with who I am, you can refer to my introductory &lt;a href="https://dev.to/rjsgml/pilot-start-of-my-blog-journey-2b04"&gt;post&lt;/a&gt;. &lt;br&gt;
For a brief overview of COMP 1800, please check out my most recent &lt;a href="https://dev.to/rjsgml/recap-reflection-of-term-1-2ic6"&gt;post&lt;/a&gt;. &lt;br&gt;
I've heard that having a deep understanding of one's projects can be beneficial during interviews. With that in mind, I'm launching a new series titled "Projects", where I'll discuss and delve into the technical components of the projects I've worked on.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;COMP 1800 🌱&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In COMP 1800, the theme of the project was to address issues related to extreme weather. The project focused on several considerations, including prevention, prediction, preparation, coping, and recovery. My team, consisting of three members, chose to focus on prevention by promoting an eco-friendly lifestyle.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Agile Methodology 💨&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.asana.biz%2Ftransform%2Ff3519623-44e4-4506-8e1f-38cb74819c58%2Finline-agile-agile-methodology-1-2x" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.asana.biz%2Ftransform%2Ff3519623-44e4-4506-8e1f-38cb74819c58%2Finline-agile-agile-methodology-1-2x" alt="Agile process" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;COMP 1800 adopted the agile software development life cycle (SDLC) methodology, and the weeks were divided into sprints. As illustrated in the image above, the steps are: (1) Plan, (2) Design, (3) Develop, (4) Test, (5) Deploy, and (6) Review.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Plan&lt;br&gt;
During the planning stage, we crafted new user stories for each sprint, focusing on implementing features based on the red route analysis. We utilized tools like Trello and Figjam for this purpose.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Design&lt;br&gt;
In the design phase, we created wireframes for the features we decided to implement, corresponding to the user story for that specific sprint.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Develop&lt;br&gt;
In the development stage, we began the actual coding for our user stories. Our tech stack included HTML5/CSS3, JavaScript, Bootstrap, Node.js, Express.js, Firebase, and Google Cloud API. I'll delve deeper into this later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test&lt;br&gt;
Given that this project was our first, our testing was limited. We didn't implement unit or integration tests. However, we did conduct usability tests with our peers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy&lt;br&gt;
Diverging from the typical agile process, we didn't fully deploy our application until the end. We used glitch.me for deployment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Review&lt;br&gt;
Our review took the form of a presentation within the course, during which we received feedback and addressed questions from our peers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Code review 🔍&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
  Node and express
  &lt;blockquote&gt;
&lt;p&gt;Initialization 🏁&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In our app, we use Express as our Node.js web framework middleware.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Initialization
const express = require("express");
const app = express();
// Middleware
app.use(express.json());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;CORS Headers 💻&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We've also set up Cross-Origin Resource Sharing (CORS) headers to allow requests from any origin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.use((req, res, next) =&amp;gt; {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Static File Serving &amp;amp; Routes 🚏&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With Express, we utilize static file serving. For instance, any files in the ./public/js directory can be accessed via the /js route.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.use(express.static('app'));
app.use("/js", express.static("./public/js"));
app.use("/css", express.static("./public/css"));
app.use("/img", express.static("./public/img"));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also manually set up routes for all of our pages, which was somewhat tedious. An example is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.get('/', (req, res) =&amp;gt; {
  res.sendFile(__dirname + '/app/html/index.html');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Server Initialization 🏁&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lastly, we initialized and ran our Express server on port 8000.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.listen(8000, () =&amp;gt; {
  console.log('Server started on port 8000');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;
  Firebase
  &lt;blockquote&gt;
&lt;p&gt;Initialization 🏁&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Initializing firebase was relative simple. All we had to do was go to firebase.google.com and start a project. After the project setup, all we had to do was install firebase as node package (&lt;code&gt;$ npm install firebase&lt;/code&gt;) and copy the firebase configurations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//----------------------------------------
//  Your web app's Firebase configuration
//----------------------------------------
var firebaseConfig = { //Input firebase API keys
  apiKey: "",
  authDomain: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
};

//--------------------------------------------
// initialize the Firebase app
// initialize Firestore database if using it
//--------------------------------------------
const app = firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();
const storage = firebase.storage();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Authentication 🔒&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We also used firebase for authentication since it was provided. We used the Firebase UI Widget for authentication and user log-ins. You can check the authentication and the sign in flow &lt;a href="https://github.com/gdcho/ecocentives/blob/main/public/js/authentication.js" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;
  JavaScript specifics
  &lt;br&gt;
The JavaScript code we wrote deals with Document Object Models (DOM), which I will explain in the code that I specifically wrote.

&lt;blockquote&gt;
&lt;p&gt;Leaderboard 🏆&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Firstly, a variable was made to retrieve a reference to the DOM element with the ID 'leaderboard-body', which involves the tbody element of the leaderboard table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var leaderboardTable = document.getElementById("leaderboard-body");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based off the leaderboard logic, I used document.createElement and appendChild method to display the users accordingly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var user = doc.data();
var points = user.points;

// Increment rank if points are lower than previous user's points
if (points !== previousPoints) {
    rank++;
}

var row = document.createElement("tr");
var rankCell = document.createElement("td");
rankCell.textContent = rank;
row.appendChild(rankCell);

var nameCell = document.createElement("td");
nameCell.appendChild(
    document.createTextNode(user.displayName || user.name)
        );
row.appendChild(nameCell);

var pointsCell = document.createElement("td");
pointsCell.textContent = points;
row.appendChild(pointsCell);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Tasks 📌&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For tasks, I randomly displayed tasks using random seed value  from the Firestore database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; const ecoActions = await getEcoActions();
 const randomTasks = [];

 for (let i = 0; i &amp;lt; 3; i++) {
    const randomIndex = Math.floor(Math.random(seed) * ecoActions.length);
    const randomTask = ecoActions[randomIndex];
    randomTasks.push(randomTask);
    ecoActions.splice(randomIndex, 1);
 }

 const taskList = document.getElementById("task-list");
 taskList.innerHTML = "";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on the tasks, I implemented functions to pick an image file to upload to call Google Vision API to analyze the image using label detection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const imageUrl = await fileRef.getDownloadURL();

// Call the Google Vision API to analyze the image
const apiKey = API_KEY;
const url = `https://vision.googleapis.com/v1/images:annotate?key=${apiKey}`;
const data = {
      requests: [
         {
           image: {
           source: {
              imageUri: imageUrl,
           },
         },
           features: [
         {
             type: "LABEL_DETECTION",
           },
          ],
         },
      ],
};

const response = await fetch(url, {
      method: "POST",
      headers: {
         "Content-Type": "application/json",
      },
          body: JSON.stringify(data),
});

const json = await response.json();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the response returns as valid, the task is marked as completed, associated points are added, and completed tasks are removed. &lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Conclusion ⛳️&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This has been a lengthy post, and I thank you for taking the time to read it. I'm not sure if this is the correct way to conduct my code review, so any suggestions are much appreciated!&lt;/p&gt;

&lt;p&gt;If you're interested in delving deeper into the code, you can check out the repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gdcho/ecocentives" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;Github Repository&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Thank you once again! Stay tuned for future posts. 🤠&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Recap - Reflection of Term 1 🧐</title>
      <dc:creator>David</dc:creator>
      <pubDate>Sat, 09 Sep 2023 23:08:08 +0000</pubDate>
      <link>https://forem.com/rjsgml/recap-reflection-of-term-1-2ic6</link>
      <guid>https://forem.com/rjsgml/recap-reflection-of-term-1-2ic6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Starters 🏁&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This blog post discusses my experience during the first term of BCIT's Computer Systems Technology program. For those unfamiliar with me, you can refer to my initial &lt;a href="https://dev.to/rjsgml/pilot-start-of-my-blog-journey-2b04"&gt;post&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;British Columbia Institute of Technology (BCIT) 🎓&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;BCIT is a public polytechnic institute located in Burnaby, British Columbia. Unlike traditional colleges or universities, the British Columbia Institute of Technology emphasizes practical, flexible, and applied education. The instructors here bring direct, hands-on experience from their respective fields.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Computer Systems Technology (CST) program 💻&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The CST program at BCIT is among the most challenging and rigorous diploma programs available. This program melds computer systems theory with hands-on experience in software development. For more details about the program, click &lt;a href="https://www.bcit.ca/programs/computer-systems-technology-diploma-full-time-5500dipma/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.bcit.ca/programs/computer-systems-technology-diploma-full-time-5500dipma/#courses" rel="noopener noreferrer"&gt;Courses&lt;/a&gt; in Term 1 📚&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;COMM 1116 (Business Communications 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one of the more relaxed courses. It covers writing professional emails, informal reports, and oral presentations. It serves as a prerequisite for COMM 2216 and aids international students in enhancing their English reading and writing skills.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;COMP 1100 (CST Program Fundamentals)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another laid-back course. It operates on a pass/fail system, requiring students to attend lectures and submit weekly journals. The focus is on introducing essential information and resources for success in the CST Diploma Program.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;COMP 1113 (Applied Mathematics)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This course is manageable with consistent effort. It covers partial discrete mathematics, an introduction to linear equations, and is segmented into: (1) Boolean algebra and logic circuit design; (2) number systems and data representation; and (3) functions, linear equations, vectors, and matrices. Based off this course, I made a &lt;a href="https://github.com/gdcho/comp1113_calculator" rel="noopener noreferrer"&gt;web application&lt;/a&gt; to assist in learning.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;COMP 1510 (Programming Methods)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is among the more challenging courses for many CST Term 1 students. It introduces the basics of object-oriented programming in Java (Burnaby campus) or Python (Downtown campus). The course covers programming fundamentals, including design, development, testing, debugging, error-handling, and problem-solving.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;COMP 1537 (Web Development 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some may find this course challenging, while those with prior web development experience might find it more accessible. It delves into both front-end and back-end programming using JavaScript, AJAX, DOM, and JSON.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;COMP 1712 (Business Analysis and System Design)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was one of the courses I found most challenging. It delves into the methodologies and tools for designing and developing information systems, covering concepts, processes, communication, decision-making, the software development life cycle (SDLC), data and process modeling, entity-relationship diagrams, databases, and more.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;COMP 1800 (Projects 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was one of my favorite courses. It involved group projects to create a small-scale responsive web application, incorporating the UX design process, agile methodology, and software management workflow.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reflections 🙏&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Overall, while Term 1 was demanding, I found it more enjoyable than anticipated. I forged numerous personal and professional connections and learned a tremendous amount in just five months. Beyond the academic growth, the rigorous schedule instilled discipline in my studies and inspired me to plan personal projects for the summer. I'll delve into these in upcoming posts.&lt;/p&gt;

&lt;p&gt;Thank you for reading, and stay tuned for future posts! 🤠&lt;/p&gt;

</description>
      <category>school</category>
      <category>education</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Pilot - Start of my blog journey 🛫</title>
      <dc:creator>David</dc:creator>
      <pubDate>Thu, 07 Sep 2023 01:31:26 +0000</pubDate>
      <link>https://forem.com/rjsgml/pilot-start-of-my-blog-journey-2b04</link>
      <guid>https://forem.com/rjsgml/pilot-start-of-my-blog-journey-2b04</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Welcome to my first post!&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I'm glad you're here to witness history.&lt;br&gt;
To those of you who do not know me, my name is David Cho, and I am a Computer Systems Technology at the &lt;a href="https://www.bcit.ca/" rel="noopener noreferrer"&gt;British Columbia Institute of Technology&lt;/a&gt; (BCIT). Before enrolling at BCIT, I graduated from the University of Waterloo with a degree in Honours Science - Bioinformatics.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why Did I Switch from Science to Tech?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;During my time at the University of Waterloo, many of my close friends and roommates were studying computer science. Their influence may have played a role in my eventual decision to pursue a tech career. Another major factor was my love for problem-solving and critical thinking. As a child, I was fascinated by puzzles and riddles and even dreamed of growing up to be like Sherlock Holmes. Fortunately, after taking a few introductory computer science courses at the University of Waterloo, I felt like I had found my calling.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why Did I Choose BCIT and the CST Program?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After extensive research, I discovered that BCIT and its CST program are popular among new graduates and career switchers. The 2-year CST program emphasizes hands-on learning and focuses more on practical skills than theory, making it ideal for those looking to advance their education.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did I Make the Right Choice?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As the saying goes, "Life is like a box of chocolates; you never know what you're going to get." I've completed my first term in the CST program and have just started my second term. So far, everything is going well, but life is full of surprises—who knows, I might even become a trout farmer one day. &lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>programming</category>
      <category>pilot</category>
      <category>career</category>
    </item>
  </channel>
</rss>
