<?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>DEV Community: peter279k</title>
    <description>The latest articles on DEV Community by peter279k (@peter279k).</description>
    <link>https://dev.to/peter279k</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%2F153868%2Fbf173814-4a16-461f-8733-514ab202b7f8.jpeg</url>
      <title>DEV Community: peter279k</title>
      <link>https://dev.to/peter279k</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/peter279k"/>
    <language>en</language>
    <item>
      <title>Web Extract Worker, a service with text-to-image worker AI models!</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Fri, 12 Apr 2024 17:44:36 +0000</pubDate>
      <link>https://dev.to/peter279k/web-extract-worker-a-service-with-text-to-image-worker-ai-models-59e1</link>
      <guid>https://dev.to/peter279k/web-extract-worker-a-service-with-text-to-image-worker-ai-models-59e1</guid>
      <description>&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;In our web service, we can fill the prompt and generate image with one of the text-to-image worker AI model randomly.&lt;/p&gt;

&lt;p&gt;The user scenario image is as folows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F63qennb786p0ikqvdc8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F63qennb786p0ikqvdc8n.png" alt="User Scenario"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Our front-end worker is deployed at the &lt;a href="https://web-extract-worker.pages.dev" rel="noopener noreferrer"&gt;Cloudflare Pages&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try out our web service!
&lt;/h3&gt;

&lt;p&gt;Firstly, open the web page and browse the above link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fg816fes8ydmp5efprrpk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fg816fes8ydmp5efprrpk.png" alt="Step 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Input the &lt;code&gt;corgi&lt;/code&gt; to be the prompt and click "Generate" button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbcwysylxm1r6fb769n1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbcwysylxm1r6fb769n1z.png" alt="Step 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After waiting for about whiles, it will present generated image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fll0y46i80dx4qg07zt9k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fll0y46i80dx4qg07zt9k.png" alt="Step 3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You're done for our web service tutorial now!&lt;/p&gt;

&lt;h2&gt;
  
  
  My Code
&lt;/h2&gt;

&lt;p&gt;Our source code is available here:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/peter279k" rel="noopener noreferrer"&gt;
        peter279k
      &lt;/a&gt; / &lt;a href="https://github.com/peter279k/web-extract-worker" rel="noopener noreferrer"&gt;
        web-extract-worker
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The web-based extract text to image worker :).
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Web Extract Worker&lt;/h1&gt;

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

&lt;/div&gt;
&lt;p&gt;The web-based extract text to image worker :).&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Firstly, clone or fork this repository.&lt;/li&gt;
&lt;li&gt;Second, please refer the &lt;a href="https://developers.cloudflare.com/pages/get-started/git-integration/" rel="nofollow noopener noreferrer"&gt;Cloudflare Pages Docs&lt;/a&gt; to complete the front-end page deployment.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/peter279k/web-extract-worker" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;And our techniques are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Front-end: The &lt;code&gt;index.html&lt;/code&gt; is the main page to let users input their prompts and see generated image.&lt;/li&gt;
&lt;li&gt;Back-end: The &lt;code&gt;extract.php&lt;/code&gt; is the main PHP program to handle user prompt and respond generated image.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;We used these following models and the PHP program will choose them randomly when retrieving user prompts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Image-to-text: &lt;a href="https://developers.cloudflare.com/workers-ai/models/dreamshaper-8-lcm" rel="noopener noreferrer"&gt;@cf/lykon/dreamshaper-8-lcm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Image-to-text: &lt;a href="https://developers.cloudflare.com/workers-ai/models/stable-diffusion-xl-base-1.0" rel="noopener noreferrer"&gt;@cf/stabilityai/stable-diffusion-xl-base-1.0&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Image-to-text: &lt;a href="https://developers.cloudflare.com/workers-ai/models/stable-diffusion-xl-lightning" rel="noopener noreferrer"&gt;@cf/bytedance/stable-diffusion-xl-lightning&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's the dead simple for PHP developers to learn how to use the native PHP codes to develop a extract text to image service via the Cloudflare worker AI models :).&lt;/p&gt;

</description>
      <category>cloudflarechallenge</category>
      <category>devchallenge</category>
      <category>ai</category>
    </item>
    <item>
      <title>Integrating the GitHub action to make yt-dlp-api tests automated!</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Mon, 15 May 2023 09:56:22 +0000</pubDate>
      <link>https://dev.to/peter279k/integrating-the-github-action-to-make-yt-dlp-api-tests-automated-37m1</link>
      <guid>https://dev.to/peter279k/integrating-the-github-action-to-make-yt-dlp-api-tests-automated-37m1</guid>
      <description>&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I developed a YouTube API service with the yt-dlp and Fast-API and it can give the YouTube video link to extract the video information.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Category Submission
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The category is for the DIY deployments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  App Link
&lt;/h3&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://yt-dlp-api.peterli.website/" rel="noopener noreferrer"&gt;
      yt-dlp-api.peterli.website
    &lt;/a&gt;
&lt;/div&gt;



&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://youtube.peterli.website/" rel="noopener noreferrer"&gt;
      youtube.peterli.website
    &lt;/a&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;The demonstration website is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fa0buri3r5qafnpvjlign.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fa0buri3r5qafnpvjlign.png" alt="Demonstration website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Swagger API doc website is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fkipqb6zrseddju3hherg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fkipqb6zrseddju3hherg.png" alt="Swagger API doc website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Description
&lt;/h3&gt;

&lt;p&gt;The simple yt-dlp-api server is to extract YouTube video URL easily.&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Source Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/peter279k" rel="noopener noreferrer"&gt;
        peter279k
      &lt;/a&gt; / &lt;a href="https://github.com/peter279k/yt-dlp-api" rel="noopener noreferrer"&gt;
        yt-dlp-api
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The simple yt-dlp-api server to extract YouTube video URL easily
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;yt-dlp-api&lt;/h1&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Introduction&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;The simple yt-dlp-api server is for extracting YouTube video information with YouTube video URL.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Usage&lt;/h1&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Preparing the Linux-like operating system.&lt;/li&gt;
&lt;li&gt;Preparing the &lt;code&gt;Python 3.7+&lt;/code&gt; version in the operating system.&lt;/li&gt;
&lt;li&gt;Install the &lt;code&gt;pipenv&lt;/code&gt; with running the &lt;code&gt;pip3 install -U pipenv&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;Running the &lt;code&gt;pipenv install&lt;/code&gt; to create the virtual environment.&lt;/li&gt;
&lt;li&gt;Modifying the &lt;code&gt;yt-dlp-api.service&lt;/code&gt; file with the &lt;code&gt;yt-dlp-api.service.example&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Copying the &lt;code&gt;yt-dlp-api.service&lt;/code&gt; file to the &lt;code&gt;/etc/systemd/system/&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;Running the &lt;code&gt;sudo systemctl daemon-reload&lt;/code&gt; to reload the systemd daemon.&lt;/li&gt;
&lt;li&gt;Running the &lt;code&gt;sudo systemctl enable --now yt-dlp-api.service&lt;/code&gt; to enable and start the service.&lt;/li&gt;
&lt;li&gt;Enjoy it!&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Tips&lt;/h1&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Sometimes the &lt;code&gt;yt-dlp&lt;/code&gt; are updated frequently and it can run the &lt;code&gt;pipenv run pip install -U yt-dlp&lt;/code&gt; command to upgrade this package and run the &lt;code&gt;systemctl restart yt-dlp-api.service&lt;/code&gt; command to restart the daemon service.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/peter279k/yt-dlp-api" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Permissive License
&lt;/h3&gt;

&lt;p&gt;The open source project is under the MIT license.&lt;/p&gt;

&lt;p&gt;The LICENSE details is available &lt;a href="https://github.com/peter279k/yt-dlp-api/blob/master/LICENSE" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;My aunt likes to watch the Japanese music video and she wants to use the video to make her own music video.&lt;/p&gt;

&lt;p&gt;However, many on-line YouTube video downloader websites are not convenient for people because they contain some advertisements. And she usually clicks the wrong place before downloading the YouTube video via the website.&lt;/p&gt;

&lt;p&gt;Due the above reason, I determine developing the YouTube video downloading website and it can resolve the above issue currently.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I built it
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For integrating the GitHub action setting, it's available &lt;a href="https://github.com/peter279k/yt-dlp-api/blob/master/.github/workflows/tests.yml" rel="noopener noreferrer"&gt;here&lt;/a&gt;.

&lt;ul&gt;
&lt;li&gt;I use the GitHub action to setup the Python 3.8 environment and make some tests automated with pytest.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;I use the following techniques to complete above website development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.8+&lt;/li&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;Bootstrap 4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use the following techniques to complete the unit tests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pytest&lt;/li&gt;
&lt;li&gt;pytest-mock&lt;/li&gt;
&lt;li&gt;Fast API testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I learn how to use above packages to complete unit tests. And it includes mocked test approaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources/Info
&lt;/h3&gt;

&lt;p&gt;Here are some useful references I found and it's helpful for me to complete this open source project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://changhsinlee.com/pytest-mock" rel="noopener noreferrer"&gt;pytest-mock&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fastapi.tiangolo.com/tutorial/testing" rel="noopener noreferrer"&gt;Fast API testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/analytics-vidhya/how-to-use-pytest-mock-to-simulate-responses-1ea41e964161" rel="noopener noreferrer"&gt;how-to-use-pytest-mock-to-simulate-responses&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>githubhack23</category>
      <category>github</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>My RSS Cache Application</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Sun, 28 Aug 2022 08:23:39 +0000</pubDate>
      <link>https://dev.to/peter279k/my-rss-cache-application-1o4k</link>
      <guid>https://dev.to/peter279k/my-rss-cache-application-1o4k</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Creating the RSS Cache can help me to cache the source RSS feeds easily!&lt;/li&gt;
&lt;li&gt;It's my requirements for developing the RSS cache application.&lt;/li&gt;
&lt;li&gt;Here is the simple system architecture to describe how to build the App:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdg0wpicwwyna7b5kk21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdg0wpicwwyna7b5kk21.png" alt="App architecture" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It's the Wacky Wildcards category.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Language Used
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Using the Python 3.8+ for developing the App.&lt;/li&gt;
&lt;li&gt;Using the Python Flask to developing the web application.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Additional Resource info
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/peter279k/my-rss-cache/blob/master/LICENSE"&gt;MIT License&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Collaborators
&lt;/h3&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/peter279k"&gt;@peter279k&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/peter279k"&gt;
        peter279k
      &lt;/a&gt; / &lt;a href="https://github.com/peter279k/my-rss-cache"&gt;
        my-rss-cache
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      My RSS Cache App for storing the RSS cache
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;My RSS Cache&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Sometitmes the RSS feed caching is not implemented, customizing the RSS cache for my favorite RSS feed.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/e30d36a899b5899036f97ca70a8b41d58ea3c786e4ed93c5bfef6bf45f8369f3/68747470733a2f2f692e696d6775722e636f6d2f637a3133555a392e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/e30d36a899b5899036f97ca70a8b41d58ea3c786e4ed93c5bfef6bf45f8369f3/68747470733a2f2f692e696d6775722e636f6d2f637a3133555a392e706e67" width="100%" height="auto"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/f21556351e5257856742dc9dc6352766c1ec5e8d8ca1a769510f57fb77854b0f/68747470733a2f2f692e696d6775722e636f6d2f3531334a6f4c4c2e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/f21556351e5257856742dc9dc6352766c1ec5e8d8ca1a769510f57fb77854b0f/68747470733a2f2f692e696d6775722e636f6d2f3531334a6f4c4c2e706e67" width="100%" height="auto"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How it works&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;How the data is stored:&lt;/h3&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;The RSS data contents is stored in the single key and data type.
&lt;ul&gt;
&lt;li&gt;For each RSS data contents:
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;lic_nttu_rss&lt;/code&gt; is  the key and its value is the RSS XML feed contents.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;lic_nttu_rss_expired&lt;/code&gt; is the key and its value is current timestamp for fetching the RSS contents.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;How the data is accessed:&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Here is the sample code to access the RSS feed and expired with Python Redis OM:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight highlight-source-python notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s1"&gt;redis_om&lt;/span&gt; &lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-s1"&gt;get_redis_connection&lt;/span&gt;

&lt;span class="pl-c"&gt;# Get the RSS feed&lt;/span&gt;
&lt;span class="pl-s1"&gt;rss_contents&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s1"&gt;redis_conn&lt;/span&gt;.&lt;span class="pl-en"&gt;get&lt;/span&gt;(&lt;span class="pl-s"&gt;'lic_nttu_rss'&lt;/span&gt;)

&lt;span class="pl-c"&gt;# Get the RSS expired value&lt;/span&gt;
&lt;span class="pl-s1"&gt;expired&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s1"&gt;redis_conn&lt;/span&gt;.&lt;span class="pl-en"&gt;get&lt;/span&gt;(&lt;span class="pl-s"&gt;'lic_nttu_rss_expired'&lt;/span&gt;)&lt;/pre&gt;

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

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Prerequisites&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Python - 3.8+&lt;/li&gt;
&lt;li&gt;pip - 21.1.1+&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Local installation&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Cloning the repository with &lt;code&gt;git clone&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;Running…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/peter279k/my-rss-cache"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>redishackathon</category>
      <category>redis</category>
    </item>
    <item>
      <title>Listen the "I want to buy the COVID-19 test kit" website with Appwrite!</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Wed, 11 May 2022 08:24:00 +0000</pubDate>
      <link>https://dev.to/peter279k/listen-the-i-want-to-buy-the-covid-19-test-kit-website-with-appwrite-4a7n</link>
      <guid>https://dev.to/peter279k/listen-the-i-want-to-buy-the-covid-19-test-kit-website-with-appwrite-4a7n</guid>
      <description>&lt;h2&gt;
  
  
  Instructions
&lt;/h2&gt;

&lt;p&gt;Since one month ago, the Omincron epidemic is outbreak and the local cases are increased every day in Taiwan.&lt;/p&gt;

&lt;p&gt;To detect the Omincron, the COVID-19 test kit is more and more important. However, the test kit in Taiwan is not cheap enough for people. To solve the above problem, the government decides to expropriate the test kit.&lt;/p&gt;

&lt;p&gt;And it can let them be cheap for people to be available to buy. These expropriated test kits will let some pharmacies sell and each pharmacy can get 78 test kits from government every day. &lt;/p&gt;

&lt;p&gt;People who have the last number of their ID number is odd can go to the pharmacy and buy the 5 test kits at most on Monday, Wednesday, Friday and Sunday. And the people who have the last number of their ID number is even can go to the pharmacy and buy the 5 test kits at most on Tuesday, Thursday, Saturday and Sunday.&lt;/p&gt;

&lt;p&gt;To let people realize where pharmacy is available to buy the test kit, I fetch the open data about pharmacy test kits that is generated by Taiwan CDC. And develop the simple website to let people type keywords to search the pharmacy and test kit numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;The website is simple, and I use the jQuery to develop the front-end.&lt;/p&gt;

