<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Kimi on Medium]]></title>
        <description><![CDATA[Stories by Kimi on Medium]]></description>
        <link>https://medium.com/@kimi0230?source=rss-87e269a0fa54------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*dmbNkD5D-u45r44go_cf0g.png</url>
            <title>Stories by Kimi on Medium</title>
            <link>https://medium.com/@kimi0230?source=rss-87e269a0fa54------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 06 Apr 2026 22:47:33 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@kimi0230/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[AWS S3, CloudFront, Certificate Manager 架設靜態網站]]></title>
            <link>https://kimi0230.medium.com/aws-s3-cloudfront-certificate-manager-%E6%9E%B6%E8%A8%AD%E9%9D%9C%E6%85%8B%E7%B6%B2%E7%AB%99-f37e51c6a192?source=rss-87e269a0fa54------2</link>
            <guid isPermaLink="false">https://medium.com/p/f37e51c6a192</guid>
            <category><![CDATA[aws-certificate-manager]]></category>
            <category><![CDATA[s3]]></category>
            <category><![CDATA[cdn]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[cloudfront]]></category>
            <dc:creator><![CDATA[Kimi]]></dc:creator>
            <pubDate>Wed, 26 Jan 2022 13:34:04 GMT</pubDate>
            <atom:updated>2022-01-26T13:35:19.134Z</atom:updated>
            <content:encoded><![CDATA[<p>使用 AWS 上的 S3, CloudFront 架設網站, 並藉由 AWS Certificate Manager 申請 SSL. 這樣的會就可以不用開啟S3的Static website hosting .藉由 CloudFront 還可以讓 bucket 不必公開, 限制 bucket 只能由 CloudFront 讀取~</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/808/1*RJEONULpMPQCUQI88VrDnA.png" /></figure><p><strong>## 流程</strong></p><ol><li>S3 建立 Bucket, public 權限打開, 放入你的靜態網頁(index.html)</li></ol><p>2. AWS Certificate Manager 申請 SSL (<strong>一定要在 virginia us-east-1 !!</strong>)</p><p>3. CloudFront 建立 Distribution, 並指向S3 Bucket.</p><p>4. S3 public 權限要關掉(如果沒用OAI的話)</p><ul><li><a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/website-hosting-custom-domain-walkthrough.html">https://docs.aws.amazon.com/AmazonS3/latest/userguide/website-hosting-custom-domain-walkthrough.html</a></li><li><a href="https://aws.amazon.com/tw/blogs/security/how-to-protect-your-web-application-against-ddos-attacks-by-using-amazon-route-53-and-a-content-delivery-network/">https://aws.amazon.com/tw/blogs/security/how-to-protect-your-web-application-against-ddos-attacks-by-using-amazon-route-53-and-a-content-delivery-network/</a></li></ul><p><strong>## 1. S3 建立 Bucket</strong></p><ul><li>Everyone Read 權限打開 不然沒人連的到網站</li><li>指定CloudFront cache 時間 <a href="https://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/Expiration.html">https://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/Expiration.html</a></li><li>因為透過 Cloudfront 所以 Static website hosting 並不需要開啟</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dHvKQ3MfnOl2YuRvTcGhdg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LBvZ_5r4hiK8zoaxXxMeIg.png" /></figure><p><strong>## 2. AWS Certificate Manager 申請 SSL</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mdPXXsFxij9_KlwKxINnJA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HgxM7FEtegXD5Yq69cj-1A.png" /></figure><p><strong>#### 使用DNS驗證</strong></p><p>使用DNS驗證的話, AWS會自動幫你 renew憑證, 如果使用email的話這樣每年都要自己手動renew</p><p>有以下2種方式做認證, 看是要用AWS 的 Route 53 , 或是第三方的DNS供應商</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kVL-G-oUWkiQaVHJNtnf7Q.png" /></figure><p>1. 不是使用 Route 53 做為 DNS 供應商，</p><ul><li>您必須擷取 CNAME 資訊並新增至 DNS 資料庫。您可以使用兩種方式的任一種執行此動作：</li></ul><blockquote>1. 複製顯示在 Domains（網域）部分的 CNAME 元件。這些資訊需手動新增至 DNS 資料庫。</blockquote><blockquote>2. 選擇 Export to CSV（匯出至 CSV）。結果檔案中的資訊需手動新增至 DNS 資料庫。</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pAF_5mLa69iSpNedEDOeOA.png" /></figure><p>2. (選用) 使用 Route 53 進行驗證。</p><ul><li>Create records in Route 53（在 Route 53 中建立記錄）按鈕會在符合以下情況時顯示：</li><li>您使用 Route 53 做為 DNS 供應商。</li><li>您擁有寫入 Route 53 託管區域的許可。</li><li>您的 FQDN 未經驗證。</li></ul><p>注意</p><blockquote>如果 Create record in Route 53 (在 Route 53 中建立記錄) 按鈕遺失或停用，請參閱「ACM 主控台不會顯示「Create record in Route 53」(在 Route 53 中建立記錄) 按鈕」。</blockquote><ul><li>選擇 Create records in Route 53（在 Route 53 中建立記錄）按鈕，然後選擇 Create records（建立記錄）。所以此 Certificate status（憑證狀態）頁面應該開啟並顯示狀態橫幅報告 Successfully created DNS records（成功建立 DNS 記錄）。您的新憑證可能會繼續顯示 Pending validation（待定驗證）狀態最多 30 分鐘。</li></ul><p>提示</p><blockquote>您無法透過編寫程式的方式請求 ACM 自動在 Route 53 中建立記錄。但是您可以對 Route 53 發出 AWS CLI 或 API 呼叫，以在 Route 53 DNS 資料庫中建立記錄。如需有關 Route 53 記錄集的詳細資訊，請參閱使用 Route 53使用資源記錄集。</blockquote><p>更詳細的話可以看官網的介紹 <a href="https://docs.aws.amazon.com/zh_tw/acm/latest/userguide/dns-validation.html">https://docs.aws.amazon.com/zh_tw/acm/latest/userguide/dns-validation.html</a></p><p><strong>## 3. Cloudfront 建立 Distribution</strong></p><p>這邊就要建立一個CDN, 然後對應到剛剛建立好的 S3 Bucket</p><p>1. `Origin Domain Name` 選擇剛剛建立的S3 Bucket</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/746/1*ms5Ey_zmPS7LrWqBdupPWw.png" /></figure><h4>OAI</h4><ul><li>如果沒有 Origin Access Identity (OAI) 的話，Cloudfront 會透過這個 identity 來存取 S3, 所以在S3的 `Grant Read Permissions on Bucket` 這邊必須選擇 `Yes`, 這會自動 update S3 bucket policy, 這樣就允許 Cloudfront 讀取 origin bucket.</li><li>如果選擇OAI. bucket can restrict access to only CloudFron, 用在限制 user 只能透過 Cloudfront 讀取靜態網頁, 而不能直接 access S3 bucket.</li></ul><blockquote>If you don’t use an OAI, your S3 bucket must allow public access.</blockquote><blockquote>If you don’t want your S3 bucket to allow public access,</blockquote><blockquote>you can use an OAI. With an OAI, CloudFront sends authenticated requests to your S3 bucket.</blockquote><blockquote>This means you can block public access to your S3 bucket while still allowing CloudFront to get objects from the bucket.</blockquote><blockquote>To use an OAI, you must update your S3 bucket policy to allow access to the OAI.</blockquote><blockquote>When you choose Yes use OAI you can also choose Yes,</blockquote><blockquote>update the bucket policy so that CloudFront updates the bucket policy for you.</blockquote><blockquote>Otherwise, you must update it yourself.</blockquote><p>2. `Viewer protocol policy` 勾 `Redirect HTTP to HTTPS`, 因為都用HTTPS了</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/801/1*e5ePVuz__Sray1YwvbIRPQ.png" /></figure><p>3. cache 就走AWS建議的</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/769/1*PATwQPon286P42ZzAD8h0A.png" /></figure><p>4. 選剛剛驗證過的SSL</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/838/1*6EU0w6WomqhHa16adpXFxw.png" /></figure><p>5. 更多設定可以參考 <a href="https://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/UpdatingExistingObjects.html">https://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/UpdatingExistingObjects.html</a></p><p><strong>## Reference</strong></p><ul><li><a href="https://blog.johnwu.cc/article/aws-s3-cloudfront-ssl-%E9%9D%9C%E6%85%8B%E7%B6%B2%E9%A0%81%E6%9E%B6%E7%AB%99%E6%95%99%E5%AD%B8.html">https://blog.johnwu.cc/article/aws-s3-cloudfront-ssl-%E9%9D%9C%E6%85%8B%E7%B6%B2%E9%A0%81%E6%9E%B6%E7%AB%99%E6%95%99%E5%AD%B8.html</a></li><li><a href="https://docs.aws.amazon.com/zh_tw/acm/latest/userguide/dns-validation.html">https://docs.aws.amazon.com/zh_tw/acm/latest/userguide/dns-validation.html</a></li><li><a href="https://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/Expiration.html">https://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/Expiration.html</a></li><li><a href="https://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/UpdatingExistingObjects.html">https://docs.aws.amazon.com/zh_tw/AmazonCloudFront/latest/DeveloperGuide/UpdatingExistingObjects.html</a></li><li><a href="https://blog.david74.dev/%E4%BD%BF%E7%94%A8-aws-s3-cloudfront-%E9%83%A8%E5%B1%AC-custom-domain-https-%E9%9D%9C%E6%85%8B%E7%B6%B2%E9%A0%81-eddd9c9ad9d1">https://blog.david74.dev/%E4%BD%BF%E7%94%A8-aws-s3-cloudfront-%E9%83%A8%E5%B1%AC-custom-domain-https-%E9%9D%9C%E6%85%8B%E7%B6%B2%E9%A0%81-eddd9c9ad9d1</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f37e51c6a192" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[深複製(Deep copy) 淺複製(Shallow copy)]]></title>
            <link>https://kimi0230.medium.com/%E6%B7%B1%E8%A4%87%E8%A3%BD-deep-copy-%E6%B7%BA%E8%A4%87%E8%A3%BD-shallow-copy-51d62ebaebb?source=rss-87e269a0fa54------2</link>
            <guid isPermaLink="false">https://medium.com/p/51d62ebaebb</guid>
            <category><![CDATA[shallow-copy]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[deep-copy]]></category>
            <dc:creator><![CDATA[Kimi]]></dc:creator>
            <pubDate>Fri, 06 Aug 2021 09:07:25 GMT</pubDate>
            <atom:updated>2021-08-06T09:07:25.101Z</atom:updated>
            <content:encoded><![CDATA[<h3>深複製 (Deep Copy)‌</h3><p>把參考物件的變數指向複製過的新物件, 而不是原有的物件.</p><p>值類型的數據, 默認是深複製, Array, Int, String, Float, Boolean, Struct 修改並不會改變原物件‌</p><p>Struct 的屬性如果是引用類型的話, 複製的是指針‌</p><h3>淺複製 (Shallow Copy)</h3><p>‌</p><p>被複製物件的所有變數都的值與原來的物件相同, 對其他物件的引用仍然只指向原來的物件‌</p><p>引用類型的數據, 默認是淺複製, Slice, Map, Channel</p><h3>‌Wiki</h3><h4><a href="https://en.wikipedia.org/wiki/Object_copying">https://en.wikipedia.org/wiki/Object_copying</a>‌</h4><h4>Shallow copy</h4><p>One method of copying an object is the shallow copy. In that case a new object B is <a href="https://en.wikipedia.org/wiki/Object_creation">created</a>, and the fields values of A are copied over to B.<a href="https://en.wikipedia.org/wiki/Object_copying#cite_note-3">[3]</a><a href="https://en.wikipedia.org/wiki/Object_copying#cite_note-4">[4]</a><a href="https://en.wikipedia.org/wiki/Object_copying#cite_note-5">[5]</a> This is also known as a field-by-field copy,<a href="https://en.wikipedia.org/wiki/Object_copying#cite_note-6">[6]</a><a href="https://en.wikipedia.org/wiki/Object_copying#cite_note-7">[7]</a><a href="https://en.wikipedia.org/wiki/Object_copying#cite_note-8">[8]</a> field-for-field copy, or field copy.<a href="https://en.wikipedia.org/wiki/Object_copying#cite_note-9">[9]</a> If the field value is a reference to an object (e.g., a memory address) it copies the reference, hence referring to the same object as A does, and if the field value is a primitive type it copies the value of the primitive type. In languages without primitive types (where everything is an object), all fields of the copy B are references to the same objects as the fields of original A. The referenced objects are thus shared, so if one of these objects is modified (from A or B), the change is visible in the other. Shallow copies are simple and typically cheap, as they can be usually implemented by simply copying the bits exactly.‌</p><h4>Deep copy</h4><p>‌</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/200/0*zpgVW3xCPOtAehlN.png" /></figure><p>A deep copy in progress.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/200/0*h_nNP1r_D3xFTCdn.png" /></figure><p>A deep copy having been completed.</p><p>An alternative is a deep copy, meaning that fields are dereferenced: rather than references to objects being copied, new copy objects are created for any referenced objects, and references to these placed in B. The result is different from the result a shallow copy gives in that the objects referenced by the copy B are distinct from those referenced by A, and independent. Deep copies are more expensive, due to needing to create additional objects, and can be substantially more complicated, due to references possibly forming a complicated graph.‌</p><p>Deep copy is a process in which the copying process occurs recursively. It means first constructing a new collection object and then recursively populating it with copies of the child objects found in the original. In case of deep copy, a copy of object is copied in other object. It means that any changes made to a copy of object do not reflect in the original object. In python, this is implemented using “deep copy()” function.</p><h3>Example in Go</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/890b360cf7d726e5501887f333e369d0/href">https://medium.com/media/890b360cf7d726e5501887f333e369d0/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/29a6de13ca3a0ddede3908eaab2ce93b/href">https://medium.com/media/29a6de13ca3a0ddede3908eaab2ce93b/href</a></iframe><p>可以看出在淺複製時, obj 和 cloneObj 記憶體位置都一樣 (address：0xc000100300). 所以cloneObj被修改後, 原先到object也會被更改</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=51d62ebaebb" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[將筆記發佈至 GitHub Pages: Gitbook CLI + GitHub Actions + GitHub Pages]]></title>
            <link>https://kimi0230.medium.com/%E5%B0%87%E7%AD%86%E8%A8%98%E7%99%BC%E4%BD%88%E8%87%B3-github-pages-gitbook-cli-github-actions-github-pages-2b1dba58f2a0?source=rss-87e269a0fa54------2</link>
            <guid isPermaLink="false">https://medium.com/p/2b1dba58f2a0</guid>
            <category><![CDATA[github-pages]]></category>
            <category><![CDATA[github-actions]]></category>
            <category><![CDATA[gitbook]]></category>
            <dc:creator><![CDATA[Kimi]]></dc:creator>
            <pubDate>Sat, 17 Jul 2021 10:26:10 GMT</pubDate>
            <atom:updated>2021-07-17T10:33:21.706Z</atom:updated>
            <content:encoded><![CDATA[<h3>目的‌</h3><p>使用 Gitbook CLI 將 Markdown 的檔案編譯, 並藉由 GitHub Actions 自動部署到 GitHub Pages‌</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/200/0*g9pSUqHZWjSx0-ir" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/200/0*yw0Dn9aHNsr6I17Q" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/885/0*JZLeaFldqNr0QlEU.png" /></figure><h3>設定流程‌</h3><h3>1. Personal access token‌</h3><h4>A. 申請 Personal access token‌</h4><p>在右上角 Github 頭像 -&gt; Settings -&gt; Developer settings -&gt; Personal access tokens -&gt; Generate new token‌</p><p>勾選 repo:status public_repo‌</p><blockquote><strong>注意: 要保存好剛產生出來 token</strong></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*W6DkIA37k9mliafk" /></figure><h4>B. 將 Personal access token 寫入至 repositories 的 Secrets</h4><p>在你的 repositories Settings -&gt; Secrets -&gt; New repository secre‌</p><p>將上一步驟的 token 寫入, 並命名 GH_ACCESS_TOKEN</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AsE__XK2pz-wDZrh" /></figure><h3>2. 建立 GitHub Actions YAML</h3><p>‌新增 GitHub Actions 的腳本在此路徑:.github/workflows/build.yml</p><p>‌此腳本功能是當你 push code 至 main branch 時, 會執行 jobs 的指令, 藉由 Gitbook CLI 將檔案 build 到 gh-pages 此 branch 的 _book 資料夾‌</p><p>需修改你想要的 branches, MYEMAIL</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ff58f9873dd8d23ef15fa28a7366f542/href">https://medium.com/media/ff58f9873dd8d23ef15fa28a7366f542/href</a></iframe><h3>3. GitHub Pages 設定‌</h3><p>在你的 repositories Settings-&gt;Pages‌</p><p>Source 的 Branch 選 gh-pages</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*sDklNiWjERsH77fz" /></figure><h3>4. 測試腳本‌</h3><p>在你的 repositories Actions -&gt; Workfows -&gt; Run workflow‌</p><p>他就開始跑 yml 腳本, 可以點進去看他執行的 log</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*RXRmkLONYSXgdSNm" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ySpGDw2U3GPXkjYz" /></figure><h3>Gitbook 指令, 插件</h3><p>如果要在本地端使用的話</p><h4>install gitbook package</h4><pre>npm install -g gitbook</pre><pre>npm install -g gitbook-cli‌</pre><p><strong>fix: /usr/local/lib/node_modules/gitbook-cli/node_modules/npm/node_modules/graceful-fs/polyfills.js:287 if (cb) cb.apply(this, arguments)</strong></p><pre>cd /usr/local/lib/node_modules/gitbook-cli/node_modules/npm/node_modules/</pre><pre>npm install graceful-fs@4.2.0 --save‌</pre><h4>gitbook commands‌</h4><p><strong>generate SUMMARY.md</strong></p><pre>book sm -i _book node_modules‌</pre><p><strong>start service</strong></p><pre>gitbook serve .‌</pre><p><strong>build static file</strong></p><pre>gitbook build --output=/build/recipe‌</pre><p>可以將想要的插件寫在 book.json -:代表停用此plugin</p><pre>{&quot;plugins&quot;: [ &quot;-search&quot;, &quot;-lunr&quot;, &quot;search-plus&quot;]}</pre><p>‌如果是本地端要測試的話, 需執行 gitbook install‌</p><p>可以參考這裡<a href="https://gitbookio.gitbooks.io/documentation/content/format/plugins.html">https://gitbookio.gitbooks.io/documentation/content/format/plugins.html</a>‌</p><h3>範例連結</h3><ul><li><a href="https://github.com/kimi0230/Recipe">Gihub連結</a></li><li><a href="https://kimi0230.github.io/Recipe/">Gihub pages</a></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_9Vvs6z8PXam9b9j" /></figure><h3>‌Reference</h3><ul><li><a href="https://wastemobile.gitbooks.io/gitbook-chinese/content/book/gitbook-cli.html">https://wastemobile.gitbooks.io/gitbook-chinese/content/book/gitbook-cli.html</a></li><li><a href="https://github.com/wangzhebufangqi/auto-export-gitbook">https://github.com/wangzhebufangqi/auto-export-gitbook</a></li><li><a href="http://www.chengweiyang.cn/gitbook/github-pages/README.html">http://www.chengweiyang.cn/gitbook/github-pages/README.html</a></li><li><a href="https://www.cnblogs.com/snowdreams1006/p/12023904.html">https://www.cnblogs.com/snowdreams1006/p/12023904.html</a></li><li><a href="https://blog.csdn.net/qq_40889820/article/details/110013310">https://blog.csdn.net/qq_40889820/article/details/110013310</a></li></ul><p>‌</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2b1dba58f2a0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Highlight Source code Paste Into Keynote]]></title>
            <link>https://kimi0230.medium.com/highlight-source-code-paste-into-keynote-6027194ea86c?source=rss-87e269a0fa54------2</link>
            <guid isPermaLink="false">https://medium.com/p/6027194ea86c</guid>
            <category><![CDATA[keynote]]></category>
            <category><![CDATA[highlights]]></category>
            <dc:creator><![CDATA[Kimi]]></dc:creator>
            <pubDate>Mon, 28 Jun 2021 05:11:53 GMT</pubDate>
            <atom:updated>2021-06-28T05:22:50.093Z</atom:updated>
            <content:encoded><![CDATA[<p>Highlight converts sourcecode to HTML, XHTML, RTF, LaTeX, TeX, SVG, BBCode and terminal escape sequences with coloured syntax highlighting.‌</p><p>You can paste result into keynote.</p><p>ps. source code to image, online tool <a href="https://carbon.now.sh/">https://carbon.now.sh/</a></p><h3>Installation</h3><pre>brew install highlight‌</pre><h3>Examples</h3><h4>1. Show result in terminal</h4><pre>highlight -O rtf -S go -K 24 -k Courier-Bold -s Moria main.go -l</pre><p>argument</p><p><a href="http://www.andre-simon.de/doku/highlight/en/highlight.php">http://www.andre-simon.de/doku/highlight/en/highlight.php</a></p><pre>-O, --out-format=&lt;format&gt;      output file in given format</pre><pre>&lt;format&gt;=[html, xhtml, latex, tex, odt, rtf,</pre><pre>ansi, xterm256, truecolor, bbcode, pango, svg]</pre><pre>-S, --syntax=&lt;type|path&gt;       specify type of source code or syntax file path</pre><pre>--syntax-by-name=&lt;name&gt;    specify type of source code by given name</pre><pre>will not read a file of this name, useful for stdin</pre><pre>-K, --font-size=&lt;num?&gt;         set font size (specific to output format)</pre><pre>-k, --font=&lt;font&gt;              set font (specific to output format)</pre><pre>-s, --style=&lt;style|path&gt;       set colour style (theme) or theme file path</pre><pre>-l, --line-numbers             print line numbers in output file</pre><p>‌more style samples</p><p><a href="http://www.andre-simon.de/doku/highlight/en/syntax-samples.php">http://www.andre-simon.de/doku/highlight/en/syntax-samples.php</a></p><h4>2. Output result into your clipboard</h4><pre>highlight -O rtf -S go -K 24 -k Courier-Bold -s Moria main.go -l | pbcopy</pre><h4>3. Create command as : hpas‌</h4><p>You can copy your code and run command hpas go. It will auto generate highlight code, then paste it to keynote or other.‌</p><p>1. create a file name hpas</p><pre>pbpaste | highlight -O rtf -S $1 -K 24 -k Courier-Bold --style Moria -l | pbcopy</pre><p>2. run vi ~/.zshrc</p><pre>export PATH=&quot;$PATH:/Users/kimiimac/myscript&quot;</pre><p>3. run source ~/.zshrc</p><h3>Result</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CdDyA_U5kChDuZ1H" /></figure><p>‌</p><h3>Reference</h3><ul><li><a href="http://www.andre-simon.de/doku/highlight/en/highlight.php">http://www.andre-simon.de/doku/highlight/en/highlight.php</a></li><li><a href="https://gitlab.com/saalen/highlight/-/wikis/CSS-Themes">https://gitlab.com/saalen/highlight/-/wikis/CSS-Themes</a></li><li><a href="https://carbon.now.sh/">https://carbon.now.sh/</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6027194ea86c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Golang Hot Reload: Air, Fresh, Realize]]></title>
            <link>https://kimi0230.medium.com/golang-hot-reload-air-fresh-realize-189c6c7cc91f?source=rss-87e269a0fa54------2</link>
            <guid isPermaLink="false">https://medium.com/p/189c6c7cc91f</guid>
            <category><![CDATA[golang-tools]]></category>
            <category><![CDATA[hot-reload]]></category>
            <category><![CDATA[go]]></category>
            <category><![CDATA[golang]]></category>
            <dc:creator><![CDATA[Kimi]]></dc:creator>
            <pubDate>Thu, 06 May 2021 08:33:01 GMT</pubDate>
            <atom:updated>2021-05-12T15:08:18.039Z</atom:updated>
            <content:encoded><![CDATA[<h3>目的‌</h3><p>Hot Reload 方便修改程式後, 讓程式自動編譯並執行. 省去每次手動編譯與執行.‌</p><p>記錄一下目前自己使用過的三個套件Air, Fresh, Realize‌</p><h3>1. Air (<a href="https://github.com/cosmtrek/air">https://github.com/cosmtrek/air</a>)‌</h3><ul><li>較推薦使用此套件</li><li>原先是使用 <a href="https://github.com/gravityblast/fresh">fresh</a>, 但是遇到fresh不能在執行指令後面帶參數.‌</li></ul><h4>features‌</h4><ul><li>Colorful log output</li><li>Customize build or binary command</li><li>Support excluding subdirectories</li><li>Allow watching new directories after Air started</li><li>Better building process‌</li></ul><h4>Installation</h4><pre># binary will be $(go env GOPATH)/bin/air</pre><pre>curl -sSfL <a href="https://raw.githubusercontent.com/cosmtrek/air/master/install.sh">https://raw.githubusercontent.com/cosmtrek/air/master/install.sh</a> | sh -s -- -b $(go env GOPATH)/bin</pre><pre># or install it into ./bin/</pre><pre>curl -sSfL <a href="https://raw.githubusercontent.com/cosmtrek/air/master/install.sh">https://raw.githubusercontent.com/cosmtrek/air/master/install.sh</a> | sh -s</pre><pre>air -v‌</pre><h4>Usage</h4><pre># 初始化設定檔</pre><pre>air init</pre><pre># 預設找 .air.toml 此設定檔</pre><pre>air</pre><pre># 選擇要執行的設定檔</pre><pre>air -c .air.toml</pre><pre># Debug</pre><pre>air -d</pre><h4>‌sample config</h4><ul><li><a href="https://github.com/cosmtrek/air/blob/master/air_example.toml">https://github.com/cosmtrek/air/blob/master/air_example.toml</a>‌</li></ul><p>我的設定檔</p><pre># Config file for [Air](https://github.com/cosmtrek/air) in TOML format</pre><pre># Working directory</pre><pre># . or absolute path, please note that the directories following must be under root.</pre><pre>root = &quot;.&quot;</pre><pre>tmp_dir = &quot;tmp&quot;</pre><pre>[build]</pre><pre># Just plain old shell command. You could use `make` as well.</pre><pre>cmd = &quot;go build -o ./tmp/main .&quot;</pre><pre># Binary file yields from `cmd`.</pre><pre>bin = &quot;tmp/main&quot;</pre><pre># Customize binary.</pre><pre>full_bin = &quot;APP_ENV=dev APP_USER=air ./tmp/main&quot;</pre><pre># Watch these filename extensions.</pre><pre>include_ext = [&quot;go&quot;, &quot;tpl&quot;, &quot;tmpl&quot;, &quot;html&quot;, &quot;css&quot;, &quot;js&quot;, &quot;env&quot;, &quot;yaml&quot;]</pre><pre># Ignore these filename extensions or directories.</pre><pre>exclude_dir = [&quot;assets&quot;, &quot;tmp&quot;, &quot;vendor&quot;, &quot;node_modules&quot;, &quot;build&quot;]</pre><pre># Watch these directories if you specified.</pre><pre>include_dir = []</pre><pre># Exclude files.</pre><pre>exclude_file = []</pre><pre># Exclude unchanged files.</pre><pre>exclude_unchanged = true</pre><pre># This log file places in your tmp_dir.</pre><pre>log = &quot;air.log&quot;</pre><pre># It&#39;s not necessary to trigger build each time file changes if it&#39;s too frequent.</pre><pre>delay = 1000 # ms</pre><pre># Stop running old binary when build errors occur.</pre><pre>stop_on_error = true</pre><pre># Send Interrupt signal before killing process (windows does not support this feature)</pre><pre>send_interrupt = false</pre><pre># Delay after sending Interrupt signal</pre><pre>kill_delay = 500 # ms</pre><pre>[log]</pre><pre># Show log time</pre><pre>time = false</pre><pre>[color]</pre><pre># Customize each part&#39;s color. If no color found, use the raw app log.</pre><pre>main = &quot;magenta&quot;</pre><pre>watcher = &quot;cyan&quot;</pre><pre>build = &quot;yellow&quot;</pre><pre>runner = &quot;green&quot;</pre><pre>[misc]</pre><pre># Delete tmp directory on exit</pre><pre>clean_on_exit = true‌</pre><h3>2. Fresh (<a href="https://github.com/gravityblast/fresh">https://github.com/gravityblast/fresh</a>)</h3><ul><li>目前看起來沒在更新了</li><li>沒法在指令後面帶入參數</li><li>如果go build返回錯誤, 會將記錄在tmp資料夾中‌</li></ul><h4>Installation</h4><pre>go get github.com/pilu/fresh‌</pre><h4>Usage</h4><pre>fresh</pre><pre># 選擇要執行的設定檔</pre><pre>fresh -c other_runner.conf</pre><h4>sample config</h4><pre>root:              .</pre><pre>tmp_path:          ./tmp</pre><pre>build_name:        runner-build</pre><pre>build_log:         runner-build-errors.log</pre><pre>valid_ext:         .go, .tpl, .tmpl, .html</pre><pre>no_rebuild_ext:    .tpl, .tmpl, .html</pre><pre>ignored:           assets, tmp</pre><pre>build_delay:       600</pre><pre>colors:            1</pre><pre>log_color_main:    cyan</pre><pre>log_color_build:   yellow</pre><pre>log_color_runner:  green</pre><pre>log_color_watcher: magenta</pre><pre>log_color_app:</pre><h3>3. realize (<a href="https://github.com/oxequa/realize">https://github.com/oxequa/realize</a>)‌</h3><h4>features</h4><ul><li>High performance Live Reload.</li><li>Manage multiple projects at the same time.</li><li>Watch by custom extensions and paths.</li><li>All Go commands supported.</li><li>Switch between different Go builds.</li><li>Custom env variables for project.</li><li>Execute custom commands before and after a file changes or globally.</li><li>Export logs and errors to an external file.</li><li>Step-by-step project initialization.</li><li>Redesigned panel that displays build errors, console outputs and warnings.</li></ul><p>‌</p><h3>總結‌</h3><p>目前較推薦使 air , fresh 遇到無法帶入參數, 且可設定的東西較少決了. realize 忘了之前是mod還是vendor無法安裝, 不知道解了沒.</p><p>‌</p><h3>Reference‌</h3><ul><li><a href="https://github.com/cosmtrek/air">https://github.com/cosmtrek/air</a></li><li><a href="https://github.com/gravityblast/fresh">https://github.com/gravityblast/fresh</a></li><li><a href="https://github.com/oxequa/realize">https://github.com/oxequa/realize</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=189c6c7cc91f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Hackintosh Big Sur11.1: Skylake i5 6400, ASUS Z170m-plus]]></title>
            <link>https://kimi0230.medium.com/hackintosh-big-sur11-1-skylake-i5-6400-asus-z170m-plus-45b3380ec943?source=rss-87e269a0fa54------2</link>
            <guid isPermaLink="false">https://medium.com/p/45b3380ec943</guid>
            <category><![CDATA[macos]]></category>
            <category><![CDATA[hackintosh]]></category>
            <category><![CDATA[黑蘋果]]></category>
            <dc:creator><![CDATA[Kimi]]></dc:creator>
            <pubDate>Fri, 29 Jan 2021 07:56:00 GMT</pubDate>
            <atom:updated>2021-10-08T01:17:36.577Z</atom:updated>
            <content:encoded><![CDATA[<h3>Hackintosh Big Sur11.1: OpenCore, Skylake i5 6400, ASUS Z170m-plus</h3><h3>官方安裝文件</h3><p>‌</p><p><strong>最詳細的安裝說明, 請直接看官網: </strong><a href="https://dortania.github.io/OpenCore-Install-Guide/"><strong>https://dortania.github.io/OpenCore-Install-Guide/</strong></a></p><p>我做好的EFI: <a href="https://github.com/kimi0230/ASUS-Z170M-PLUS-Skylake-Hackintosh">https://github.com/kimi0230/ASUS-Z170M-PLUS-Skylake-Hackintosh</a></p><h3>摘要</h3><p>‌</p><p>此篇文章主要記錄‌</p><ul><li>安裝黑蘋果的流程</li><li>相關設定的對應連結</li><li>usb port客製</li><li>需要下載的軟體‌</li></ul><p><strong>其實直接買 Mac mini 比較爽</strong></p><p><strong>最後有Github 連結存放 EFI</strong>‌</p><h3>硬體需求</h3><p>‌</p><p><a href="https://dortania.github.io/Anti-Hackintosh-Buyers-Guide/">https://dortania.github.io/Anti-Hackintosh-Buyers-Guide/</a>‌</p><ul><li>CPU : 使用 intel cpu 比較輕鬆</li><li>SSD: m2 ssd 需要挑選某幾個型號, 我使用 wd blue sn550 1t</li><li>VGA: 挑AMD某幾個型號, 我使用RX5500</li><li>WIFI: 建議買 BCM94360CD, wifi, 藍芽皆有. 免驅動還可以使用airdrop‌</li></ul><h3>BIOS設置</h3><h4>Disable</h4><ul><li>快速啟動</li><li>VT-d（如果將DisableIoMapper設置為YES，則可以啟用）</li><li>CSM</li><li>Thunderbolt</li><li>Intel SGX</li><li>Intel Platform Trust</li><li>CFG鎖（MSR 0xE2寫保護）</li><li>如果無法在BIOS中關閉（甚至找不到），請考慮對其進行修補。有關更多信息，請參見固定CFG鎖。 AMD CPU用戶無需擔心。‌</li></ul><h4>Enable</h4><ul><li>VT-x</li><li>4G以上解碼</li><li>Hyper-Threading</li><li>Execute Disable Bit</li><li>EHCI/XHCI Hand-off</li><li>操作系統類型：Windows 8.1 / 10 UEFI模式</li><li>舊版RTC設備（與Z370 +相關）</li></ul><p>‌</p><h3>安裝流程</h3><h3>00. OpenCore 基本文件架構</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/301/0*9JzMwv9EKwCtF1vC" /></figure><p>Enter a caption for this image (optional)</p><h3>01. 作業流程</h3><ul><li>下載好的OC引導文件，把Doc文件夾下面的 SampleFull.plist 改名為 config.plist，並把此文件移動到EFI目錄裡面</li><li>打開EFI ㄧ&gt; Kexts 資料夾，把主機板相關硬體的kexts 先放進去</li><li>OC－ACPI、Drivers、Kexts、Tools 已經內建許多工具，我們只保留自己所需要的工具即可。</li><li>ACPI：加入修補程式, SSDT</li><li>USB 引導</li></ul><h3>會動到的資料夾跟檔案</h3><ul><li>OC/Kexts</li><li>OC/ACPI</li><li>OC/config.plist</li></ul><p>‌</p><h3>主要會用的軟體</h3><ul><li>DSDT/SSDT 反編譯工具: <a href="https://www.acpica.org/downloads">isal</a></li><li>編輯config.plist用, 擇一: <a href="https://mackie100projects.altervista.org/download-opencore-configurator/">opencore configurator</a> 或 <a href="https://github.com/corpnewt/ProperTree">ProperTree</a></li><li>產生mac 序號: <a href="https://github.com/corpnewt/GenSMBIOS">GenSMBIOS</a></li><li>掛載EFI, 用在製作usb或事後修改系統的EFI: <a href="https://github.com/corpnewt/MountEFI">MountEFI</a></li><li>安裝好黑蘋果後可看一些設定: <a href="https://github.com/headkaze/Hackintool">Hackintool</a></li></ul><h3>02. Kexts</h3><p><a href="https://dortania.github.io/OpenCore-Install-Guide/ktext.html#kexts">https://dortania.github.io/OpenCore-Install-Guide/ktext.html#kexts</a></p><ul><li>kernel 的擴充, 根據你的主機板決定要導入哪些kexts</li><li><a href="https://bitbucket.org/RehabMan/os-x-usb-inject-all/downloads/">SBInjectAll</a> : oc上面提到 “ Shouldn’t be needed on Desktop Skylake and new “, 但在安裝畫面usb皆無反應, 建議usb無法使用時將此補上</li><li>下載Kexts放入 OC/Kexts‌</li></ul><h4>檔案下載: <a href="https://bitbucket.org/profdrluigi/kextupdater/downloads/">https://bitbucket.org/profdrluigi/kextupdater/downloads/</a></h4><p>‌</p><h3>03. OC/ACPI (SSDT)‌</h3><p><a href="https://dortania.github.io/Getting-Started-With-ACPI/">https://dortania.github.io/Getting-Started-With-ACPI/</a>‌</p><ul><li>根據cpu決定要導入哪些必要的SSDT</li><li>產生ssdt文件工具 <a href="https://github.com/corpnewt/SSDTTime">https://github.com/corpnewt/SSDTTime</a></li><li>將ssdt檔案放入 OC/ACPI</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/860/0*tjLVb8tN_66rKjUs" /></figure><p>Enter a caption for this image (optional)</p><h3>04. config.plist 設定‌</h3><p><a href="https://dortania.github.io/OpenCore-Install-Guide/config.plist/#creating-your-config-plist">https://dortania.github.io/OpenCore-Install-Guide/config.plist/#creating-your-config-plist</a></p><p>‌</p><ul><li>使用 <a href="https://mackie100projects.altervista.org/download-opencore-configurator/">opencore configurator</a> 或 <a href="https://github.com/corpnewt/ProperTree">ProperTree</a> 來編輯檔案</li><li>依據你的CPU, 主機板, 顯示卡來設定你的config</li><li>使用 <a href="https://github.com/corpnewt/GenSMBIOS">GenSMBIOS</a> 產生序號</li><li><a href="https://heipg.cn/tutorial/smbios-id-and-details.html">SMBIOS ID, Platform ID 快速查詢</a></li><li>或者從官網看要選哪種 <a href="https://dortania.github.io/OpenCore-Install-Guide/extras/smbios-support.html#how-to-decide">https://dortania.github.io/OpenCore-Install-Guide/extras/smbios-support.html#how-to-decide</a></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gsubWMftpWD6Fal4.jpg" /></figure><ul><li>檢查序號是否有人使用 <a href="https://checkcoverage.apple.com/tw/zh/">https://checkcoverage.apple.com/tw/zh/</a></li></ul><blockquote><em>ASUS Z170M-PLUS(realtek 887) Audio ID = 1 Skylake: iMac17,1</em></blockquote><p>‌</p><ul><li>最後檢查 Config 是否有誤 <a href="https://opencore.slowgeek.com/">https://opencore.slowgeek.com/</a></li></ul><p>‌</p><h3>05. 導引製作/安裝‌</h3><p><a href="https://dortania.github.io/OpenCore-Install-Guide/installer-guide/#creating-the-usb">https://dortania.github.io/OpenCore-Install-Guide/installer-guide/#creating-the-usb</a>‌</p><ol><li>打開磁碟工具。從左邊的欄位找到要製作USB引導碟的『主體』。選擇『清除』，選擇格式：Mac OS 擴充格式（日誌式），架構為GUID分區圖配置表，名稱暫時為USB <a href="https://www.macobserver.com/tips/quick-tip/how-to-format-drive-guid/">https://www.macobserver.com/tips/quick-tip/how-to-format-drive-guid/</a></li><li>安裝macOS映像檔：</li></ol><p>APP store 下載 <a href="https://support.apple.com/en-us/HT201372">https://support.apple.com/en-us/HT201372</a></p><p>打開終端機輸入</p><ul><li>sudo /Applications/Install\ macOS\ Big\ Sur.app/Contents/Resources/createinstallmedia — volume /Volumes/MyVolume</li></ul><h3>06. 將efi放入製作好usb導引‌</h3><ul><li>使用 <a href="https://github.com/corpnewt/MountEFI">MountEFI</a> 掛載檔案, 就可以把你的efi放入‌</li></ul><h3>07. 訂製USB Ports</h3><ul><li>為了避免機器睡眠會有問題(機率很小), 需要訂製一下usb的port</li><li>使用<a href="https://github.com/headkaze/Hackintool">Hackintool</a>: 準備usb2.0跟3.0的裝置如隨身碟, 將裝置插入電腦看看tool是哪個位置偵測到,並對此位置做修改</li><li>詳細請參考 <a href="https://www.youtube.com/watch?v=5f9CpjE3ZpA&amp;t=1s">【司波图】10代CometLake平台黑苹果Opencore6.0下的声卡驱动&amp;USB定制</a></li></ul><p>‌</p><h3>EFI : ASUS-Z170M-PLUS-Skylake‌</h3><ul><li><a href="https://github.com/kimi0230/ASUS-Z170M-PLUS-Skylake-Hackintosh">https://github.com/kimi0230/ASUS-Z170M-PLUS-Skylake-Hackintosh</a></li></ul><p>‌</p><h3>其他問題</h3><ul><li>Apple TV 無法播放: <a href="https://github.com/acidanthera/WhateverGreen/blob/master/Manual/FAQ.Chart.md">https://github.com/acidanthera/WhateverGreen/blob/master/Manual/FAQ.Chart.md</a></li><li>iMovies 無法匯出檔案</li></ul><p>change iMac17,1 to iMac19,1</p><h3>Reference‌</h3><ul><li><a href="https://dortania.github.io/OpenCore-Install-Guide/">https://dortania.github.io/OpenCore-Install-Guide/</a></li><li><a href="https://heipg.cn/tutorial/smbios-id-and-details.html">https://heipg.cn/tutorial/smbios-id-and-details.html</a></li><li><a href="https://heipg.cn/tutorial/custom-usbports-for-hackintosh.html">https://heipg.cn/tutorial/custom-usbports-for-hackintosh.html</a></li><li><a href="https://www.imacpc.net/archives/3340">https://www.imacpc.net/archives/3340</a></li><li><a href="https://www.macobserver.com/tips/quick-tip/how-to-format-drive-guid/">https://www.macobserver.com/tips/quick-tip/how-to-format-drive-guid/</a></li><li><a href="https://medium.com/ishengp-laboratory/ishengp-catalina-opencore-80be977427ae">https://medium.com/ishengp-laboratory/ishengp-catalina-opencore-80be977427ae</a></li><li><a href="https://www.kancloud.cn/chandler/mac_os/480624">https://www.kancloud.cn/chandler/mac_os/480624</a></li><li><a href="https://www.youtube.com/watch?v=5f9CpjE3ZpA&amp;t=1s">[youtube] 【司波图】10代CometLake平台黑苹果Opencore6.0下的声卡驱动&amp;USB定制</a></li><li><a href="https://www.youtube.com/watch?v=Lu6Kmz5aDhY">[youtube] Intel Coffee Lake平台完美黑苹果系统安装教程（Opencore+Catalina15.4）</a></li></ul><p>‌</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=45b3380ec943" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[iPhone Shortcut Play Spotify Playlist by Spotify API]]></title>
            <link>https://kimi0230.medium.com/iphone-shortcut-play-spotify-playlist-by-spotify-api-b4c066727f7a?source=rss-87e269a0fa54------2</link>
            <guid isPermaLink="false">https://medium.com/p/b4c066727f7a</guid>
            <category><![CDATA[ios-shortcuts]]></category>
            <category><![CDATA[siri]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[spotify]]></category>
            <category><![CDATA[shortcuts]]></category>
            <dc:creator><![CDATA[Kimi]]></dc:creator>
            <pubDate>Fri, 18 Sep 2020 08:19:31 GMT</pubDate>
            <atom:updated>2020-09-18T08:31:33.064Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/306/1*FjTbZ_nhz03-_ttPzRjzTw.png" /></figure><h3>目的</h3><p>利用 iOS 的 shortcut, 自動執行 Spotify 特定歌單或專輯. 或者藉由 siri 播放特定歌曲.‌</p><h3>取得 Spotify access token</h3><p>可參考 doc 的 Authorization Guide (<a href="https://developer.spotify.com/documentation/general/guides/authorization-guide/">https://developer.spotify.com/documentation/general/guides/authorization-guide/</a>)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*8cZf69Y3sqvxOPpy" /></figure><h3>‌1. 到 Spotify dev 申請一個APP</h3><p><a href="https://developer.spotify.com/dashboard/login">My Dashboard | Spotify for Developers</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*pMnOnRtHT-2sYj7K" /></figure><p>填好資料後, 記住 Client ID 和 Secret.</p><h3>2. 點擊 EDIT SETTINGS, 在 Redirect URIs 這欄填入隨便自己的一個 Github 網址</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*VcAaOvPePxc3ZMe_" /></figure><h3>3. 將剛剛 GitHub URL encode 一下, 藉由此網址</h3><p><a href="https://www.urlencoder.org/">URL Encode and Decode - Online</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/805/0*1h8c-IVRt5iqwfdp" /></figure><h3>4. 選則該 token可以使用的權限(Scopes)</h3><p><a href="https://developer.spotify.com/documentation/general/guides/scopes/">Authorization Scopes | Spotify for Developers</a></p><p>我選了這幾個. 記住中間都使用一個空白隔開</p><pre>playlist-read-private user-modify-playback-state user-read-playback-state</pre><h3>5. 將前面幾步驟的東西組成一個網址, 貼到瀏覽器</h3><p>https://accounts.spotify.com/authorize?client_id=<strong>{第1步取得的Client ID}</strong>&amp;response_type=code&amp;redirect_uri=<strong>{第3步encode的github url}</strong>&amp;scope=<strong>{第4步的scopes}</strong></p><h3>6. 按下同意, 會導向先前填的 Github 網址, 並且後面會出現code=”xxxx”</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1008/0*kdWWMZBW49RFgVEj" /></figure><h3>7. 組出 API header Authorization 格式</h3><pre>第一步的Client ID:第一步的Client Secret</pre><p>並用此網址來做 base64 encode</p><p><a href="https://www.base64encode.org/">Base64 Encode and Decode - Online</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/900/0*hmI-B5GsDelV9eD2" /></figure><h3>8. 可以開始打申請 Token 的API了～用 Postman 或者 Terminal 的 curl 來打. 並記住refresh_token 跟 access_token</h3><pre>curl --location --request POST &#39;https://accounts.spotify.com/api/token&#39; \</pre><pre>--header &#39;Authorization: Basic {第7步的 API  header  Authorization 格式}&#39; \</pre><pre>--header &#39;Content-Type: application/x-www-form-urlencoded&#39; \</pre><pre>--data-urlencode &#39;grant_type=authorization_code&#39; \</pre><pre>--data-urlencode &#39;code={第6步取得的 code}&#39; \</pre><pre>--data-urlencode &#39;redirect_uri={你的github url}&#39;</pre><p>可參考 ‌Spotify doc</p><p>request 參數</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/913/0*E6CU0N_m6xg5kqg2" /></figure><p>Respone 參數</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/885/0*YTkW3hD5ZS4xRXB2" /></figure><blockquote>因為access_token, 有效期限只有3600秒. 所以要記住 refresh_token. 藉由refresh_token重新去要access_token</blockquote><h3>撰寫 IOS Shortcut‌</h3><h3>1. 呼叫API:從refresh_token取得新的access_token</h3><p><a href="https://www.icloud.com/shortcuts/29dba791327c42e9bdbdf13fcac86355">https://www.icloud.com/shortcuts/29dba791327c42e9bdbdf13fcac86355</a></p><p>有三個變數需要帶入: 在”文字”上面分別填入第8步的 refresh_token與 先前的client_id, secret.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*T69rlB97UHlEq6xh" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9QYDW15eLFD7dlop" /></figure><h3>2. 呼叫API:取得現在正在執行spotify的裝置id (device_id) . 這個捷徑是取正在行動裝置上執行的ID</h3><p><a href="https://www.icloud.com/shortcuts/1633627d0ca946089dac40384e4e52b3">Shortcuts</a></p><h3>3.呼叫API: 設定是否隨機播放API</h3><p><a href="https://www.icloud.com/shortcuts/1a80e3df57314883b344ebfcfd58a86a">Shortcuts</a></p><h3>4. 呼叫API: 播放指定歌單, 目前設定此歌單(<a href="https://open.spotify.com/playlist/1AL0bu2zPr1GXn4TE9toBU?si=akwdzQ_sRRShCAL2bPlqng">https://open.spotify.com/playlist/1AL0bu2zPr1GXn4TE9toBU?si=akwdzQ_sRRShCAL2bPlqng</a>)</h3><blockquote>Spotify uri 為: <strong>spotify:playlist:1AL0bu2zPr1GXn4TE9toBU</strong></blockquote><p><a href="https://www.icloud.com/shortcuts/665225ca7788459bbbec0d8e56e0550c">Shortcuts</a></p><p>要更換歌單可以修改context_uri</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ea9MiIqH-WKqcCvc" /></figure><p><strong>5. 整合上面的捷徑</strong></p><p><a href="https://www.icloud.com/shortcuts/589ba987db074f7896470ecb89b920de">Shortcuts</a></p><h3>步驟1取的token. 打開 iPhone 的 Spotify app. 目的是為了讓後面的取得 devcie id API 可以使用</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*vk2xtE7D3CDsuQey" /></figure><h3>步驟2取得device id</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*eD2Yxdid0EeGq7KP" /></figure><p>‌</p><blockquote>將 device id 跟 access token 帶入辭典. 此變數可以給步驟3跟 步驟4的捷徑使用. state: true代表隨機播放</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*3PeZnZm-KHyFk_uh" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*szWZpFw3HV_Laken" /></figure><h3>6.設定完之後可以在自動化那邊新增鬧中停止時觸發捷徑, 或者對著 Siri 大聲喊 Danny go demo (你的捷徑名稱). 就可以自動執行腳本了!</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*VJ07EVCFZrZbZpQU" /></figure><h3>Reference</h3><p><a href="https://medium.com/%E6%B5%B7%E5%A4%A7-ios-app-%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88/%E4%B8%B2%E6%8E%A5%E5%A4%9A%E7%A8%AE-api-%E8%A3%BD%E4%BD%9Clady-gaga-app-spotify%E7%AF%87-2d39c52da7e4">https://medium.com/%E6%B5%B7%E5%A4%A7-ios-app-%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88/%E4%B8%B2%E6%8E%A5%E5%A4%9A%E7%A8%AE-api-%E8%A3%BD%E4%BD%9Clady-gaga-app-spotify%E7%AF%87-2d39c52da7e4</a></p><p>‌<a href="https://www.igeeksblog.com/best-spotify-siri-shortcuts/">https://www.igeeksblog.com/best-spotify-siri-shortcuts/</a></p><p>‌</p><p>‌</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b4c066727f7a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[OpenAPI: Swagger API Swaggo/swag]]></title>
            <link>https://kimi0230.medium.com/openapi-swagger-api-swaggo-swag-7b050f82af98?source=rss-87e269a0fa54------2</link>
            <guid isPermaLink="false">https://medium.com/p/7b050f82af98</guid>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[open-api]]></category>
            <category><![CDATA[swagger]]></category>
            <category><![CDATA[gin]]></category>
            <category><![CDATA[swaggo]]></category>
            <dc:creator><![CDATA[Kimi]]></dc:creator>
            <pubDate>Tue, 04 Aug 2020 05:56:10 GMT</pubDate>
            <atom:updated>2020-08-04T06:19:12.108Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>目的</strong></h3><p>解決開發 API 文件, 但又不想花時間同時開發跟維護文件. 加個欄位還要跑去改文件.</p><p>Swagger 可快速產生API文件. 且多個程式語言皆有支援</p><ul><li><a href="https://github.com/swaggo/swag">Swaggo/swag</a> 是由Golang撰寫, 且支援</li><li><a href="http://github.com/swaggo/gin-swagger">gin</a></li><li><a href="http://github.com/swaggo/echo-swagger">echo</a></li><li><a href="https://github.com/swaggo/buffalo-swagger">buffalo</a></li><li><a href="https://github.com/swaggo/http-swagger">net/http</a></li><li><a href="https://github.com/i-love-flamingo/swagger">flamingo</a></li><li><a href="https://github.com/arsmn/fiber-swagger">fiber</a></li></ul><p>‌此範例使用 gin 來實作. 藉由註解, Swagger就能產文件.依據格式寫出來的註解可對應到文檔說明</p><h3>安裝 package (gin, swagger)</h3><p>gin</p><pre>go get -u github.com/gin-gonic/gin</pre><p>swagger</p><pre>go get -u github.com/swaggo/swag/cmd/swag</pre><h3>Demo範例,資料夾結構</h3><pre>├── Readme.md<br>├── app<br>│   ├── controllers<br>│   │   └── api<br>│   │       ├── test<br>│   │       │   └── test.go<br>│   │       └── v1<br>│   │           └── account<br>│   │               └── account.go<br>│   ├── models<br>│   │   ├── account.go<br>│   │   └── error.go<br>│   └── services<br>│       └── httputil<br>│           └── error.go<br>├── docs<br>│   ├── docs.go<br>│   ├── swagger.json<br>│   └── swagger.yaml<br>├── main.go<br>├── routes<br>│   └── routes.go<br>└── tmp<br>└── runner-build</pre><h3>導入 swagger 文檔, package, 匯入路由</h3><h3>main.go</h3><blockquote><em>Debug Mode 才將 Swagger 路由導入</em></blockquote><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/abd477bd108a375c567c88c5e2fe3029/href">https://medium.com/media/abd477bd108a375c567c88c5e2fe3029/href</a></iframe><h3>Swagger 註解</h3><p>Swagger 是藉由註解內容來產生文件的, 在main.go上面是一般API訊息. 每個api func 上面註解用來顯示使用方法,需要哪些參數,回傳結果等等</p><p>‌一般API訊息</p><pre>title         簡單API專案的標題或主要的業務功能<br>version         目前這專案API的版本<br>description 簡單描述<br>tersOfService 服務條款<br>tag.name 標籤名稱<br>tag.description 標籤描述<br>tag.docs.url 標籤的外部文檔URL<br>tag.docs.description 標籤的外部文檔說明<br>contact.name 作者名稱<br>contact.url 作者網址<br>contact.email 作者email<br>license.name 許可證名稱<br>license.url 許可證網址<br>host         服務名稱或者是ip<br>BasePath 基本URL路徑, (/api/v1)<br>schemes         提供的協定, (http, https)</pre><blockquote><strong>使用＠開頭當變數 後面的值需使用一個空</strong>白</blockquote><h4>main.go</h4><pre>/*<br>@title Swagger Example API With Gin<br>@version 1.0<br>@description This is a sample server celler server.<br>@termsOfService <a href="http://swagger.io/terms/">http://swagger.io/terms/</a><br>@contact.name API Support<br>@contact.url <a href="http://www.swagger.io/support">http://www.swagger.io/support</a><br>@contact.email support@swagger.io<br>@license.name Apache 2.0<br>@license.url <a href="http://www.apache.org/licenses/LICENSE-2.0.html">http://www.apache.org/licenses/LICENSE-2.0.html</a><br>@host localhost:5566<br>@BasePath /api/v1<br>@query.collection.format multi<br>@x-extension-openapi {&quot;example&quot;: &quot;value on a json format&quot;}<br>*/</pre><pre>func main() {...}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*l4QLzkyDyIOlHk7KHtrMEA.png" /></figure><h3>API操作</h3><pre>description	操作行為的詳細說明<br>summary	描述該API<br>id	用於標示API的唯一字符,在所有API操作中必須唯一。<br>tags	歸屬同一類的API的tag, 以逗號分隔<br>accept	request的context-type<br>produce	response的context-type<br>param	參數按照: `參數名` `參數類型` `參數的資料類型` `是否必填` `註解`<br>header	response header: `return code` `參數類型` `資料類型` `註解`<br>router	path httpMethod</pre><h4>app/controllers/api/v1/account/account.go</h4><pre>// AddAccount godoc<br>// @Summary X01 Add an account<br>// @Description add by json account<br>// @Tags accounts, accounts2<br>// @Accept  json<br>// @Produce  json<br>// @Param account body models.AddAccount true &quot;Add account&quot;<br>// @Success 200 {object} models.Account<br>// @Failure 400 {object} httputil.HTTPError<br>// @Failure 404 {object} httputil.HTTPError<br>// @Failure 500 {object} httputil.HTTPError<br>// @Router /accounts [post]</pre><pre>func AddAccount(c *gin.Context) {...}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ivt2qkAsGYJj8YUZlxVBQw.png" /></figure><h3>參數類型</h3><p><a href="https://github.com/swaggo/swag#param-type">https://github.com/swaggo/swag#param-type</a></p><ul><li>query</li><li>path</li><li>header</li><li>body</li><li>formData</li></ul><h3>‌Data類型</h3><p><a href="https://github.com/swaggo/swag#data-type">https://github.com/swaggo/swag#param-type</a></p><ul><li>string (string)</li><li>integer (int, uint, uint32, uint64)</li><li>number (float32)</li><li>boolean (bool)</li><li>user defined struct</li></ul><h3>Mime Types</h3><p><a href="https://github.com/swaggo/swag#mime-types"><strong>https://github.com/swaggo/swag#mime-types</strong></a></p><h3>屬性</h3><p><a href="https://github.com/swaggo/swag#attribute">https://github.com/swaggo/swag#attribute</a></p><h3>定義回傳結構</h3><h4>app/models/account.go</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6e5e98fe2cbfa1d9266cdea234c2fa47/href">https://medium.com/media/6e5e98fe2cbfa1d9266cdea234c2fa47/href</a></iframe><h4>app/services/httputil/error.go</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/99016ad0afdc3c3cb56f976735cf71f4/href">https://medium.com/media/99016ad0afdc3c3cb56f976735cf71f4/href</a></iframe><h3>重新產生Swagger 文件</h3><pre>swag init</pre><h3>啟動 Gin Server</h3><pre>go run main.go</pre><h3>API Doc 連結</h3><p><a href="http://localhost:8080/swagger/index.html">http://localhost:8080/swagger/index.html</a></p><h3>完整範例</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*UoGu4opzBQxV3F2f" /></figure><p><a href="https://github.com/kimi0230/swagger_gin_demo">https://github.com/kimi0230/swagger_gin_demo</a></p><p>‌</p><h3>參考</h3><ul><li><a href="https://github.com/swaggo/swag">swaggo/swag</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7b050f82af98" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Golang Export Excel by Excelize and Gorm]]></title>
            <link>https://kimi0230.medium.com/golang-export-excel-by-excelize-and-gorm-3add1d07b80f?source=rss-87e269a0fa54------2</link>
            <guid isPermaLink="false">https://medium.com/p/3add1d07b80f</guid>
            <dc:creator><![CDATA[Kimi]]></dc:creator>
            <pubDate>Tue, 07 Apr 2020 10:06:35 GMT</pubDate>
            <atom:updated>2020-04-07T12:49:27.710Z</atom:updated>
            <content:encoded><![CDATA[<h3>目的</h3><p>‌使用sequel pro 匯出excel時, 遇到了欄位名稱跑掉等等問題．故直接寫一個匯出功能, 藉由Gorm 撈取Mysql 資料, 並寫入Excel.</p><h3>‌安裝</h3><pre>go get -u github.com/360EntSecGroup-Skylar/excelize<br>go get -u github.com/jinzhu/gorm</pre><h3>‌檔案結構</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/330/1*3HKuLMcvHrCf1VzcBhMvww.png" /></figure><h3>‌設定.env</h3><p>此設定給mysql/mysql.go 連線使用</p><pre>## Database</pre><pre>DB_CONNECTION=mysql</pre><pre>DB_HOST=</pre><pre>DB_PORT=3306</pre><pre>DB_DATABASE=</pre><pre>DB_USERNAME=</pre><pre>DB_PASSWORD=</pre><h3>‌建立excel</h3><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/43de07ede933e1a2da64d37843ca494c/href">https://medium.com/media/43de07ede933e1a2da64d37843ca494c/href</a></iframe><h3>編譯</h3><pre>go build excelize_demo.go</pre><h3>‌使用方法</h3><pre>./excelize_demo -f {file name}</pre><pre>./excelize_demo -f kimi</pre><h3>Excel 相關設定</h3><ul><li><a href="https://xuri.me/excelize/zh-tw/workbook.html#CopySheet">https://xuri.me/excelize/zh-tw/workbook.html#CopySheet</a></li></ul><h3>Reference</h3><ul><li><a href="https://github.com/360EntSecGroup-Skylar/excelize">https://github.com/360EntSecGroup-Skylar/excelize</a></li><li><a href="https://xuri.me/excelize/zh-tw/workbook.html#CopySheet">https://xuri.me/excelize/zh-tw/workbook.html#CopySheet</a></li></ul><p>‌</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3add1d07b80f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Vue Router Refresh : Uncaught (in promise) NavigationDuplicated]]></title>
            <link>https://kimi0230.medium.com/vue-router-refresh-uncaught-in-promise-navigationduplicated-be5195f5dd7e?source=rss-87e269a0fa54------2</link>
            <guid isPermaLink="false">https://medium.com/p/be5195f5dd7e</guid>
            <category><![CDATA[vue-router]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[vuex]]></category>
            <category><![CDATA[vuejs]]></category>
            <dc:creator><![CDATA[Kimi]]></dc:creator>
            <pubDate>Fri, 27 Mar 2020 09:56:32 GMT</pubDate>
            <atom:updated>2020-03-27T14:10:11.245Z</atom:updated>
            <content:encoded><![CDATA[<h3>Vue Router Error Message : Uncaught (in promise) NavigationDuplicated / Router Refresh</h3><h3>問題</h3><p>‌如果同一個路由又用 router 導向同一個路由會遇到下面的錯誤</p><blockquote><em>vue-router.esm.js?8c4f:2089 Uncaught (in promise) NavigationDuplicated {_name: “NavigationDuplicated”, name: “NavigationDuplicated”, message: “Navigating to current location (“/reservation/create”) is not allowed”, stack: “Error↵ at new NavigationDuplicated (webpack-int…node_modules/vue/dist/vue.runtime.esm.js:1853:26)”}</em></blockquote><h3><strong>‌原因</strong></h3><p>‌vue-router 3.1後 push 和 replace方法返回 promise, promise 被 reject 但是沒有 catch，導致報錯 Uncaught. 3.1版本之前是通過傳回調函數捕獲錯誤, 沒有回調就不會捕獲也不會報錯</p><p>‌官方issue: <a href="https://github.com/vuejs/vue-router/issues/2881#issuecomment-520554378">https://github.com/vuejs/vue-router/issues/2881#issuecomment-520554378</a></p><h3>‌解法</h3><h4><strong>方法1.使用 go(0)</strong></h4><p>router.go(n) 這個方法的參數是一個整數, 意思是在 history 記錄中向前或者後退多少步, 類似 window.history.go(n)。</p><pre>this.$router.go(0);</pre><p>這做法有個問題, 他會重新整理頁面, 所以會導致 vuex 裡面存的資料被刷掉.</p><h4><strong>方法2.先跳到某頁, 再跳回來</strong></h4><p>‌新增一個vue檔案, Refresh.vue</p><p>用來跳回原本路徑.‌</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2832e005dd349306d33eb06512a57c61/href">https://medium.com/media/2832e005dd349306d33eb06512a57c61/href</a></iframe><p>在 vue router 補上剛剛建立的Refresh.vue‌</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1cb3d175fe79952c798aa0d5938f816d/href">https://medium.com/media/1cb3d175fe79952c798aa0d5938f816d/href</a></iframe><p>導頁時補上, 當 catch 到 err 時, 就會跑到 Refresh, 再導回來.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9e8936cb378c8eaa9d9d51b675aa7d33/href">https://medium.com/media/9e8936cb378c8eaa9d9d51b675aa7d33/href</a></iframe><h3>參考</h3><ul><li><a href="https://forum.vuejs.org/t/navigationduplicated/71600/2">https://forum.vuejs.org/t/navigationduplicated/71600/2</a></li><li><a href="https://router.vuejs.org/guide/essentials/navigation.html#router-go-n">https://router.vuejs.org/guide/essentials/navigation.html#router-go-n</a></li><li><a href="https://github.com/vuejs/vue-router/issues/2881#issuecomment-520554378">https://github.com/vuejs/vue-router/issues/2881#issuecomment-520554378</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=be5195f5dd7e" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>