&lt;p&gt;Then using the &lt;a href="https://data.nhi.gov.tw/resource/Nhi_Fst/Fstdata.csv"&gt;pharmacy test kit data&lt;/a&gt; to be the source data and let the jQuery parse the CSV data then present them in the web page finally.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ibjqpjv2i29q9426q8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ibjqpjv2i29q9426q8c.png" alt="Website screen" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl7lwfwh53sin6thifywa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl7lwfwh53sin6thifywa.png" alt="Appwrite dashoboard" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I provide the website for people to browse and the available links are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pharmacy-test-kit.peterli.website"&gt;My Appwrite dashboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://peter279k.github.io/pharmacy-test-kit"&gt;GitHub page&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;It belongs to the Web2 Wizards category.&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/peter279k"&gt;
        peter279k
      &lt;/a&gt; / &lt;a href="https://github.com/peter279k/pharmacy-test-kit"&gt;
        pharmacy-test-kit
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      查詢各藥局快篩試劑的數量
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;我要買快篩&lt;/h1&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;專案介紹&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;查詢各藥局快篩試劑的數量 (文字查詢簡易版)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;特別感謝&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;感謝 &lt;a href="https://github.com/SOSELab401/pharmacy"&gt;pharmacy&lt;/a&gt; 專案讓此網站得以完成:).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Demonstration/網站展示&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://peter279k.github.io/pharmacy-test-kit" rel="nofollow"&gt;https://peter279k.github.io/pharmacy-test-kit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Data Source資料來源&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://data.nhi.gov.tw/resource/Nhi_Fst/Fstdata.csv" rel="nofollow"&gt;Fstdata.csv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/peter279k/pharmacy-test-kit"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;Here are some references are about developing above website:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jquery.com"&gt;jQuery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://data.nhi.gov.tw"&gt;Taiwan NHI Open Data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>appwritehack</category>
      <category>appwrite</category>
    </item>
    <item>
      <title>Deploy my web-youtube-downloader in my Azure VM!</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Sun, 06 Mar 2022 08:22:47 +0000</pubDate>
      <link>https://dev.to/peter279k/deploy-my-web-youtube-downloader-in-my-azure-vm-3d8a</link>
      <guid>https://dev.to/peter279k/deploy-my-web-youtube-downloader-in-my-azure-vm-3d8a</guid>
      <description>&lt;h3&gt;
  
  
  Instructions
&lt;/h3&gt;

&lt;p&gt;I use the Azure Virtual Machines to deploy my we-base YouTube downloader and it can help developers to download the specific YouTube video easily via my website :)!&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;Here are my quick steps to complete this repository&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a Azure VM and use the Ubuntu 20.04 LTS via the Azure portal.&lt;/li&gt;
&lt;li&gt;Using the SSH client to login the remote server.&lt;/li&gt;
&lt;li&gt;Installing the PHP 8.1, Nginx and other required PHP packages with &lt;code&gt;apt-get&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;Cloning the GitHub repository with &lt;code&gt;git&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;Running the &lt;code&gt;build.sh&lt;/code&gt; shell script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are snippets about my running command histories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lee@lee-VirtualBox:~&lt;span class="nv"&gt;$ &lt;/span&gt;ssh peterli@20.121.186.160
Welcome to Ubuntu 20.04.4 LTS &lt;span class="o"&gt;(&lt;/span&gt;GNU/Linux 5.13.0-1014-azure x86_64&lt;span class="o"&gt;)&lt;/span&gt;

 &lt;span class="k"&gt;*&lt;/span&gt; Documentation:  https://help.ubuntu.com
 &lt;span class="k"&gt;*&lt;/span&gt; Management:     https://landscape.canonical.com
 &lt;span class="k"&gt;*&lt;/span&gt; Support:        https://ubuntu.com/advantage

  System information as of Sun Mar  6 05:41:26 UTC 2022

  System load:  0.0               Processes:             127
  Usage of /:   4.8% of 28.90GB   Users logged &lt;span class="k"&gt;in&lt;/span&gt;:       0
  Memory usage: 3%                IPv4 address &lt;span class="k"&gt;for &lt;/span&gt;eth0: 10.0.0.4
  Swap usage:   0%

 &lt;span class="k"&gt;*&lt;/span&gt; Super-optimized &lt;span class="k"&gt;for &lt;/span&gt;small spaces - &lt;span class="nb"&gt;read &lt;/span&gt;how we shrank the memory
   footprint of MicroK8s to make it the smallest full K8s around.

   https://ubuntu.com/blog/microk8s-memory-optimisation

1 update can be applied immediately.
To see these additional updates run: apt list &lt;span class="nt"&gt;--upgradable&lt;/span&gt;


Last login: Sun Mar  6 05:34:06 2022 from 114.32.26.216
To run a &lt;span class="nb"&gt;command &lt;/span&gt;as administrator &lt;span class="o"&gt;(&lt;/span&gt;user &lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;, use &lt;span class="s2"&gt;"sudo &amp;lt;command&amp;gt;"&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
See &lt;span class="s2"&gt;"man sudo_root"&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;details.

peterli@web-youtube-downloader:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
Hit:1 http://azure.archive.ubuntu.com/ubuntu focal InRelease
Get:2 http://azure.archive.ubuntu.com/ubuntu focal-updates InRelease &lt;span class="o"&gt;[&lt;/span&gt;114 kB]
Get:3 http://azure.archive.ubuntu.com/ubuntu focal-backports InRelease &lt;span class="o"&gt;[&lt;/span&gt;108 kB]
Get:4 http://azure.archive.ubuntu.com/ubuntu focal-security InRelease &lt;span class="o"&gt;[&lt;/span&gt;114 kB]
Get:5 http://azure.archive.ubuntu.com/ubuntu focal/universe amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;8628 kB]
Get:6 http://azure.archive.ubuntu.com/ubuntu focal/universe Translation-en &lt;span class="o"&gt;[&lt;/span&gt;5124 kB]
Get:7 http://azure.archive.ubuntu.com/ubuntu focal/universe amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;265 kB]
Get:8 http://azure.archive.ubuntu.com/ubuntu focal/multiverse amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;144 kB]
Get:9 http://azure.archive.ubuntu.com/ubuntu focal/multiverse Translation-en &lt;span class="o"&gt;[&lt;/span&gt;104 kB]
Get:10 http://azure.archive.ubuntu.com/ubuntu focal/multiverse amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;9136 B]
Get:11 http://azure.archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;1608 kB]
Get:12 http://azure.archive.ubuntu.com/ubuntu focal-updates/main amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;14.8 kB]
Get:13 http://azure.archive.ubuntu.com/ubuntu focal-updates/universe amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;905 kB]
Get:14 http://azure.archive.ubuntu.com/ubuntu focal-updates/universe Translation-en &lt;span class="o"&gt;[&lt;/span&gt;201 kB]
Get:15 http://azure.archive.ubuntu.com/ubuntu focal-updates/universe amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;20.2 kB]
Get:16 http://azure.archive.ubuntu.com/ubuntu focal-updates/multiverse amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;23.7 kB]
Get:17 http://azure.archive.ubuntu.com/ubuntu focal-updates/multiverse Translation-en &lt;span class="o"&gt;[&lt;/span&gt;7312 B]
Get:18 http://azure.archive.ubuntu.com/ubuntu focal-updates/multiverse amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;580 B]
Get:19 http://azure.archive.ubuntu.com/ubuntu focal-backports/main amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;42.2 kB]
Get:20 http://azure.archive.ubuntu.com/ubuntu focal-backports/main Translation-en &lt;span class="o"&gt;[&lt;/span&gt;10.1 kB]
Get:21 http://azure.archive.ubuntu.com/ubuntu focal-backports/main amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;864 B]
Get:22 http://azure.archive.ubuntu.com/ubuntu focal-backports/restricted amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;116 B]
Get:23 http://azure.archive.ubuntu.com/ubuntu focal-backports/universe amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;22.7 kB]
Get:24 http://azure.archive.ubuntu.com/ubuntu focal-backports/universe Translation-en &lt;span class="o"&gt;[&lt;/span&gt;15.4 kB]
Get:25 http://azure.archive.ubuntu.com/ubuntu focal-backports/universe amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;804 B]
Get:26 http://azure.archive.ubuntu.com/ubuntu focal-backports/multiverse amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;116 B]
Get:27 http://azure.archive.ubuntu.com/ubuntu focal-security/main amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;1275 kB]
Get:28 http://azure.archive.ubuntu.com/ubuntu focal-security/main Translation-en &lt;span class="o"&gt;[&lt;/span&gt;224 kB]
Get:29 http://azure.archive.ubuntu.com/ubuntu focal-security/main amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;9732 B]
Get:30 http://azure.archive.ubuntu.com/ubuntu focal-security/universe amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;680 kB]
Get:31 http://azure.archive.ubuntu.com/ubuntu focal-security/universe Translation-en &lt;span class="o"&gt;[&lt;/span&gt;117 kB]
Get:32 http://azure.archive.ubuntu.com/ubuntu focal-security/universe amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;13.2 kB]
Get:33 http://azure.archive.ubuntu.com/ubuntu focal-security/multiverse amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;20.7 kB]
Get:34 http://azure.archive.ubuntu.com/ubuntu focal-security/multiverse Translation-en &lt;span class="o"&gt;[&lt;/span&gt;5196 B]
Get:35 http://azure.archive.ubuntu.com/ubuntu focal-security/multiverse amd64 c-n-f Metadata &lt;span class="o"&gt;[&lt;/span&gt;500 B]
Fetched 19.8 MB &lt;span class="k"&gt;in &lt;/span&gt;3s &lt;span class="o"&gt;(&lt;/span&gt;6263 kB/s&lt;span class="o"&gt;)&lt;/span&gt;
Reading package lists... Done
peterli@web-youtube-downloader:~&lt;span class="err"&gt;$&lt;/span&gt;
peterli@web-youtube-downloader:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get upgrade
Reading package lists... Done
Building dependency tree
Reading state information... Done
Calculating upgrade... Done
The following packages will be upgraded:
  open-vm-tools
1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 647 kB of archives.
After this operation, 952 kB of additional disk space will be used.
Do you want to &lt;span class="k"&gt;continue&lt;/span&gt;? &lt;span class="o"&gt;[&lt;/span&gt;Y/n]
Get:1 http://azure.archive.ubuntu.com/ubuntu focal-updates/universe amd64 open-vm-tools amd64 2:11.3.0-2ubuntu0~ubuntu20.04.2 &lt;span class="o"&gt;[&lt;/span&gt;647 kB]
Fetched 647 kB &lt;span class="k"&gt;in &lt;/span&gt;0s &lt;span class="o"&gt;(&lt;/span&gt;6344 kB/s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;Reading database ... 57736 files and directories currently installed.&lt;span class="o"&gt;)&lt;/span&gt;
Preparing to unpack .../open-vm-tools_2%3a11.3.0-2ubuntu0~ubuntu20.04.2_amd64.deb ...
Unpacking open-vm-tools &lt;span class="o"&gt;(&lt;/span&gt;2:11.3.0-2ubuntu0~ubuntu20.04.2&lt;span class="o"&gt;)&lt;/span&gt; over &lt;span class="o"&gt;(&lt;/span&gt;2:11.0.5-4&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up open-vm-tools &lt;span class="o"&gt;(&lt;/span&gt;2:11.3.0-2ubuntu0~ubuntu20.04.2&lt;span class="o"&gt;)&lt;/span&gt; ...
Installing new version of config file /etc/vmware-tools/tools.conf.example ...
Installing new version of config file /etc/vmware-tools/vgauth.conf ...
Removing obsolete conffile /etc/vmware-tools/vm-support ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;systemd &lt;span class="o"&gt;(&lt;/span&gt;245.4-4ubuntu3.15&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;man-db &lt;span class="o"&gt;(&lt;/span&gt;2.9.1-1&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;libc-bin &lt;span class="o"&gt;(&lt;/span&gt;2.31-0ubuntu9.7&lt;span class="o"&gt;)&lt;/span&gt; ...
peterli@web-youtube-downloader:~&lt;span class="err"&gt;$&lt;/span&gt;
peterli@web-youtube-downloader:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;add-apt-repository ppa:ondrej/php &lt;span class="nt"&gt;-y&lt;/span&gt;
Hit:1 http://azure.archive.ubuntu.com/ubuntu focal InRelease
Hit:2 http://azure.archive.ubuntu.com/ubuntu focal-updates InRelease
Hit:3 http://azure.archive.ubuntu.com/ubuntu focal-backports InRelease
Hit:4 http://azure.archive.ubuntu.com/ubuntu focal-security InRelease
Get:5 http://ppa.launchpad.net/ondrej/php/ubuntu focal InRelease &lt;span class="o"&gt;[&lt;/span&gt;23.9 kB]
Get:6 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;101 kB]
Get:7 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main Translation-en &lt;span class="o"&gt;[&lt;/span&gt;33.6 kB]
Fetched 159 kB &lt;span class="k"&gt;in &lt;/span&gt;1s &lt;span class="o"&gt;(&lt;/span&gt;142 kB/s&lt;span class="o"&gt;)&lt;/span&gt;
Reading package lists... Done
peterli@web-youtube-downloader:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;add-apt-repository ppa:ondrej/nginx &lt;span class="nt"&gt;-y&lt;/span&gt;
Hit:1 http://azure.archive.ubuntu.com/ubuntu focal InRelease
Hit:2 http://azure.archive.ubuntu.com/ubuntu focal-updates InRelease
Hit:3 http://azure.archive.ubuntu.com/ubuntu focal-backports InRelease
Hit:4 http://azure.archive.ubuntu.com/ubuntu focal-security InRelease
Get:5 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal InRelease &lt;span class="o"&gt;[&lt;/span&gt;23.8 kB]
Hit:6 http://ppa.launchpad.net/ondrej/php/ubuntu focal InRelease
Get:7 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 Packages &lt;span class="o"&gt;[&lt;/span&gt;5892 B]
Get:8 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main Translation-en &lt;span class="o"&gt;[&lt;/span&gt;6104 B]
Fetched 35.8 kB &lt;span class="k"&gt;in &lt;/span&gt;1s &lt;span class="o"&gt;(&lt;/span&gt;44.1 kB/s&lt;span class="o"&gt;)&lt;/span&gt;
Reading package lists... Done
peterli@web-youtube-downloader:~&lt;span class="err"&gt;$&lt;/span&gt;
peterli@web-youtube-downloader:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;php8.1-cli
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  libpcre2-8-0 php-common php8.1-common php8.1-opcache php8.1-readline
Suggested packages:
  php-pear
The following NEW packages will be installed:
  php-common php8.1-cli php8.1-common php8.1-opcache php8.1-readline
The following packages will be upgraded:
  libpcre2-8-0
1 upgraded, 5 newly installed, 0 to remove and 6 not upgraded.
Need to get 3313 kB of archives.
After this operation, 15.9 MB of additional disk space will be used.
Do you want to &lt;span class="k"&gt;continue&lt;/span&gt;? &lt;span class="o"&gt;[&lt;/span&gt;Y/n]
Get:1 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 libpcre2-8-0 amd64 10.39-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;202 kB]
Get:2 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 php-common all 2:92+ubuntu20.04.1+deb.sury.org+2 &lt;span class="o"&gt;[&lt;/span&gt;16.3 kB]
Get:3 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 php8.1-common amd64 8.1.3-1+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;1091 kB]
Get:4 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 php8.1-opcache amd64 8.1.3-1+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;332 kB]
Get:5 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 php8.1-readline amd64 8.1.3-1+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;12.8 kB]
Get:6 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 php8.1-cli amd64 8.1.3-1+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;1659 kB]
Fetched 3313 kB &lt;span class="k"&gt;in &lt;/span&gt;3s &lt;span class="o"&gt;(&lt;/span&gt;1243 kB/s&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;Reading database ... 57751 files and directories currently installed.&lt;span class="o"&gt;)&lt;/span&gt;
Preparing to unpack .../libpcre2-8-0_10.39-2+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking libpcre2-8-0:amd64 &lt;span class="o"&gt;(&lt;/span&gt;10.39-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; over &lt;span class="o"&gt;(&lt;/span&gt;10.34-7&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libpcre2-8-0:amd64 &lt;span class="o"&gt;(&lt;/span&gt;10.39-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package php-common.
&lt;span class="o"&gt;(&lt;/span&gt;Reading database ... 57751 files and directories currently installed.&lt;span class="o"&gt;)&lt;/span&gt;
Preparing to unpack .../php-common_2%3a92+ubuntu20.04.1+deb.sury.org+2_all.deb ...
Unpacking php-common &lt;span class="o"&gt;(&lt;/span&gt;2:92+ubuntu20.04.1+deb.sury.org+2&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package php8.1-common.
Preparing to unpack .../php8.1-common_8.1.3-1+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking php8.1-common &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package php8.1-opcache.
Preparing to unpack .../php8.1-opcache_8.1.3-1+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking php8.1-opcache &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package php8.1-readline.
Preparing to unpack .../php8.1-readline_8.1.3-1+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking php8.1-readline &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package php8.1-cli.
Preparing to unpack .../php8.1-cli_8.1.3-1+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking php8.1-cli &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up php-common &lt;span class="o"&gt;(&lt;/span&gt;2:92+ubuntu20.04.1+deb.sury.org+2&lt;span class="o"&gt;)&lt;/span&gt; ...
Created symlink /etc/systemd/system/timers.target.wants/phpsessionclean.timer → /lib/systemd/system/phpsessionclean.timer.
Setting up php8.1-common &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...

Creating config file /etc/php/8.1/mods-available/calendar.ini with new version

Creating config file /etc/php/8.1/mods-available/ctype.ini with new version

Creating config file /etc/php/8.1/mods-available/exif.ini with new version

Creating config file /etc/php/8.1/mods-available/fileinfo.ini with new version

Creating config file /etc/php/8.1/mods-available/ffi.ini with new version

Creating config file /etc/php/8.1/mods-available/ftp.ini with new version

Creating config file /etc/php/8.1/mods-available/gettext.ini with new version

Creating config file /etc/php/8.1/mods-available/iconv.ini with new version

Creating config file /etc/php/8.1/mods-available/pdo.ini with new version

Creating config file /etc/php/8.1/mods-available/phar.ini with new version

Creating config file /etc/php/8.1/mods-available/posix.ini with new version

Creating config file /etc/php/8.1/mods-available/shmop.ini with new version

Creating config file /etc/php/8.1/mods-available/sockets.ini with new version

Creating config file /etc/php/8.1/mods-available/sysvmsg.ini with new version

Creating config file /etc/php/8.1/mods-available/sysvsem.ini with new version

Creating config file /etc/php/8.1/mods-available/sysvshm.ini with new version

Creating config file /etc/php/8.1/mods-available/tokenizer.ini with new version
Setting up php8.1-readline &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...

Creating config file /etc/php/8.1/mods-available/readline.ini with new version
Setting up php8.1-opcache &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...

Creating config file /etc/php/8.1/mods-available/opcache.ini with new version
Setting up php8.1-cli &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
update-alternatives: using /usr/bin/php8.1 to provide /usr/bin/php &lt;span class="o"&gt;(&lt;/span&gt;php&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;auto mode
update-alternatives: using /usr/bin/phar8.1 to provide /usr/bin/phar &lt;span class="o"&gt;(&lt;/span&gt;phar&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;auto mode
update-alternatives: using /usr/bin/phar.phar8.1 to provide /usr/bin/phar.phar &lt;span class="o"&gt;(&lt;/span&gt;phar.phar&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;auto mode

Creating config file /etc/php/8.1/cli/php.ini with new version
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;man-db &lt;span class="o"&gt;(&lt;/span&gt;2.9.1-1&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;libc-bin &lt;span class="o"&gt;(&lt;/span&gt;2.31-0ubuntu9.7&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;php8.1-cli &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
peterli@web-youtube-downloader:~&lt;span class="err"&gt;$&lt;/span&gt;
peterli@web-youtube-downloader:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;curl php8.1-xml php8.1-curl php8.1-xml php8.1-mbstrin
g php8.1-zip
Reading package lists... Done
Building dependency tree
Reading state information... Done
curl is already the newest version &lt;span class="o"&gt;(&lt;/span&gt;7.68.0-1ubuntu2.7&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
curl &lt;span class="nb"&gt;set &lt;/span&gt;to manually installed.
The following additional packages will be installed:
  libonig5 libzip4
The following NEW packages will be installed:
  libonig5 libzip4 php8.1-curl php8.1-mbstring php8.1-xml php8.1-zip
0 upgraded, 6 newly installed, 0 to remove and 6 not upgraded.
Need to get 753 kB of archives.
After this operation, 2595 kB of additional disk space will be used.
Do you want to &lt;span class="k"&gt;continue&lt;/span&gt;? &lt;span class="o"&gt;[&lt;/span&gt;Y/n]
Get:1 http://azure.archive.ubuntu.com/ubuntu focal/universe amd64 libonig5 amd64 6.9.4-1 &lt;span class="o"&gt;[&lt;/span&gt;142 kB]
Get:2 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 libzip4 amd64 1.7.3-1+ubuntu20.04.1+deb.sury.org+2 &lt;span class="o"&gt;[&lt;/span&gt;55.1 kB]
Get:3 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 php8.1-curl amd64 8.1.3-1+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;33.7 kB]
Get:4 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 php8.1-mbstring amd64 8.1.3-1+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;392 kB]
Get:5 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 php8.1-xml amd64 8.1.3-1+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;106 kB]
Get:6 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 php8.1-zip amd64 8.1.3-1+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;24.2 kB]
Fetched 753 kB &lt;span class="k"&gt;in &lt;/span&gt;2s &lt;span class="o"&gt;(&lt;/span&gt;431 kB/s&lt;span class="o"&gt;)&lt;/span&gt;
Selecting previously unselected package libonig5:amd64.
&lt;span class="o"&gt;(&lt;/span&gt;Reading database ... 57864 files and directories currently installed.&lt;span class="o"&gt;)&lt;/span&gt;
Preparing to unpack .../0-libonig5_6.9.4-1_amd64.deb ...
Unpacking libonig5:amd64 &lt;span class="o"&gt;(&lt;/span&gt;6.9.4-1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libzip4:amd64.
Preparing to unpack .../1-libzip4_1.7.3-1+ubuntu20.04.1+deb.sury.org+2_amd64.deb ...
Unpacking libzip4:amd64 &lt;span class="o"&gt;(&lt;/span&gt;1.7.3-1+ubuntu20.04.1+deb.sury.org+2&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package php8.1-curl.
Preparing to unpack .../2-php8.1-curl_8.1.3-1+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking php8.1-curl &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package php8.1-mbstring.
Preparing to unpack .../3-php8.1-mbstring_8.1.3-1+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking php8.1-mbstring &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package php8.1-xml.
Preparing to unpack .../4-php8.1-xml_8.1.3-1+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking php8.1-xml &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package php8.1-zip.
Preparing to unpack .../5-php8.1-zip_8.1.3-1+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking php8.1-zip &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libzip4:amd64 &lt;span class="o"&gt;(&lt;/span&gt;1.7.3-1+ubuntu20.04.1+deb.sury.org+2&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up php8.1-curl &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...

Creating config file /etc/php/8.1/mods-available/curl.ini with new version
Setting up php8.1-xml &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...

Creating config file /etc/php/8.1/mods-available/dom.ini with new version

Creating config file /etc/php/8.1/mods-available/simplexml.ini with new version

Creating config file /etc/php/8.1/mods-available/xml.ini with new version

Creating config file /etc/php/8.1/mods-available/xmlreader.ini with new version

Creating config file /etc/php/8.1/mods-available/xmlwriter.ini with new version

Creating config file /etc/php/8.1/mods-available/xsl.ini with new version
Setting up php8.1-zip &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...

Creating config file /etc/php/8.1/mods-available/zip.ini with new version
Setting up libonig5:amd64 &lt;span class="o"&gt;(&lt;/span&gt;6.9.4-1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up php8.1-mbstring &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...

Creating config file /etc/php/8.1/mods-available/mbstring.ini with new version
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;libc-bin &lt;span class="o"&gt;(&lt;/span&gt;2.31-0ubuntu9.7&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;php8.1-cli &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
peterli@web-youtube-downloader:~&lt;span class="err"&gt;$&lt;/span&gt;
peterli@web-youtube-downloader:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nginx
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  fontconfig-config fonts-dejavu-core geoip-database libfontconfig1 libgd3 libgeoip1 libjbig0
  libjpeg-turbo8 libjpeg8 libnginx-mod-brotli libnginx-mod-http-geoip libnginx-mod-http-image-filter
  libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-ssl-ct libnginx-mod-stream
  libnginx-mod-stream-geoip libtiff5 libwebp6 libxpm4 nginx-common nginx-core
Suggested packages:
  libgd-tools geoip-bin fcgiwrap nginx-doc ssl-cert
The following NEW packages will be installed:
  fontconfig-config fonts-dejavu-core geoip-database libfontconfig1 libgd3 libgeoip1 libjbig0
  libjpeg-turbo8 libjpeg8 libnginx-mod-brotli libnginx-mod-http-geoip libnginx-mod-http-image-filter
  libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-ssl-ct libnginx-mod-stream
  libnginx-mod-stream-geoip libtiff5 libwebp6 libxpm4 nginx nginx-common nginx-core
0 upgraded, 23 newly installed, 0 to remove and 6 not upgraded.
Need to get 5859 kB of archives.
After this operation, 18.8 MB of additional disk space will be used.
Get:1 http://azure.archive.ubuntu.com/ubuntu focal/main amd64 fonts-dejavu-core all 2.37-1 &lt;span class="o"&gt;[&lt;/span&gt;1041 kB]
Get:2 http://azure.archive.ubuntu.com/ubuntu focal/main amd64 fontconfig-config all 2.13.1-2ubuntu3 &lt;span class="o"&gt;[&lt;/span&gt;28.8 kB]
Get:3 http://azure.archive.ubuntu.com/ubuntu focal/universe amd64 geoip-database all 20191224-2 &lt;span class="o"&gt;[&lt;/span&gt;3029 kB]
Get:4 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 libgd3 amd64 2.3.0-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;135 kB]
Get:5 http://azure.archive.ubuntu.com/ubuntu focal/main amd64 libfontconfig1 amd64 2.13.1-2ubuntu3 &lt;span class="o"&gt;[&lt;/span&gt;114 kB]
Get:6 http://azure.archive.ubuntu.com/ubuntu focal-updates/main amd64 libjpeg-turbo8 amd64 2.0.3-0ubuntu1.20.04.1 &lt;span class="o"&gt;[&lt;/span&gt;117 kB]
Get:7 http://azure.archive.ubuntu.com/ubuntu focal/main amd64 libjpeg8 amd64 8c-2ubuntu8 &lt;span class="o"&gt;[&lt;/span&gt;2194 B]
Get:8 http://azure.archive.ubuntu.com/ubuntu focal/main amd64 libjbig0 amd64 2.1-3.1build1 &lt;span class="o"&gt;[&lt;/span&gt;26.7 kB]
Get:9 http://azure.archive.ubuntu.com/ubuntu focal-updates/main amd64 libwebp6 amd64 0.6.1-2ubuntu0.20.04.1 &lt;span class="o"&gt;[&lt;/span&gt;185 kB]
Get:10 http://azure.archive.ubuntu.com/ubuntu focal-updates/main amd64 libtiff5 amd64 4.1.0+git191117-2ubuntu0.20.04.2 &lt;span class="o"&gt;[&lt;/span&gt;162 kB]
Get:11 http://azure.archive.ubuntu.com/ubuntu focal/main amd64 libxpm4 amd64 1:3.5.12-1 &lt;span class="o"&gt;[&lt;/span&gt;34.0 kB]
Get:12 http://azure.archive.ubuntu.com/ubuntu focal/universe amd64 libgeoip1 amd64 1.6.12-6build1 &lt;span class="o"&gt;[&lt;/span&gt;70.5 kB]
Get:13 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 nginx-common all 1.20.1-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;60.9 kB]
Get:14 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 libnginx-mod-brotli amd64 1.20.1-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;35.9 kB]
Get:15 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 libnginx-mod-http-geoip amd64 1.20.1-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;33.6 kB]
Get:16 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 libnginx-mod-http-image-filter amd64 1.20.1-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;37.2 kB]
Get:17 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 libnginx-mod-http-xslt-filter amd64 1.20.1-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;35.4 kB]
Get:18 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 libnginx-mod-mail amd64 1.20.1-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;67.6 kB]
Get:19 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 libnginx-mod-ssl-ct amd64 1.20.1-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;33.1 kB]
Get:20 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 libnginx-mod-stream amd64 1.20.1-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;90.6 kB]
Get:21 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 libnginx-mod-stream-geoip amd64 1.20.1-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;32.9 kB]
Get:22 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 nginx-core amd64 1.20.1-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;459 kB]
Get:23 http://ppa.launchpad.net/ondrej/nginx/ubuntu focal/main amd64 nginx all 1.20.1-2+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;28.0 kB]
Fetched 5859 kB &lt;span class="k"&gt;in &lt;/span&gt;4s &lt;span class="o"&gt;(&lt;/span&gt;1507 kB/s&lt;span class="o"&gt;)&lt;/span&gt;
Preconfiguring packages ...
Selecting previously unselected package fonts-dejavu-core.
&lt;span class="o"&gt;(&lt;/span&gt;Reading database ... 57922 files and directories currently installed.&lt;span class="o"&gt;)&lt;/span&gt;
Preparing to unpack .../00-fonts-dejavu-core_2.37-1_all.deb ...
Unpacking fonts-dejavu-core &lt;span class="o"&gt;(&lt;/span&gt;2.37-1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package fontconfig-config.
Preparing to unpack .../01-fontconfig-config_2.13.1-2ubuntu3_all.deb ...
Unpacking fontconfig-config &lt;span class="o"&gt;(&lt;/span&gt;2.13.1-2ubuntu3&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package geoip-database.
Preparing to unpack .../02-geoip-database_20191224-2_all.deb ...
Unpacking geoip-database &lt;span class="o"&gt;(&lt;/span&gt;20191224-2&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libfontconfig1:amd64.
Preparing to unpack .../03-libfontconfig1_2.13.1-2ubuntu3_amd64.deb ...
Unpacking libfontconfig1:amd64 &lt;span class="o"&gt;(&lt;/span&gt;2.13.1-2ubuntu3&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libjpeg-turbo8:amd64.
Preparing to unpack .../04-libjpeg-turbo8_2.0.3-0ubuntu1.20.04.1_amd64.deb ...
Unpacking libjpeg-turbo8:amd64 &lt;span class="o"&gt;(&lt;/span&gt;2.0.3-0ubuntu1.20.04.1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libjpeg8:amd64.
Preparing to unpack .../05-libjpeg8_8c-2ubuntu8_amd64.deb ...
Unpacking libjpeg8:amd64 &lt;span class="o"&gt;(&lt;/span&gt;8c-2ubuntu8&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libjbig0:amd64.
Preparing to unpack .../06-libjbig0_2.1-3.1build1_amd64.deb ...
Unpacking libjbig0:amd64 &lt;span class="o"&gt;(&lt;/span&gt;2.1-3.1build1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libwebp6:amd64.
Preparing to unpack .../07-libwebp6_0.6.1-2ubuntu0.20.04.1_amd64.deb ...
Unpacking libwebp6:amd64 &lt;span class="o"&gt;(&lt;/span&gt;0.6.1-2ubuntu0.20.04.1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libtiff5:amd64.
Preparing to unpack .../08-libtiff5_4.1.0+git191117-2ubuntu0.20.04.2_amd64.deb ...
Unpacking libtiff5:amd64 &lt;span class="o"&gt;(&lt;/span&gt;4.1.0+git191117-2ubuntu0.20.04.2&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libxpm4:amd64.
Preparing to unpack .../09-libxpm4_1%3a3.5.12-1_amd64.deb ...
Unpacking libxpm4:amd64 &lt;span class="o"&gt;(&lt;/span&gt;1:3.5.12-1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libgd3:amd64.
Preparing to unpack .../10-libgd3_2.3.0-2+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking libgd3:amd64 &lt;span class="o"&gt;(&lt;/span&gt;2.3.0-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libgeoip1:amd64.
Preparing to unpack .../11-libgeoip1_1.6.12-6build1_amd64.deb ...
Unpacking libgeoip1:amd64 &lt;span class="o"&gt;(&lt;/span&gt;1.6.12-6build1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package nginx-common.
Preparing to unpack .../12-nginx-common_1.20.1-2+ubuntu20.04.1+deb.sury.org+1_all.deb ...
Unpacking nginx-common &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libnginx-mod-brotli.
Preparing to unpack .../13-libnginx-mod-brotli_1.20.1-2+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking libnginx-mod-brotli &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libnginx-mod-http-geoip.
Preparing to unpack .../14-libnginx-mod-http-geoip_1.20.1-2+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking libnginx-mod-http-geoip &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libnginx-mod-http-image-filter.
Preparing to unpack .../15-libnginx-mod-http-image-filter_1.20.1-2+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking libnginx-mod-http-image-filter &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libnginx-mod-http-xslt-filter.
Preparing to unpack .../16-libnginx-mod-http-xslt-filter_1.20.1-2+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking libnginx-mod-http-xslt-filter &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libnginx-mod-mail.
Preparing to unpack .../17-libnginx-mod-mail_1.20.1-2+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking libnginx-mod-mail &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libnginx-mod-ssl-ct.
Preparing to unpack .../18-libnginx-mod-ssl-ct_1.20.1-2+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking libnginx-mod-ssl-ct &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libnginx-mod-stream.
Preparing to unpack .../19-libnginx-mod-stream_1.20.1-2+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking libnginx-mod-stream &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package libnginx-mod-stream-geoip.
Preparing to unpack .../20-libnginx-mod-stream-geoip_1.20.1-2+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking libnginx-mod-stream-geoip &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package nginx-core.
Preparing to unpack .../21-nginx-core_1.20.1-2+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking nginx-core &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Selecting previously unselected package nginx.
Preparing to unpack .../22-nginx_1.20.1-2+ubuntu20.04.1+deb.sury.org+1_all.deb ...
Unpacking nginx &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libxpm4:amd64 &lt;span class="o"&gt;(&lt;/span&gt;1:3.5.12-1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up nginx-common &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libjbig0:amd64 &lt;span class="o"&gt;(&lt;/span&gt;2.1-3.1build1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libnginx-mod-http-xslt-filter &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libwebp6:amd64 &lt;span class="o"&gt;(&lt;/span&gt;0.6.1-2ubuntu0.20.04.1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up fonts-dejavu-core &lt;span class="o"&gt;(&lt;/span&gt;2.37-1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libjpeg-turbo8:amd64 &lt;span class="o"&gt;(&lt;/span&gt;2.0.3-0ubuntu1.20.04.1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libnginx-mod-brotli &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libgeoip1:amd64 &lt;span class="o"&gt;(&lt;/span&gt;1.6.12-6build1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up geoip-database &lt;span class="o"&gt;(&lt;/span&gt;20191224-2&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libjpeg8:amd64 &lt;span class="o"&gt;(&lt;/span&gt;8c-2ubuntu8&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libnginx-mod-mail &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up fontconfig-config &lt;span class="o"&gt;(&lt;/span&gt;2.13.1-2ubuntu3&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libnginx-mod-stream &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libnginx-mod-ssl-ct &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libnginx-mod-stream-geoip &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libnginx-mod-http-geoip &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libtiff5:amd64 &lt;span class="o"&gt;(&lt;/span&gt;4.1.0+git191117-2ubuntu0.20.04.2&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libfontconfig1:amd64 &lt;span class="o"&gt;(&lt;/span&gt;2.13.1-2ubuntu3&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libgd3:amd64 &lt;span class="o"&gt;(&lt;/span&gt;2.3.0-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up libnginx-mod-http-image-filter &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up nginx-core &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up nginx &lt;span class="o"&gt;(&lt;/span&gt;1.20.1-2+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;ufw &lt;span class="o"&gt;(&lt;/span&gt;0.36-6ubuntu1&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;systemd &lt;span class="o"&gt;(&lt;/span&gt;245.4-4ubuntu3.15&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;man-db &lt;span class="o"&gt;(&lt;/span&gt;2.9.1-1&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;libc-bin &lt;span class="o"&gt;(&lt;/span&gt;2.31-0ubuntu9.7&lt;span class="o"&gt;)&lt;/span&gt; ...
peterli@web-youtube-downloader:~&lt;span class="err"&gt;$&lt;/span&gt;
peterli@web-youtube-downloader:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; git
Reading package lists... Done
Building dependency tree
Reading state information... Done
git is already the newest version &lt;span class="o"&gt;(&lt;/span&gt;1:2.25.1-1ubuntu3.2&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
git &lt;span class="nb"&gt;set &lt;/span&gt;to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 6 not upgraded.
peterli@web-youtube-downloader:~&lt;span class="err"&gt;$&lt;/span&gt;
peterli@web-youtube-downloader:~&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www/html/
peterli@web-youtube-downloader:/var/www/html&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;git clone https://github.com/peter279k/web-youtube-downloader
Cloning into &lt;span class="s1"&gt;'web-youtube-downloader'&lt;/span&gt;...
remote: Enumerating objects: 109, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;109/109&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;69/69&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Total 109 &lt;span class="o"&gt;(&lt;/span&gt;delta 59&lt;span class="o"&gt;)&lt;/span&gt;, reused 80 &lt;span class="o"&gt;(&lt;/span&gt;delta 31&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused 0
Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;109/109&lt;span class="o"&gt;)&lt;/span&gt;, 15.44 KiB | 1.71 MiB/s, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;59/59&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
peterli@web-youtube-downloader:/var/www/html&lt;span class="err"&gt;$&lt;/span&gt;
peterli@web-youtube-downloader:/var/www/html&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;web-youtube-downloader/
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;dos2unix
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  dos2unix
0 upgraded, 1 newly installed, 0 to remove and 6 not upgraded.
Need to get 374 kB of archives.
After this operation, 1342 kB of additional disk space will be used.
Get:1 http://azure.archive.ubuntu.com/ubuntu focal/universe amd64 dos2unix amd64 7.4.0-2 &lt;span class="o"&gt;[&lt;/span&gt;374 kB]
Fetched 374 kB &lt;span class="k"&gt;in &lt;/span&gt;0s &lt;span class="o"&gt;(&lt;/span&gt;15.5 MB/s&lt;span class="o"&gt;)&lt;/span&gt;
Selecting previously unselected package dos2unix.
&lt;span class="o"&gt;(&lt;/span&gt;Reading database ... 58185 files and directories currently installed.&lt;span class="o"&gt;)&lt;/span&gt;
Preparing to unpack .../dos2unix_7.4.0-2_amd64.deb ...
Unpacking dos2unix &lt;span class="o"&gt;(&lt;/span&gt;7.4.0-2&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up dos2unix &lt;span class="o"&gt;(&lt;/span&gt;7.4.0-2&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;man-db &lt;span class="o"&gt;(&lt;/span&gt;2.9.1-1&lt;span class="o"&gt;)&lt;/span&gt; ...
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="err"&gt;$&lt;/span&gt;
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; ./build.sh
Cloning Web YouTube Downloader...
Cloning into &lt;span class="s1"&gt;'youtube-downloader'&lt;/span&gt;...
remote: Enumerating objects: 574, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;189/189&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;82/82&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Total 574 &lt;span class="o"&gt;(&lt;/span&gt;delta 118&lt;span class="o"&gt;)&lt;/span&gt;, reused 107 &lt;span class="o"&gt;(&lt;/span&gt;delta 107&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused 385
Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;574/574&lt;span class="o"&gt;)&lt;/span&gt;, 139.40 KiB | 17.42 MiB/s, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;336/336&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
All settings correct &lt;span class="k"&gt;for &lt;/span&gt;using Composer
Downloading...

Composer &lt;span class="o"&gt;(&lt;/span&gt;version 2.2.7&lt;span class="o"&gt;)&lt;/span&gt; successfully installed to: /var/www/html/web-youtube-downloader/composer.phar
Use it: php composer.phar

Do not run Composer as root/super user! See https://getcomposer.org/root &lt;span class="k"&gt;for &lt;/span&gt;details
Installing dependencies from lock file
Verifying lock file contents can be installed on current platform.
Package operations: 2 installs, 0 updates, 0 removals
As there is no &lt;span class="s1"&gt;'unzip'&lt;/span&gt; nor &lt;span class="s1"&gt;'7z'&lt;/span&gt; &lt;span class="nb"&gt;command &lt;/span&gt;installed zip files are being unpacked using the PHP zip extension.
This may cause invalid reports of corrupted archives. Besides, any UNIX permissions &lt;span class="o"&gt;(&lt;/span&gt;e.g. executable&lt;span class="o"&gt;)&lt;/span&gt; defined &lt;span class="k"&gt;in &lt;/span&gt;the archives will be lost.
Installing &lt;span class="s1"&gt;'unzip'&lt;/span&gt; or &lt;span class="s1"&gt;'7z'&lt;/span&gt; may remediate them.
  - Installing athlon1600/php-curl-client &lt;span class="o"&gt;(&lt;/span&gt;v1.1.3&lt;span class="o"&gt;)&lt;/span&gt;: Extracting archive
  - Installing athlon1600/php-curl-file-downloader &lt;span class="o"&gt;(&lt;/span&gt;v1.0.2&lt;span class="o"&gt;)&lt;/span&gt;: Extracting archive
Package phpunit/php-token-stream is abandoned, you should avoid using it. No replacement was suggested.
Generating autoload files
dos2unix: &lt;span class="k"&gt;*&lt;/span&gt;.html: No such file or directory
dos2unix: Skipping &lt;span class="k"&gt;*&lt;/span&gt;.html, not a regular file.
dos2unix: &lt;span class="k"&gt;*&lt;/span&gt;.php: No such file or directory
dos2unix: Skipping &lt;span class="k"&gt;*&lt;/span&gt;.php, not a regular file.
Building Web YouTube Downloader has been &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/nginx/sites-available/def
ault
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf &lt;span class="nb"&gt;test &lt;/span&gt;is successful
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload nginx.service
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="err"&gt;$&lt;/span&gt;
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;php8.1-fpm &lt;span class="nt"&gt;-y&lt;/span&gt;
Reading package lists... Done
Building dependency tree
Reading state information... Done
Suggested packages:
  php-pear
The following NEW packages will be installed:
  php8.1-fpm
0 upgraded, 1 newly installed, 0 to remove and 6 not upgraded.
Need to get 1669 kB of archives.
After this operation, 5608 kB of additional disk space will be used.
Get:1 http://ppa.launchpad.net/ondrej/php/ubuntu focal/main amd64 php8.1-fpm amd64 8.1.3-1+ubuntu20.04.1+deb.sury.org+1 &lt;span class="o"&gt;[&lt;/span&gt;1669 kB]
Fetched 1669 kB &lt;span class="k"&gt;in &lt;/span&gt;1s &lt;span class="o"&gt;(&lt;/span&gt;2444 kB/s&lt;span class="o"&gt;)&lt;/span&gt;
Selecting previously unselected package php8.1-fpm.
&lt;span class="o"&gt;(&lt;/span&gt;Reading database ... 58285 files and directories currently installed.&lt;span class="o"&gt;)&lt;/span&gt;
Preparing to unpack .../php8.1-fpm_8.1.3-1+ubuntu20.04.1+deb.sury.org+1_amd64.deb ...
Unpacking php8.1-fpm &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
Setting up php8.1-fpm &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...

Creating config file /etc/php/8.1/fpm/php.ini with new version
Created symlink /etc/systemd/system/multi-user.target.wants/php8.1-fpm.service → /lib/systemd/system/php8.1-fpm.service.
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;man-db &lt;span class="o"&gt;(&lt;/span&gt;2.9.1-1&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;systemd &lt;span class="o"&gt;(&lt;/span&gt;245.4-4ubuntu3.15&lt;span class="o"&gt;)&lt;/span&gt; ...
Processing triggers &lt;span class="k"&gt;for &lt;/span&gt;php8.1-fpm &lt;span class="o"&gt;(&lt;/span&gt;8.1.3-1+ubuntu20.04.1+deb.sury.org+1&lt;span class="o"&gt;)&lt;/span&gt; ...
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="err"&gt;$&lt;/span&gt;
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/nginx/sites-available/default
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/nginx/sites-available/default
&lt;span class="c"&gt;##&lt;/span&gt;
&lt;span class="c"&gt;# You should look at the following URL's in order to grasp a solid understanding&lt;/span&gt;
&lt;span class="c"&gt;# of Nginx configuration files in order to fully unleash the power of Nginx.&lt;/span&gt;
&lt;span class="c"&gt;# https://www.nginx.com/resources/wiki/start/&lt;/span&gt;
&lt;span class="c"&gt;# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/&lt;/span&gt;
&lt;span class="c"&gt;# https://wiki.debian.org/Nginx/DirectoryStructure&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# In most cases, administrators will remove this file from sites-enabled/ and&lt;/span&gt;
&lt;span class="c"&gt;# leave it as reference inside of sites-available where it will continue to be&lt;/span&gt;
&lt;span class="c"&gt;# updated by the nginx packaging team.&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# This file will automatically load configuration files provided by other&lt;/span&gt;
&lt;span class="c"&gt;# applications, such as Drupal or Wordpress. These applications will be made&lt;/span&gt;
&lt;span class="c"&gt;# available underneath a path with that package name, such as /drupal8.&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.&lt;/span&gt;
&lt;span class="c"&gt;##&lt;/span&gt;

&lt;span class="c"&gt;# Default server configuration&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
server &lt;span class="o"&gt;{&lt;/span&gt;
        listen 80 default_server&lt;span class="p"&gt;;&lt;/span&gt;
        listen &lt;span class="o"&gt;[&lt;/span&gt;::]:80 default_server&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c"&gt;# SSL configuration&lt;/span&gt;
        &lt;span class="c"&gt;#&lt;/span&gt;
        &lt;span class="c"&gt;# listen 443 ssl default_server;&lt;/span&gt;
        &lt;span class="c"&gt;# listen [::]:443 ssl default_server;&lt;/span&gt;
        &lt;span class="c"&gt;#&lt;/span&gt;
        &lt;span class="c"&gt;# Note: You should disable gzip for SSL traffic.&lt;/span&gt;
        &lt;span class="c"&gt;# See: https://bugs.debian.org/773332&lt;/span&gt;
        &lt;span class="c"&gt;#&lt;/span&gt;
        &lt;span class="c"&gt;# Read up on ssl_ciphers to ensure a secure configuration.&lt;/span&gt;
        &lt;span class="c"&gt;# See: https://bugs.debian.org/765782&lt;/span&gt;
        &lt;span class="c"&gt;#&lt;/span&gt;
        &lt;span class="c"&gt;# Self signed certs generated by the ssl-cert package&lt;/span&gt;
        &lt;span class="c"&gt;# Don't use them in a production server!&lt;/span&gt;
        &lt;span class="c"&gt;#&lt;/span&gt;
        &lt;span class="c"&gt;# include snippets/snakeoil.conf;&lt;/span&gt;

        root /var/www/html/web-youtube-downloader/youtube-downloader/public&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c"&gt;# Add index.php to the list if you are using PHP&lt;/span&gt;
        index index.html index.htm index.nginx-debian.html&lt;span class="p"&gt;;&lt;/span&gt;

        server_name _&lt;span class="p"&gt;;&lt;/span&gt;

        location / &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="c"&gt;# First attempt to serve request as file, then&lt;/span&gt;
                &lt;span class="c"&gt;# as directory, then fall back to displaying a 404.&lt;/span&gt;
                try_files &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;/ &lt;span class="o"&gt;=&lt;/span&gt;404&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;# pass PHP scripts to FastCGI server&lt;/span&gt;
        &lt;span class="c"&gt;#&lt;/span&gt;
        location ~ &lt;span class="se"&gt;\.&lt;/span&gt;php&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
                include snippets/fastcgi-php.conf&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c"&gt;#&lt;/span&gt;
        &lt;span class="c"&gt;#       # With php-fpm (or other unix sockets):&lt;/span&gt;
                fastcgi_pass unix:/run/php/php8.1-fpm.sock&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c"&gt;#       # With php-cgi (or other tcp sockets):&lt;/span&gt;
        &lt;span class="c"&gt;#       fastcgi_pass 127.0.0.1:9000;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;# deny access to .htaccess files, if Apache's document root&lt;/span&gt;
        &lt;span class="c"&gt;# concurs with nginx's one&lt;/span&gt;
        &lt;span class="c"&gt;#&lt;/span&gt;
        &lt;span class="c"&gt;#location ~ /\.ht {&lt;/span&gt;
        &lt;span class="c"&gt;#       deny all;&lt;/span&gt;
        &lt;span class="c"&gt;#}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;span class="c"&gt;# Virtual Host configuration for example.com&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# You can move that to a different file under sites-available/ and symlink that&lt;/span&gt;
&lt;span class="c"&gt;# to sites-enabled/ to enable it.&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#server {&lt;/span&gt;
&lt;span class="c"&gt;#       listen 80;&lt;/span&gt;
&lt;span class="c"&gt;#       listen [::]:80;&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#       server_name example.com;&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#       root /var/www/example.com;&lt;/span&gt;
&lt;span class="c"&gt;#       index index.html;&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#       location / {&lt;/span&gt;
&lt;span class="c"&gt;#               try_files $uri $uri/ =404;&lt;/span&gt;
&lt;span class="c"&gt;#       }&lt;/span&gt;
&lt;span class="c"&gt;#}&lt;/span&gt;
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf &lt;span class="nb"&gt;test &lt;/span&gt;is successful
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload nginx.service
peterli@web-youtube-downloader:/var/www/html/web-youtube-downloader&lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;After running these above commands, open the web browser and enter the &lt;code&gt;20.121.186.160&lt;/code&gt; it will get the following picture:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gasjs5vc8zli9sv04cm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gasjs5vc8zli9sv04cm.png" alt="IP with web browser" width="800" height="274"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;The category is about Computing Captains and I use the &lt;a href="https://azure.microsoft.com/en-us/services/virtual-machines/"&gt;Azure Virtual Machines&lt;/a&gt; to deploy my Web YouTube Downloader!&lt;/p&gt;
&lt;h3&gt;
  
  
  Link to Code on GitHub
&lt;/h3&gt;

&lt;p&gt;Here is the link about I develop and use in this post:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/peter279k"&gt;
        peter279k
      &lt;/a&gt; / &lt;a href="https://github.com/peter279k/web-youtube-downloader"&gt;
        web-youtube-downloader
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This is the web-based youtube-downloader service
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Web YouTube Downloader&lt;/h1&gt;

&lt;/div&gt;

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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;This is a web-based YouTube downloading website for my family!&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Here is the &lt;a href="https://youtube.peterli.website" rel="nofollow"&gt;link&lt;/a&gt; for this repository demonstration.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;

&lt;p&gt;Here are some repositories to accomplish this web-based service!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Athlon1600/youtube-downloader"&gt;Athlon1600/youtube-downloader&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/yt-dlp/yt-dlp"&gt;yt-dlp/yt-dlp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/peter279k/web-youtube-downloader"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The completed running command histories are available on above section.&lt;/li&gt;
&lt;li&gt;Here is the useful &lt;a href="https://docs.microsoft.com/en-us/azure/virtual-machines/linux/quick-create-portal"&gt;reference&lt;/a&gt; to let me know how to create the virtual machine in Azure Portal :).&lt;/li&gt;
&lt;li&gt;My completed picture for Azure VM description is as follows:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcd8ylgqjns2da6qa49ty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcd8ylgqjns2da6qa49ty.png" alt="Azure VM decription" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azuretrialhack</category>
      <category>microsoft</category>
      <category>azure</category>
    </item>
    <item>
      <title>Introduce to my Taiwan COVID-19 news website and crawler</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Tue, 07 Dec 2021 15:27:28 +0000</pubDate>
      <link>https://dev.to/peter279k/introduce-to-my-taiwan-covid-19-news-website-and-crawler-1o58</link>
      <guid>https://dev.to/peter279k/introduce-to-my-taiwan-covid-19-news-website-and-crawler-1o58</guid>
      <description>&lt;h2&gt;
  
  
  Instructions
&lt;/h2&gt;

&lt;p&gt;In Taiwan, it's COVID-19 outbreak on May 13 and there're about 100 local cases every day. And it's zero local case since October.&lt;/p&gt;

&lt;p&gt;At that moment, I'm really concerned about daily local cases so I develop this project and publish it to the &lt;a href="https://github.com/peter279k/covid19-tw-news"&gt;GitHub&lt;/a&gt;. I use the cron job feature to fetch the latest COVID-19 news and publish my new web page during GitHub action running. &lt;/p&gt;

&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;My completed workflow files are available &lt;a href="https://github.com/peter279k/covid19-tw-news/tree/master/.github/workflows"&gt;here&lt;/a&gt; and it includes following YAML files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fetcher.yml&lt;/code&gt;, this YAML file is for fetching latest COVID-19 news and store them to be JSON file. This web crawler is written in Python. And It will be run every hour.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;web_build.yml&lt;/code&gt;, this YAML file is for publishing new website and loading new JSON file. This website is written in JavaScript with Vue.js framework. And it will be run every seventy minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;This category is for DIY-Deployments and I hope developers love this and can be referenced :-).&lt;/p&gt;

&lt;h3&gt;
  
  
  YAML files and link to repository
&lt;/h3&gt;

&lt;p&gt;Here are repository preview and completed codes about above two YAML files:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/peter279k"&gt;
        peter279k
      &lt;/a&gt; / &lt;a href="https://github.com/peter279k/covid19-tw-news"&gt;
        covid19-tw-news
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The Taiwan COVID-19 News
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;COVID-19 Taiwan News&lt;/h1&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;References&lt;/h1&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vuejs.org/" rel="nofollow"&gt;https://vuejs.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://getbootstrap.com/docs/5.0/getting-started/introduction" rel="nofollow"&gt;https://getbootstrap.com/docs/5.0/getting-started/introduction&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Data Sources (資料來源)&lt;/h1&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://heho.com.tw/page/page_number/?s=%E5%85%A8%E5%8F%B0%E6%9F%93%E7%96%AB%E8%B6%B3%E8%B7%A1%E4%B8%80%E6%AC%A1%E7%9C%8B+" rel="nofollow"&gt;https://heho.com.tw/page/page_number/?s=%E5%85%A8%E5%8F%B0%E6%9F%93%E7%96%AB%E8%B6%B3%E8%B7%A1%E4%B8%80%E6%AC%A1%E7%9C%8B+&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://od.cdc.gov.tw/icb/%E6%8C%87%E5%AE%9A%E6%8E%A1%E6%AA%A2%E9%86%AB%E9%99%A2%E6%B8%85%E5%96%AE.csv" rel="nofollow"&gt;http://od.cdc.gov.tw/icb/%E6%8C%87%E5%AE%9A%E6%8E%A1%E6%AA%A2%E9%86%AB%E9%99%A2%E6%B8%85%E5%96%AE.csv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mohw.gov.tw/rss-16-1.html" rel="nofollow"&gt;https://www.mohw.gov.tw/rss-16-1.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://od.cdc.gov.tw/eic/Day_Confirmation_Age_County_Gender_19CoV.csv" rel="nofollow"&gt;https://od.cdc.gov.tw/eic/Day_Confirmation_Age_County_Gender_19CoV.csv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://od.cdc.gov.tw/eic/covid19/covid19_global_cases_and_deaths.csv" rel="nofollow"&gt;https://od.cdc.gov.tw/eic/covid19/covid19_global_cases_and_deaths.csv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/peter279k/covid19-tw-news"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fetcher.yml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update CSV Dataset Records from Taiwan CDC website&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-and-deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get working copy&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@master&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python &lt;/span&gt;&lt;span class="m"&gt;3.8&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Requirements&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install -r requirements.txt&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update COVD-19 Labs&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python Fetcher/LabFetcher.py&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update MOHW RSS News&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python Fetcher/MohwRssFetcher.py&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update COVID-19 global cases and deaths&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python Fetcher/GlobalCasesFetcher.py&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update COVID-19 TW datasets&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python Fetcher/DailyCovid19TW.py&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Copy JSON files to assets folder&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cp datasets/*.json web/src/assets/&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Commit and push if it changed&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git config user.name "peter279k"&lt;/span&gt;
          &lt;span class="s"&gt;git config user.email "peter279k@gmail.com"&lt;/span&gt;
          &lt;span class="s"&gt;git add -A&lt;/span&gt;
          &lt;span class="s"&gt;timestamp=$(date -u)&lt;/span&gt;
          &lt;span class="s"&gt;git commit -m "Last Commit: ${timestamp}(TW)" || exit 0&lt;/span&gt;
          &lt;span class="s"&gt;git push origin master&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;web_build.yml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Web&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Deploy'&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;10&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-and-deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout 🛎️&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2.3.1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;persist-credentials&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install and Build 🔧&lt;/span&gt;
        &lt;span class="na"&gt;working-directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;cp .env.example .env&lt;/span&gt;
          &lt;span class="s"&gt;export VUE_APP_MAPKEY=${{ secrets.VUE_APP_MAPKEY }}&lt;/span&gt;
          &lt;span class="s"&gt;sed -i -e "s/MAP_KEY/$VUE_APP_MAPKEY/g" ./.env&lt;/span&gt;
          &lt;span class="s"&gt;npm install&lt;/span&gt;
          &lt;span class="s"&gt;npm run build&lt;/span&gt;
          &lt;span class="s"&gt;cd dist&lt;/span&gt;
          &lt;span class="s"&gt;cp index.html 404.html&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy 🚀&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;JamesIves/github-pages-deploy-action@3.6.2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GIT_CONFIG_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;peter279k"&lt;/span&gt;
          &lt;span class="na"&gt;GIT_CONFIG_EMAIL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;peter279k@gmail.com"&lt;/span&gt;
          &lt;span class="na"&gt;SINGLE_COMMIT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;BRANCH&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gh-pages&lt;/span&gt;
          &lt;span class="na"&gt;FOLDER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web//dist&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;Here are some useful references about GitHub action workflows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows"&gt;Events trigger about GitHub Workflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/actions/security-guides/encrypted-secrets"&gt;Encrypted secrets settings about GitHub Workflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>actionshackathon21</category>
      <category>github</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Emask Notifier - DigitalOcean App Platform Hackathon</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Sat, 09 Jan 2021 19:11:26 +0000</pubDate>
      <link>https://dev.to/peter279k/emask-notifier-digitalocean-app-platform-hackathon-3epl</link>
      <guid>https://dev.to/peter279k/emask-notifier-digitalocean-app-platform-hackathon-3epl</guid>
      <description>&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;Emask Notifier is a background worker that running a process and managed by Supervisor daemon.&lt;/p&gt;

&lt;p&gt;This notifier can monitor this &lt;a href="https://emask.taiwan.gov.tw/msk/index.jsp"&gt;Emask website&lt;/a&gt; and check whether the e-Mask can be available for buying.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx62erbw7ohh2hh1y6z9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx62erbw7ohh2hh1y6z9g.png" alt="Emask Website" width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7c6sjk45ykcahsgtizhi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7c6sjk45ykcahsgtizhi.png" alt="Emask Website(EN)" width="800" height="131"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this moment, it doesn't have the public API service for everyone because it's only for people in Taiwan.&lt;/p&gt;

&lt;p&gt;To be private usage, it's only for my friends to let them receive the notification message and know the masks are available to buy.&lt;/p&gt;

&lt;p&gt;In the future, it will have the contact form to let people in Taiwan can allow this notifier sends notification via Vonage SMS API to specific cell-phone number.&lt;/p&gt;

&lt;h3&gt;
  
  
  Category Submission:
&lt;/h3&gt;

&lt;p&gt;Program for the People&lt;/p&gt;

&lt;h3&gt;
  
  
  App Link
&lt;/h3&gt;

&lt;p&gt;At this moment, it's not available because this is the notifier and it's running as the background process on the targeted operating system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Screenshots
&lt;/h3&gt;

&lt;p&gt;If someone is in the default phone lists, it will get following SMS message:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F13e254o4ug4d16hxipg3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F13e254o4ug4d16hxipg3.jpg" alt="SMS (TW)" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Description
&lt;/h3&gt;

&lt;p&gt;If developers want to setup own notifier for this eMask notifier, it's very easy to build.&lt;/p&gt;

&lt;p&gt;And the completed README is available &lt;a href="https://github.com/peter279k/emask-notifier/blob/master/README.md#emask-notifier-for-notifierphp-installation"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Source Code
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/peter279k"&gt;
        peter279k
      &lt;/a&gt; / &lt;a href="https://github.com/peter279k/emask-notifier"&gt;
        emask-notifier
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The e-mask notifier for improve https://emask.taiwan.gov.tw/msk/index.jsp feature
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;emask-notifier&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Introduction&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Using the Nexmo API to make SMS message with specific phone number and user.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Emask Notifier Installation (Deprecated)&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Set up a Nexmo account on &lt;a href="https://dashboard.nexmo.com/" rel="nofollow"&gt;Nexmo developer site&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Creating &lt;code&gt;phone.csv&lt;/code&gt; and locate this CSV file is with &lt;code&gt;emask-notifier.sh&lt;/code&gt; on same directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the format is as follows:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;user_name,user_phone
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Set &lt;code&gt;api_key&lt;/code&gt; as a system environment variable with &lt;code&gt;echo 'export api_key="{your_api_key}"' | sudo tee -a /etc/environment&lt;/code&gt; on &lt;code&gt;/etc/environment&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;api_secret&lt;/code&gt; as a system environment variable with &lt;code&gt;echo 'export api_secret="{your_api_secret}"' | sudo tee -a /etc/environment&lt;/code&gt; on &lt;code&gt;/etc/environment&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;cd /path/to/emask-notifier/ &amp;amp;&amp;amp; ./emask-notifier.sh&lt;/code&gt; as a Cronjob to let this Bash script do work automatically.&lt;/li&gt;
&lt;li&gt;Done. Happy to do notification for your friends :)!&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Emask Notifier Uninstallation (Deprecated)&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Remove &lt;code&gt;api_key&lt;/code&gt; system environment variable on &lt;code&gt;/etc/environment&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Remove &lt;code&gt;api_secret&lt;/code&gt; system environment variable on &lt;code&gt;/etc/environment&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Remove this Cronjob work.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Emask Notifier for notifier.php Installation&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Checking the &lt;code&gt;supervisor&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;cron&lt;/code&gt; commands have…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/peter279k/emask-notifier"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Permissive License
&lt;/h3&gt;

&lt;p&gt;The license is under MIT and available &lt;a href="https://github.com/peter279k/emask-notifier/blob/master/LICENSE"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;When the COVID-19 is ravaging the world, the mask is very important for people to avoid droplet infection.&lt;/p&gt;

&lt;p&gt;Fortunately, the Taiwan government provides the e-mask website for Taiwan people to buy ten masks per two weeks.&lt;/p&gt;

&lt;p&gt;However, the website doesn't have the subscription service that sending the notification via SMS to people and notify them buying masks.&lt;/p&gt;

&lt;p&gt;That's the main reason why I build this notifier worker and setup the process running on the operating system :).&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources/Info
&lt;/h3&gt;

&lt;p&gt;I'm grateful for these services to help me to complete this notifier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.vonage.com"&gt;Vonage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com"&gt;DigitalOcean&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.php.net"&gt;PHP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://supervisord.org"&gt;Supervisor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gnu.org/software/mcron/manual/html_node/Crontab-file.html"&gt;Cronjob&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dohackathon</category>
      <category>php</category>
      <category>supervisor</category>
      <category>mask</category>
    </item>
    <item>
      <title>Getting started with GitHub Action to deploy website continuously!</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Wed, 16 Sep 2020 18:43:43 +0000</pubDate>
      <link>https://dev.to/peter279k/getting-started-with-github-action-to-deploy-website-continuously-2gn0</link>
      <guid>https://dev.to/peter279k/getting-started-with-github-action-to-deploy-website-continuously-2gn0</guid>
      <description>&lt;h1&gt;
  
  
  Instructions
&lt;/h1&gt;

&lt;p&gt;Recently I participated this &lt;a href="https://2020datathon.wixsite.com/hack" rel="noopener noreferrer"&gt;competition&lt;/a&gt; and our team decide to do data analysis for invoice, address normalizing and weather data sets.&lt;/p&gt;

&lt;p&gt;However, I don't have much time to work on above data analysis website. I need to join the &lt;a href="https://hitcon.org/2020/" rel="noopener noreferrer"&gt;HITCON 2020&lt;/a&gt; at the same time.&lt;/p&gt;

&lt;p&gt;And I want to let my website publish to specific website continuously.&lt;/p&gt;

&lt;p&gt;In this tutorial, I will show how to use the GitHub Action to publish my website continuously/easily!&lt;/p&gt;

&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;My workflow is very simple, and every upcoming commits will be published to my specific &lt;a href="https://2020datathon.peterli.website/" rel="noopener noreferrer"&gt;website&lt;/a&gt; and I can look at the latest web page instantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;My category is about the DIY deployment and I will show my deployment YAML file on the next section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;

&lt;p&gt;This GitHub repository is as follows:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/peter279k" rel="noopener noreferrer"&gt;
        peter279k
      &lt;/a&gt; / &lt;a href="https://github.com/peter279k/2020-datathon" rel="noopener noreferrer"&gt;
        2020-datathon
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The Datathon 2020 for demonstration website.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;2020-datathon&lt;/h1&gt;

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

&lt;/div&gt;
&lt;p&gt;Here are the steps to configure and setup &lt;code&gt;2020-datathon&lt;/code&gt; website&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using the &lt;code&gt;cp js/config.js.sample js/config.js&lt;/code&gt; to copy a &lt;code&gt;config.js&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;token&lt;/code&gt; on &lt;code&gt;config.js&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;We assume that the &lt;code&gt;docker&lt;/code&gt; and &lt;code&gt;docker-compose&lt;/code&gt; commands are installed on Ubuntu 18.04 or Ubuntu 16.04.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Demo&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Using the &lt;code&gt;docker-compose up -d&lt;/code&gt; to let this website run as a Docker container on current operating system background.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Slide&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;N/A&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/peter279k/2020-datathon" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;My workflow steps are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone this repository via &lt;code&gt;git clone github_repository_url&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add some codes.&lt;/li&gt;
&lt;li&gt;Write a commit for this change.&lt;/li&gt;
&lt;li&gt;Pushing the latest changes and commit via &lt;code&gt;git push github_repository_url&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Done!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the last thing is about the &lt;code&gt;deploy.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Copy repository contents via scp to DigitalOcean site&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appleboy/scp-action@master&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.HOST }}&lt;/span&gt;
        &lt;span class="na"&gt;USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.USERNAME }}&lt;/span&gt;
        &lt;span class="na"&gt;PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.PORT }}&lt;/span&gt;
        &lt;span class="na"&gt;KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SSHKEY }}&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;."&lt;/span&gt;
        &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/www/2020datathon.peterli.website/html"&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Executing remote command to create the Leaflet map token and copy sample data sets&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;appleboy/ssh-action@master&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.HOST }}&lt;/span&gt;
        &lt;span class="na"&gt;USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.USERNAME }}&lt;/span&gt;
        &lt;span class="na"&gt;PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.PORT }}&lt;/span&gt;
        &lt;span class="na"&gt;KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SSHKEY }}&lt;/span&gt;
        &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cd /var/www/2020datathon.peterli.website/html/js/ &amp;amp;&amp;amp; cp config.js.sample config.js &amp;amp;&amp;amp; sed -i -e "s/your.leaflet.token/$(cat $HOME/leaflet_token.txt)/g" config.js &amp;amp;&amp;amp; cp $HOME/datathon2020.csv /var/www/2020datathon.peterli.website/html/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can look at above YAML file, the deployment steps are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting a machine to complete this deployment steps. And I choose the &lt;a href="https://www.digitalocean.com/" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt; to setup a machine.&lt;/li&gt;
&lt;li&gt;Generate a SSH private key and public key via &lt;code&gt;ssh-keygen&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;Uploading the public key to targeted machine.&lt;/li&gt;
&lt;li&gt;Setting the encrypted environment variables on this repository. Such as a SSH host, username and the private key.&lt;/li&gt;
&lt;li&gt;Writing above &lt;code&gt;deploy.yml&lt;/code&gt; and enable GitHub Action Workflow.&lt;/li&gt;
&lt;li&gt;Enjoy the continuous deployment on every upcoming commits!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's all, hopefully it'll be the nice tutorial to help developers/beginner to know the continuous deployment quickly :)!&lt;/p&gt;

</description>
      <category>actionshackathon</category>
      <category>github</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to buy a LaravelConf Taiwan 2020 ticket?</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Mon, 06 Jul 2020 04:21:51 +0000</pubDate>
      <link>https://dev.to/peter279k/how-to-buy-a-laravelconf-taiwan-2020-ticket-3d4c</link>
      <guid>https://dev.to/peter279k/how-to-buy-a-laravelconf-taiwan-2020-ticket-3d4c</guid>
      <description>&lt;p&gt;Hi developers, I'm Chun-Sheng, Li (Peter) and I'm Laravel Conference Taiwan member.&lt;/p&gt;

&lt;p&gt;We're excited that our ticket has been available for whiles.&lt;/p&gt;

&lt;p&gt;Unfortunately, the ticket website is not friendly for foreigners if they don't know about Chinese.&lt;/p&gt;

&lt;p&gt;Fortunately, we've the &lt;strong&gt;Google translation&lt;/strong&gt; to translate this website. But it's not good enough for foreigners.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will show you how to visit this &lt;a href="https://events.laravel-dojo.com/events/5"&gt;website&lt;/a&gt; and buy a ticket to join our LaravelConf Taiwan 2020 Webinar!&lt;/p&gt;

&lt;h1&gt;
  
  
  Buy Ticket!
&lt;/h1&gt;

&lt;p&gt;Firstly, we need to visit a &lt;a href="https://events.laravel-dojo.com/events/5"&gt;website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can simply use the Google Translation with English to change the wordings on this website and we will get following page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O4jf5OTs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/zHDf65o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O4jf5OTs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/zHDf65o.png" alt="Alt Text" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can click "register now" button and it will present following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fli7j432lzl19ronca6ib.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fli7j432lzl19ronca6ib.png" alt="Alt Text" width="409" height="623"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've the account, you can simply fill Email and password and click "Sign in" button.&lt;/p&gt;

&lt;p&gt;If you don't have a account, you should click "Sign up now" button to register a account.&lt;/p&gt;

&lt;p&gt;We assume that you don't have the registered account so we click "Sign up now". And it will present following page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcsa44dk23xx2d4h7b3af.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcsa44dk23xx2d4h7b3af.png" alt="Alt Text" width="403" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the above image, we have three ways to sign up a account:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sign up an account with "Facebook registration" button.&lt;/li&gt;
&lt;li&gt;Sign up an account with "Google registration" button.&lt;/li&gt;
&lt;li&gt;Sign up an account with typing a Email field.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We use the normal way to sign up an account so I type my e-mail address to sign up an account:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7wmljt8faatz7asfpsdh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7wmljt8faatz7asfpsdh.png" alt="Alt Text" width="384" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we can click "Next step". And we'll get following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ferov3voc6gasg7n517p0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ferov3voc6gasg7n517p0.png" alt="Alt Text" width="397" height="669"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On above image, we need to type name, phone number, password and confirm password fields.&lt;/p&gt;

&lt;p&gt;After typing all of above fields are done, just click the "registered" button.&lt;/p&gt;

&lt;p&gt;After registering the account, we can notice that your account has been registered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2nvyg12wfmok25tmjehf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2nvyg12wfmok25tmjehf.png" alt="Alt Text" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we can click "register now" button again and we will get following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4O2YB67i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/j75jii1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4O2YB67i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/j75jii1.png" alt="Alt Text" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On above image, here are available tickets are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Physical Event Ticket Eagle Ticket, TWD $3,000 ($102 USD dollars).

&lt;ul&gt;
&lt;li&gt;This is a physical ticket. If you're not in Taiwan, you should not select this ticket to join our physical conference.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Online ticket [Online live broadcast] Live broadcast + playback, TWD $800 ($28 USD dollars)

&lt;ul&gt;
&lt;li&gt;This ticket is for on-line and Webinar. I suggest you should select this ticket if you're not in Taiwan.&lt;/li&gt;
&lt;li&gt;This ticket can available for watching Webinar video record.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Online ticket [Online live broadcast], TWD $600 ($21 USD dollars)

&lt;ul&gt;
&lt;li&gt;This ticket is for on-line and Webinar. I suggest you should select this ticket if you're not in Taiwan.&lt;/li&gt;
&lt;li&gt;This ticket is &lt;strong&gt;not available&lt;/strong&gt; for watching Webinar video record.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We assume that you want to have a Online ticket [Online live broadcast] Live broadcast + playback, TWD $800 ($28 USD dollars).&lt;/p&gt;

&lt;p&gt;After selecting ticket has been done, we click "Next step" button.&lt;/p&gt;

&lt;p&gt;And we have to fill some fields on following registration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name. Please select your name.&lt;/li&gt;
&lt;li&gt;Company/School name. Please select your company or school name.&lt;/li&gt;
&lt;li&gt;Company title (student please fill in student). Please select your job title. If you're student, just type the "student".&lt;/li&gt;
&lt;li&gt;Eating habits (please select none online). Please select "none" because this ticket is available for on-line.&lt;/li&gt;
&lt;li&gt;Place of residence. Please select "other". &lt;strong&gt;This is only for the area in Taiwan if you live in Taiwan&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Qualifications for developing PHP applications. Please select the experiences about PHP development.&lt;/li&gt;
&lt;li&gt;Get used to PHP development methods. Please select the method/approaches about PHP development.

&lt;ul&gt;
&lt;li&gt;Page Script line by line. It means the developer can use pure PHP to develop a PHP program.&lt;/li&gt;
&lt;li&gt;Accustomed to self-built framework. It means the developer can use their customized frameworks to develop own PHP applications.&lt;/li&gt;
&lt;li&gt;Get used to the framework. It means developer can use popular PHP frameworks to develop a PHP programs.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Have you used Laravel? It means asking developer whether you've used Laravel framework before.&lt;/li&gt;
&lt;li&gt;Qualifications to use Laravel. Please select Laravel framework experiences/skills:

&lt;ul&gt;
&lt;li&gt;Will use basic Laravel functions and can write CRUD applications. It means developer can only use Laravel framework to create a simple CRUD applications.&lt;/li&gt;
&lt;li&gt;Will use advanced Laravel functions, will use Mail, Queue, Middleware and other components. It means developer can know how to use Queue, Mail and other components provided by Laravel framework.&lt;/li&gt;
&lt;li&gt;Very familiar with Laravel core, know IoC Container, Service Provider. It means developer can know how to use container, service provider an some advanced Laravel framework features during PHP application development.&lt;/li&gt;
&lt;li&gt;Know a lot about expanding Laravel, and will write Laravel Package. It means developer can know how to create a Laravel package or components.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Is the company's product or project already using Laravel?

&lt;ul&gt;
&lt;li&gt;some, it means developers use Laravel framework to develop some products in their companies.&lt;/li&gt;
&lt;li&gt;not yet. It means developers don't use any Laravel framework to develop some products in their companies.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Are you willing to provide your information to the conference partners?

&lt;ul&gt;
&lt;li&gt;willing, it means developers is willing to provide their information for Laravel conference team.&lt;/li&gt;
&lt;li&gt;Unwilling, it means developer is not willing to provide their information for Laravel conference team.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Places to pay special attention to during the meeting (do not eat beef/allergic to seafood/better radio/I want to interact more with the entity online...etc) 

&lt;ul&gt;
&lt;li&gt;Please type "No" if you don't have any additional information or suggestions to want to tell Laravel Conference team.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After filling these above field is done, just click "Next step" button:&lt;/p&gt;

&lt;p&gt;You will get following page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F728ydzvbh2l3uophb6ow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F728ydzvbh2l3uophb6ow.png" alt="Alt Text" width="638" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On above image, it asks developers whether let ticket have the Uniform invoice numbers.&lt;/p&gt;

&lt;p&gt;Please select "no" because this field is only for Taiwan developer to let ticket apply for reimbursement in company.&lt;/p&gt;

&lt;p&gt;Just click "Next step" button and we will get following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2jbvrq1kdgla6ly3kfhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2jbvrq1kdgla6ly3kfhw.png" alt="Alt Text" width="627" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just have one more step! Just click "Go to payment" button to pay for the ticket!&lt;/p&gt;

&lt;p&gt;It will get following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk69iambthl90yfbu3jon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk69iambthl90yfbu3jon.png" alt="Alt Text" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can be easy to know because it has the English fields!&lt;/p&gt;

&lt;p&gt;And it can help developers to fill their card information to make a payment.&lt;/p&gt;

&lt;p&gt;After filling all of card fields, just click "Pay now" button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F12ny279vdcdhqdkopgp7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F12ny279vdcdhqdkopgp7.png" alt="Alt Text" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After paying for the ticket, buying ticket is done.&lt;/p&gt;

&lt;p&gt;And you'll get following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr7kk6pnmieatcvifcv0z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr7kk6pnmieatcvifcv0z.png" alt="Alt Text" width="644" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also click "view my ticket" button to checkout your registered ticket or check your registered mail box to ensure you revive the ticket information &lt;strong&gt;(Please forgive that the mail contents are only for Chinese)&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3pqmhn6o0hzwo5bsmmm9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3pqmhn6o0hzwo5bsmmm9.png" alt="Alt Text" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;In this tutorial, you will learn how to buy a LaravelConf Taiwan 2020 Webinar ticket!&lt;/p&gt;

&lt;p&gt;Still have some questions about buying ticket? Just write some comments on this post discussion thread or tweet &lt;a href="https://twitter.com/laravelconftw"&gt;Laravel Conf Taiwan Twitter&lt;/a&gt; :)!&lt;/p&gt;

</description>
      <category>ticket</category>
      <category>laravelconftw</category>
    </item>
    <item>
      <title>How to create own Packagist mirror site on Ubuntu 18.04</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Wed, 24 Jun 2020 19:16:00 +0000</pubDate>
      <link>https://dev.to/peter279k/how-to-create-own-packagist-mirror-list-on-ubuntu-18-04-56j3</link>
      <guid>https://dev.to/peter279k/how-to-create-own-packagist-mirror-list-on-ubuntu-18-04-56j3</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;If you're a modern PHP developer, you may heard about the &lt;a href="https://packagist.org"&gt;packagist.org&lt;/a&gt; and &lt;a href="https://getcomposer.org/"&gt;composer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Packagist is a PHP package repositories and it stores many composer-based packages.&lt;/p&gt;

&lt;p&gt;What about Composer? It's a package manager for PHP and it can help PHP developers to be easy to manage all kinds of PHP packages via Composer.&lt;/p&gt;

&lt;p&gt;And its functionalities are very similar with NPM (a Node.js package manager).&lt;/p&gt;

&lt;p&gt;If you use a lot for installing PHP packages via Composer, you may know about this &lt;a href="https://github.com/composer/composer/issues/9003"&gt;issue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This issue is about the main Packagist of Asia mirror has the bandwidth problem. (For now, it has been fixed.)&lt;/p&gt;

&lt;p&gt;And it causes many PHP developers cannot install some PHP packages via &lt;code&gt;composer install&lt;/code&gt;, &lt;code&gt;composer require&lt;/code&gt; and &lt;code&gt;composer update&lt;/code&gt; at that moment.&lt;/p&gt;

&lt;p&gt;I also notice this issue and try to find another mirror to replace.&lt;/p&gt;

&lt;p&gt;However, most of mirror locations are listed on official &lt;a href="https://packagist.org/mirrors"&gt;Packagist Org&lt;/a&gt; and &lt;a href="https://github.com/webysther/packagist-mirror#-packagist-public-metadata-mirrors-observatory-around-the-world"&gt;this&lt;/a&gt; are far away from me.&lt;/p&gt;

&lt;p&gt;And sometimes these locations cannot save my time because it takes slow time  during composer package installation.&lt;/p&gt;

&lt;p&gt;To resolve this issue, I want to setup my own Packagist mirror sites in my country.&lt;/p&gt;

&lt;p&gt;And I also use &lt;a href="https://github.com/webysther/packagist-mirror"&gt;packagist-mirror&lt;/a&gt; to accomplish my above issue because this mirror setup is recommended by &lt;a href="https://packagist.org/mirrors"&gt;packagist.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this tutorial, I will show you how to use my customized Bash script to setup our own Packagist mirror site on Ubuntu 18.04 hosting system.&lt;/p&gt;

&lt;h1&gt;
  
  
  Perquisites
&lt;/h1&gt;

&lt;p&gt;Here are some required stuffs before we get started with setting up our amazing Packagist mirror site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One VPS (virtual private server) with at least one core CPU, 2GB RAM and a clean Ubuntu 18.04 operating system.&lt;/li&gt;
&lt;li&gt;A registered domain, it's nice to let developers be easy to know mirror site and use it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;wget&lt;/code&gt; command is available now on your VPS.&lt;/li&gt;
&lt;li&gt;It's nice to have a &lt;code&gt;.env&lt;/code&gt; file on current home directory.&lt;/li&gt;
&lt;li&gt;It's nice to have the &lt;a href="https://gist.githubusercontent.com/peter279k/cab67ba6207ec291747cc3cc6071a519/raw/e85bf920c3077236170da693ac21e21d8f86c015/nginx-default"&gt;nginx-default&lt;/a&gt; and &lt;a href="https://gist.githubusercontent.com/peter279k/cab67ba6207ec291747cc3cc6071a519/raw/e85bf920c3077236170da693ac21e21d8f86c015/nginx.conf"&gt;nginx.conf&lt;/a&gt; files are located on current user home directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Installation
&lt;/h1&gt;

&lt;p&gt;If you've looked at the &lt;a href="https://github.com/webysther/packagist-mirror"&gt;packagist-mirror&lt;/a&gt; repository, you may find it has many kinds of ways to install the Packagist mirror site.&lt;/p&gt;

&lt;p&gt;Including Docker container building, hosting setup and so on.&lt;/p&gt;

&lt;p&gt;In this tutorial, I will use the hosting way to install the Packagist mirror site and I also provide a automated Bash script to help developers to setup Packagist mirror happily :).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Download a packagist_mirror_installer.sh script
&lt;/h2&gt;

&lt;p&gt;It's easy to use following command to download a &lt;code&gt;packagist_mirror_installer.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://gist.githubusercontent.com/peter279k/cab67ba6207ec291747cc3cc6071a519/raw/46495d8dad37e769f4065f46925ff7b8d22b1e7e/packagist_mirror_installer.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After script downloading has been completed, it can change this Bash script permission into &lt;code&gt;755&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is, owner can read, write and execute this script, and group owner or other users can read and execute the script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Run this packagist_mirror_installer.sh script
&lt;/h2&gt;

&lt;p&gt;After setting above permission is successful, executing following command to start Packagist mirror site building:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./packagist_mirror_installer.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it will present following captured picture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lxP3-7K8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/4R5H04N.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lxP3-7K8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/4R5H04N.png" alt="update_upgrade" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's doing for update and installing required packages.&lt;/p&gt;

&lt;p&gt;By default, the system locale will setup for &lt;code&gt;en_US.UTF-8&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If developers want to change locale, it will set specific locale manually.&lt;/p&gt;

&lt;p&gt;When installing required packages has been done, it will present following pictures to let developers select current timezone:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wxNfkx-U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/nCjkSOM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wxNfkx-U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/nCjkSOM.png" alt="timezone_area" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--11wII2jr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/OPvQQ2H.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--11wII2jr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/OPvQQ2H.png" alt="timezone_country" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After selecting timezone has been done, it will present following picture to tell developers setting a host name for this mirror site:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Dkb1ETc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/2uRrREf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Dkb1ETc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/2uRrREf.png" alt="ask_set_host_name" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If developers don't set any host name and type enter, script will try to use &lt;code&gt;hostname&lt;/code&gt; to get current host name on this hosting operating system. And ask you to ensure set this host/domain name.&lt;/p&gt;

&lt;p&gt;If the host name is configured correctly, developers can type &lt;code&gt;Y&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt; to continue the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Copy nginx.conf and nginx sites default files
&lt;/h2&gt;

&lt;p&gt;After setting the host name is successful, the script will try to find the &lt;code&gt;nginx.conf&lt;/code&gt; and &lt;code&gt;nginx-default&lt;/code&gt; files on current user home directory.&lt;/p&gt;

&lt;p&gt;If it doesn't find any Nginx configuration files, it will ask you to skip this copy work and do next step.&lt;/p&gt;

&lt;p&gt;If developers type &lt;code&gt;Y&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt;, it will skip above steps. Otherwise terminate this script with exit code &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NHvYHc5t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Swemdxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NHvYHc5t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/Swemdxl.png" alt="nginx_conf_ask" width="800" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After doing above steps about copying Nginx configuration files, it will present following picture to tell whether developers to delete all files/folders on &lt;code&gt;/var/www/html/*&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;If typing &lt;code&gt;Y&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt;, it should delete all of the things on &lt;code&gt;/var/www/html&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--76hiQ9vh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/9vETWYp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--76hiQ9vh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/9vETWYp.png" alt="ask_var_www_html" width="800" height="26"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After manipulating the &lt;code&gt;/var/www/html&lt;/code&gt; folder, it will ask developers whether updating Packagist repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7V0RVNKV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/cYv2hay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7V0RVNKV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/cYv2hay.png" alt="packagist_repo" width="800" height="36"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If developers type &lt;code&gt;Y&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt;, it will use &lt;code&gt;git pull origin master&lt;/code&gt; command to update Packagist repository right now. Otherwise skipping this step.&lt;/p&gt;

&lt;p&gt;After updating Packagist repositories step, it will present following picture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bxWtadfO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/A8dEoUC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bxWtadfO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/A8dEoUC.png" alt="composer_nginx_start" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will do following steps for above captured picture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download Composer.&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;composer install&lt;/code&gt; to install some packages for &lt;code&gt;packgist-mirror&lt;/code&gt; repository.&lt;/li&gt;
&lt;li&gt;Asking developers whether executing the &lt;code&gt;composer update -n&lt;/code&gt; to update dependencies for above repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After doing some steps, it will present following picture to tell developers whether syncing Packagist mirror:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TcfHIT1Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/TfAT8Zf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TcfHIT1Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/TfAT8Zf.png" alt="sync_mirror" width="661" height="45"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If developers type &lt;code&gt;Y&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt;, it will use &lt;code&gt;php bin/mirror create -vvv&lt;/code&gt; command to update Packagist repository right now. Otherwise skipping this step.&lt;/p&gt;

&lt;p&gt;After syncing or skip Packagist mirror syncing step, it will present following picture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lPS6QCnW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/JOnANzo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lPS6QCnW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/JOnANzo.png" alt="install_certbot" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It does some steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update package mirror for Ubuntu operating system and install required packages for &lt;code&gt;cert-bot&lt;/code&gt;. This can help developers to install a &lt;code&gt;Let's Encrypt&lt;/code&gt; SSL certificate to secure mirror website easily.&lt;/li&gt;
&lt;li&gt;Asking developers to determine setup SSL certificate with &lt;code&gt;cert-bot&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JWt_R1m3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/2fUbN1J.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JWt_R1m3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/2fUbN1J.png" alt="ask_certbot_setting" width="800" height="28"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If developers type &lt;code&gt;Y&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt;, it will do &lt;code&gt;cert-bot&lt;/code&gt; command interactively.&lt;/p&gt;

&lt;p&gt;And help developers to setup and configure a SSL certificate quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Editing DotEnv file
&lt;/h2&gt;

&lt;p&gt;Editing &lt;code&gt;.env&lt;/code&gt; file is very simple, and developers can scratch this file from &lt;a href="https://github.com/webysther/packagist-mirror/blob/master/.env.example"&gt;.env.example&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;And it's very clear for every developer to know each DotEnv values have the comment and let us know setting functionality easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing index page
&lt;/h2&gt;

&lt;p&gt;If developers want to customize index page, it's easy to edit the &lt;a href="https://github.com/webysther/packagist-mirror/blob/master/resources/index.html.php"&gt;index.html.php&lt;/a&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;After doing above Bash script correctly, it will have this &lt;a href="https://packagist.tw"&gt;page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enjoy it and have your own Packagist mirror right now :)!&lt;/p&gt;

</description>
      <category>packagist</category>
      <category>mirror</category>
    </item>
    <item>
      <title>Let's use PHP to develop a Web Monetization helper!</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Sun, 14 Jun 2020 04:35:35 +0000</pubDate>
      <link>https://dev.to/peter279k/let-s-use-php-to-develop-a-web-monetization-helper-3k1</link>
      <guid>https://dev.to/peter279k/let-s-use-php-to-develop-a-web-monetization-helper-3k1</guid>
      <description>&lt;p&gt;[Instructions]: In this tutorial, I present a PHP package and how to generate some web monetization features on back-end easily :).&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;Here are some links and description for what I built:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/peter279k/php-monetization"&gt;php-monetiation link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packagist.org/packages/lee/php-monetization"&gt;Packagist link&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Validate payment pointer URL.&lt;/li&gt;
&lt;li&gt;Generate payment pointer URL with given arguments.&lt;/li&gt;
&lt;li&gt;Generate payment pointer URL with meta tag.&lt;/li&gt;
&lt;li&gt;Get default payment pointer URL.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;This PHP package is about Foundational Technology.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;These following sample codes include above features.&lt;/li&gt;
&lt;li&gt;Here are some sample codes and their results:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Lee\WebMonetization\WebMonetization&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Generate payment pointer URL with meta tag&lt;/span&gt;
&lt;span class="nv"&gt;$paymentPointerUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'$ilp.uphold.com/alice'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$metaTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WebMonetization&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;generateMetaTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$paymentPointerUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$metaTag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;meta name="monetization" content="$ilp.uphold.com/alice"&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Validate payment pointer URL&lt;/span&gt;
&lt;span class="nv"&gt;$validateResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WebMonetization&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;validatePaymentPointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$paymentPointerUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$validateResult&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="c1"&gt;// Generate payment pointer&lt;/span&gt;
&lt;span class="nv"&gt;$interLedger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ilp'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$domainName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'uphold'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$tldName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$userTokenName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'alice'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$paymentPointerUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WebMonetization&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;generatePaymentPointer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$interLedger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$domainName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$tldName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$userTokenName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$paymentPointerUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// $ilp.uphold.com/alice&lt;/span&gt;

&lt;span class="c1"&gt;// Get default payment pointer urls&lt;/span&gt;
&lt;span class="nv"&gt;$webMonetization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebMonetization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$paymentPointerUrls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$webMonetization&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getDefaultPaymentPointerUrls&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$paymentPointerUrls&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// [ '$ilp.uphold.com/', '$ilp.gatehub.net/', '$pay.stronghold.co/',]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Link to Code
&lt;/h2&gt;

&lt;p&gt;[Note]: &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/peter279k"&gt;
        peter279k
      &lt;/a&gt; / &lt;a href="https://github.com/peter279k/php-monetization"&gt;
        php-monetization
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The Web Monetization feature helper written in PHP
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;php-monetization&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/peter279k/php-monetization/workflows/CI-Build/badge.svg"&gt;&lt;img src="https://github.com/peter279k/php-monetization/workflows/CI-Build/badge.svg" alt="CI-Build"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;This is a PHP for Web Monetization helper.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Here are some features about Web Monetization:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validate payment pointer URL.&lt;/li&gt;
&lt;li&gt;Generate payment pointer URL with given arguments.&lt;/li&gt;
&lt;li&gt;Generate payment pointer URL with meta tag.&lt;/li&gt;
&lt;li&gt;Get default payment pointer URL.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;

&lt;p&gt;We strongly recoomend using &lt;code&gt;composer&lt;/code&gt; to install this package.&lt;/p&gt;

&lt;p&gt;The installation steps are as follows:&lt;/p&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;composer require lee/php-monetization:^1.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;It's very simple. Here are some usages:&lt;/p&gt;

&lt;div class="highlight highlight-text-html-php notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="pl-k"&gt;require_once&lt;/span&gt; __DIR__ . &lt;span class="pl-s"&gt;'/vendor/autoload.php'&lt;/span&gt;;

&lt;span class="pl-k"&gt;use&lt;/span&gt; &lt;span class="pl-v"&gt;Lee&lt;/span&gt;\&lt;span class="pl-v"&gt;WebMonetization&lt;/span&gt;\&lt;span class="pl-v"&gt;WebMonetization&lt;/span&gt;;

&lt;span class="pl-c"&gt;// Generate payment pointer URL with meta tag&lt;/span&gt;
&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;paymentPointerUrl&lt;/span&gt; = &lt;span class="pl-s"&gt;'$ilp.uphold.com/alice'&lt;/span&gt;;
&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;metaTag&lt;/span&gt; = &lt;span class="pl-v"&gt;WebMonetization&lt;/span&gt;::&lt;span class="pl-en"&gt;generateMetaTag&lt;/span&gt;(&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;paymentPointerUrl&lt;/span&gt;);

&lt;span class="pl-k"&gt;echo&lt;/span&gt; &lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;metaTag&lt;/span&gt;; &lt;span class="pl-c"&gt;// &amp;lt;meta name="monetization" content="$ilp.uphold.com/alice"&amp;gt;&lt;/span&gt;

&lt;span class="pl-c"&gt;// Validate payment pointer URL&lt;/span&gt;
&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;validateResult&lt;/span&gt; = &lt;span class="pl-v"&gt;WebMonetization&lt;/span&gt;::&lt;span class="pl-en"&gt;validatePaymentPointer&lt;/span&gt;(&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;paymentPointerUrl&lt;/span&gt;);

&lt;span class="pl-k"&gt;echo&lt;/span&gt; &lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;validateResult&lt;/span&gt;; &lt;span class="pl-c"&gt;// true&lt;/span&gt;

&lt;span class="pl-c"&gt;// Generate payment pointer&lt;/span&gt;
&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;interLedger&lt;/span&gt; = &lt;span class="pl-s"&gt;'ilp'&lt;/span&gt;;
&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;domainName&lt;/span&gt; = &lt;span class="pl-s"&gt;'uphold'&lt;/span&gt;;
&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;tldName&lt;/span&gt; = &lt;/pre&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/peter279k/php-monetization"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  How I built it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I use the PCRE (Per Compatibility Regular Expression) to validate specific payment pointer URL on PHP.
And it can call &lt;code&gt;WebMonetization::validatePaymentPointer&lt;/code&gt; to complete above specifictaion.&lt;/li&gt;
&lt;li&gt;I create configuration array wit PHP to define a default payment pointer URL prefix lists.
These lists are as follows:

&lt;ul&gt;
&lt;li&gt;$ilp.uphold.com/&lt;/li&gt;
&lt;li&gt;$ilp.gatehub.net/&lt;/li&gt;
&lt;li&gt;$pay.stronghold.co/
It can call &lt;code&gt;WebMonetization::getDefaultPaymentPointerUrls&lt;/code&gt; method to complete above specification.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;To crate completed payment pointer URL string easily, I also create a method named &lt;code&gt;WebMonetization::generatePaymentPointer&lt;/code&gt; to complete above specification.&lt;/li&gt;
&lt;li&gt;To create payment pointer URL with meta tag string easily, I also create a method named &lt;code&gt;WebMonetization::generateMetaTag&lt;/code&gt; to complete this specification.&lt;/li&gt;
&lt;li&gt;To make all of static methods verified and reliable, I also develop unit tests with PHPUnit to complete above specifications.
All of unit tests are available on &lt;a href="https://github.com/peter279k/php-monetization/blob/master/tests/WebMonetizationTest.php"&gt;WebMonetizationTest&lt;/a&gt; class.&lt;/li&gt;
&lt;li&gt;To make sure all of above static methods are verified and reliable, I also integrate the GitHub Action Workflows to complete this issue about do automatic PHPUnit tests for every incoming commits.
The latest GitHub Action Workflows status is available &lt;a href="https://github.com/peter279k/php-monetization/actions?query=workflow%3ACI-Build"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Additional Resources/Info
&lt;/h2&gt;

&lt;p&gt;Here are some useful resources and info to help me to complete this simple and useful PHP packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PCRE reference and function usages on &lt;a href="https://www.php.net/manual/en/book.pcre.php"&gt;official PHP website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The payment pointer URL specification and description is available &lt;a href="https://paymentpointers.org/"&gt;here&lt;/a&gt;. And it can help me to know more details about generating payment pointer URL :).&lt;/li&gt;
&lt;li&gt;To complete all of static methods I develop on &lt;code&gt;WebMonetization&lt;/code&gt; class reliably, I also want to say thanks for &lt;a href="https://phpunit.de/"&gt;PHPUnit&lt;/a&gt; to help me to complete all related static methods with unit tests.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gftwhackathon</category>
    </item>
    <item>
      <title>Let's build a Web Service with Web Monetization X PHP Binding!</title>
      <dc:creator>peter279k</dc:creator>
      <pubDate>Wed, 03 Jun 2020 17:25:56 +0000</pubDate>
      <link>https://dev.to/peter279k/let-s-build-a-web-service-with-web-monetization-x-php-binding-2165</link>
      <guid>https://dev.to/peter279k/let-s-build-a-web-service-with-web-monetization-x-php-binding-2165</guid>
      <description>&lt;p&gt;[Instructions]:&lt;/p&gt;

&lt;p&gt;In this Hackathon, it can learn about how to develop some popular web service with Web Monetization features and PHP binding.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;Here are some stuffs I build for this dead simple web service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using Bootstrap to develop all required templates.&lt;/li&gt;
&lt;li&gt;Using PHP 7.2+ version with Slim 4 Framework to build a web service.&lt;/li&gt;
&lt;li&gt;Using the Twig view template to be back-end rendering exclusive contents.&lt;/li&gt;
&lt;li&gt;Using PHP session to record current Web Monetization status event.&lt;/li&gt;
&lt;li&gt;In development mode, using mkcert command to create self-signed certificate easily.&lt;/li&gt;
&lt;li&gt;In development mode, using the stunnel command to create SSL tunnel and make local PHP web bulit-in server can be served on HTTPS. (It's important for Web Monetization because this only supports over HTTP.)&lt;/li&gt;
&lt;li&gt;In production mode, using the &lt;a href="https://certbot.eff.org/"&gt;certbot&lt;/a&gt; to create HTTPS easily.&lt;/li&gt;
&lt;li&gt;Both development mode and production mode are on Ubuntu 18.04.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Here are some categories included in this Hackathon:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Foundational Technology: using the PHP to be back-end binding.&lt;/li&gt;
&lt;li&gt;Experiment stuffs: let all some stuffs and put them together to be a development environment.&lt;/li&gt;
&lt;li&gt;Production stuffs: After completing this service in development environment, I also provide the deployment steps to publish in production mode.&lt;/li&gt;
&lt;li&gt;Automatic Building Steps: I want to save my life, so I develop a simple Bash script to build my development environment easily.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Firstly, visiting the following website via &lt;a href="https://web-monetization.peterli.website/"&gt;web-monetization.peterli.website&lt;/a&gt;, and it will present following captured picture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4q0az5gvet4p7106hfon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4q0az5gvet4p7106hfon.png" alt="Alt Text" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Second, the Home and Introduction don't have the web-monetized feature, they're the simple page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F84d8jmp0gglypdher7x6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F84d8jmp0gglypdher7x6.png" alt="Alt Text" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Third, click the Blog link. By default, this page with web-monetized is disabled. And it will only look at the warning message about "This is the locked section one, You've to enable and pay with Web Monetization to unlock it :)!".&lt;/p&gt;

&lt;p&gt;And the danger message says: "The Web Monetization has been disabled!".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzwh69gr4bwhrd72gn5n9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzwh69gr4bwhrd72gn5n9.png" alt="Alt Text" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To enable the web-monetized, we can just click the "Enable Web Monetization".&lt;/p&gt;

&lt;p&gt;Once click this button, it will refresh this page and it will look at these exclusive contents:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu7swj2f977x18b4wjvaq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu7swj2f977x18b4wjvaq.png" alt="Alt Text" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If people thinks this is enough to do web monetization, they can click "Disable Web Monetization" button.&lt;/p&gt;

&lt;p&gt;If people want to do web monetization for about whiles, they don't have to click disabled button.&lt;/p&gt;

&lt;p&gt;They can enable web-monetization and leave this page directly.&lt;/p&gt;

&lt;p&gt;The web service will use PHP session to remember this until the session has been expired.&lt;/p&gt;

&lt;p&gt;If people want to know how much amounts are sent to this author, they can use the "Calculate Web Monetization" to present total amounts:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Feh8wq3243rjz2iakbfx4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Feh8wq3243rjz2iakbfx4.png" alt="Alt Text" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If people want to stop knowing the amount information, just click "Stop Calculating Web Monetization".&lt;/p&gt;

&lt;p&gt;Then visiting the donation page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fra0rq98tzlod4dd8f2z7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fra0rq98tzlod4dd8f2z7.png" alt="Alt Text" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's alternative way to do donation.&lt;/p&gt;

&lt;p&gt;Sometimes most of developers have the PayPal donation button or other payment donation buttons to let sponsor pay some dollars.&lt;/p&gt;

&lt;p&gt;Every payment donation buttons need to have the minimum dollars to let sponsor pay. For example, 1, 5 or 10 USD dollars at least.&lt;/p&gt;

&lt;p&gt;This is not very convenient for every sponsor and it's up to sponsor determine how much amounts paid for developer.&lt;/p&gt;

&lt;p&gt;The donation page are developed for these sponsors.&lt;/p&gt;

&lt;p&gt;If some sponsors want to pay small amounts to developers, it can just click "Enable Donation Page".&lt;/p&gt;

&lt;p&gt;And this donation page will enable the web monetization page.&lt;/p&gt;

&lt;p&gt;Once enabling web monetization page, it will start paying some amounts and present current amount they pay for this developer.&lt;/p&gt;

&lt;p&gt;Once the sponsor thinks it's good enough to do this payment, they can click "Disable Donation Page" at any moments!&lt;/p&gt;

&lt;p&gt;Finally, visiting History page. In this page, it can show how much amounts that this website owner has made.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkmekqm4d9gt8tbwykxng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkmekqm4d9gt8tbwykxng.png" alt="Alt Text" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think amounts should be public and it can let every user and sponsor know the total amounts of this website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Link to Code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;All codes are located on &lt;a href="https://github.com/peter279k/web-monetization-demo"&gt;web-monetization-demo&lt;/a&gt;.
Feel free to fork and use them :).&lt;/li&gt;
&lt;li&gt;It also provides a completed &lt;a href="https://github.com/peter279k/web-monetization-demo/blob/master/README.md"&gt;README&lt;/a&gt; for every back-end developers to develop a awesome web-based application services steps by steps.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I built it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I think these exclusive contents should be hidden.
And I use the Twig view to complete this issue.&lt;/li&gt;
&lt;li&gt;To sync transaction history for every micro payment sent to Coil , I still use the AJAX to do POST method to store every amount detail.&lt;/li&gt;
&lt;li&gt;To let developers decide to enable/disable web monetization, every page I develop has the enable and disable button.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Additional Resources/Info
&lt;/h2&gt;

&lt;p&gt;Here are some useful references I look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://coil.com/"&gt;Coil&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webmonetization.org/docs"&gt;Web Monetization Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.slimframework.com/"&gt;Slim Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://odan.github.io/2019/11/05/slim4-tutorial.html#deployment"&gt;Slim Framework tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://uphold.com/"&gt;Uphold&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/"&gt;DigitalOcean&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://certbot.eff.org/#ubuntutrusty-apache"&gt;Certbot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gftwhackathon</category>
    </item>
  </channel>
</rss>
