<?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:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Danish Joshi]]></title><description><![CDATA[My encounters with 0s 1s and beyond]]></description><link>https://blog.danishjoshi.com</link><image><url>https://substackcdn.com/image/fetch/$s_!2cAq!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7e1fe32-995e-43d3-a1a8-3cf0e738c614_469x469.png</url><title>Danish Joshi</title><link>https://blog.danishjoshi.com</link></image><generator>Substack</generator><lastBuildDate>Mon, 06 Apr 2026 13:53:14 GMT</lastBuildDate><atom:link href="https://blog.danishjoshi.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[su1199]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[danishjoshi@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[danishjoshi@substack.com]]></itunes:email><itunes:name><![CDATA[su1199]]></itunes:name></itunes:owner><itunes:author><![CDATA[su1199]]></itunes:author><googleplay:owner><![CDATA[danishjoshi@substack.com]]></googleplay:owner><googleplay:email><![CDATA[danishjoshi@substack.com]]></googleplay:email><googleplay:author><![CDATA[su1199]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Modding electron apps on macOS.]]></title><description><![CDATA[Also reverse engineering to bypass the licence activation logic (for fun..)]]></description><link>https://blog.danishjoshi.com/p/modding-electron-apps-on-macos</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/modding-electron-apps-on-macos</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Fri, 20 Sep 2024 19:29:44 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/95b8a9c9-9f4f-44d9-a6a6-e8a8c5f85890_568x439.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Step 1. Prepare the environment : </p><ol><li><p>Extract the .app from dmg file to your project&#8217;s folder.</p></li><li><p>Right click the .app file and click show package contents.</p></li><li><p>There you&#8217;ll find a couple of files and folders. Copy the &#8216;Resources&#8216; folder to the parent project directory</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ge3s!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a71d83-b645-4efb-a26c-d7721e9e2e4d_1102x460.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ge3s!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a71d83-b645-4efb-a26c-d7721e9e2e4d_1102x460.png 424w, https://substackcdn.com/image/fetch/$s_!Ge3s!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a71d83-b645-4efb-a26c-d7721e9e2e4d_1102x460.png 848w, https://substackcdn.com/image/fetch/$s_!Ge3s!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a71d83-b645-4efb-a26c-d7721e9e2e4d_1102x460.png 1272w, https://substackcdn.com/image/fetch/$s_!Ge3s!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a71d83-b645-4efb-a26c-d7721e9e2e4d_1102x460.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ge3s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a71d83-b645-4efb-a26c-d7721e9e2e4d_1102x460.png" width="374" height="156.11615245009074" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9a71d83-b645-4efb-a26c-d7721e9e2e4d_1102x460.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:460,&quot;width&quot;:1102,&quot;resizeWidth&quot;:374,&quot;bytes&quot;:109978,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ge3s!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a71d83-b645-4efb-a26c-d7721e9e2e4d_1102x460.png 424w, https://substackcdn.com/image/fetch/$s_!Ge3s!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a71d83-b645-4efb-a26c-d7721e9e2e4d_1102x460.png 848w, https://substackcdn.com/image/fetch/$s_!Ge3s!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a71d83-b645-4efb-a26c-d7721e9e2e4d_1102x460.png 1272w, https://substackcdn.com/image/fetch/$s_!Ge3s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a71d83-b645-4efb-a26c-d7721e9e2e4d_1102x460.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div></li><li><p>We are gonna need the following tools : </p><ol><li><p><a href="https://github.com/electron/asar">asar</a> CLI : its basically a packaging program for electron apps which can be also be used for unpacking apps</p></li><li><p><a href="https://github.com/j4k0xb/webcrack">webcrack</a> CLI : Really Good JS deobfuscator. Works well on common obfuscation techniques. I&#8217;ll show what they are later.</p></li><li><p>A faster text editor : Obfuscated and packaged js code is reeeally ugly and the LOC can extend upto 100k+ per file. So no, your electron based editor (cough.. vs code) won&#8217;t cut it. You need something performant to perform static analysis without ripping your hair out.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Nr-m!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F769f58e1-1341-4e8b-8a57-1bc5757c12d7_700x278.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Nr-m!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F769f58e1-1341-4e8b-8a57-1bc5757c12d7_700x278.png 424w, https://substackcdn.com/image/fetch/$s_!Nr-m!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F769f58e1-1341-4e8b-8a57-1bc5757c12d7_700x278.png 848w, https://substackcdn.com/image/fetch/$s_!Nr-m!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F769f58e1-1341-4e8b-8a57-1bc5757c12d7_700x278.png 1272w, https://substackcdn.com/image/fetch/$s_!Nr-m!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F769f58e1-1341-4e8b-8a57-1bc5757c12d7_700x278.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Nr-m!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F769f58e1-1341-4e8b-8a57-1bc5757c12d7_700x278.png" width="390" height="154.88571428571427" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/769f58e1-1341-4e8b-8a57-1bc5757c12d7_700x278.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:278,&quot;width&quot;:700,&quot;resizeWidth&quot;:390,&quot;bytes&quot;:30762,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Nr-m!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F769f58e1-1341-4e8b-8a57-1bc5757c12d7_700x278.png 424w, https://substackcdn.com/image/fetch/$s_!Nr-m!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F769f58e1-1341-4e8b-8a57-1bc5757c12d7_700x278.png 848w, https://substackcdn.com/image/fetch/$s_!Nr-m!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F769f58e1-1341-4e8b-8a57-1bc5757c12d7_700x278.png 1272w, https://substackcdn.com/image/fetch/$s_!Nr-m!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F769f58e1-1341-4e8b-8a57-1bc5757c12d7_700x278.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>I recommend using vim or any other cli based IDE. You can also try  <a href="https://zed.dev">ZED</a> if you are used to the UI. It&#8217;s written in RUST and is really performant.</p></li></ol></li></ol><div><hr></div><p>Step 2. Unpack the asar file : Use the asar CLI to unpack the asar file: Make sure the supporting directories (eg. app.asar.unpacked) and modules are present in the folder where app.asar is present. </p><blockquote><p>npx asar extract resources/app.asar extracted-app/</p></blockquote><p>This will extract out all the app data to a separate folder for static analysis.</p><div><hr></div><p>Step 3. Find and deobfuscate all the {{required}} js files in the dist directories &#8230;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zaS6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca96fcf7-a7c9-45a6-9b83-39ec23a8d2af_720x490.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zaS6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca96fcf7-a7c9-45a6-9b83-39ec23a8d2af_720x490.png 424w, https://substackcdn.com/image/fetch/$s_!zaS6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca96fcf7-a7c9-45a6-9b83-39ec23a8d2af_720x490.png 848w, https://substackcdn.com/image/fetch/$s_!zaS6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca96fcf7-a7c9-45a6-9b83-39ec23a8d2af_720x490.png 1272w, https://substackcdn.com/image/fetch/$s_!zaS6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca96fcf7-a7c9-45a6-9b83-39ec23a8d2af_720x490.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zaS6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca96fcf7-a7c9-45a6-9b83-39ec23a8d2af_720x490.png" width="356" height="242.27777777777777" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca96fcf7-a7c9-45a6-9b83-39ec23a8d2af_720x490.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:490,&quot;width&quot;:720,&quot;resizeWidth&quot;:356,&quot;bytes&quot;:37175,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!zaS6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca96fcf7-a7c9-45a6-9b83-39ec23a8d2af_720x490.png 424w, https://substackcdn.com/image/fetch/$s_!zaS6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca96fcf7-a7c9-45a6-9b83-39ec23a8d2af_720x490.png 848w, https://substackcdn.com/image/fetch/$s_!zaS6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca96fcf7-a7c9-45a6-9b83-39ec23a8d2af_720x490.png 1272w, https://substackcdn.com/image/fetch/$s_!zaS6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fca96fcf7-a7c9-45a6-9b83-39ec23a8d2af_720x490.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Obfuscated js looks like this :</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qQrS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7834a781-179d-479e-9326-9ece5b778144_1780x774.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qQrS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7834a781-179d-479e-9326-9ece5b778144_1780x774.png 424w, https://substackcdn.com/image/fetch/$s_!qQrS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7834a781-179d-479e-9326-9ece5b778144_1780x774.png 848w, https://substackcdn.com/image/fetch/$s_!qQrS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7834a781-179d-479e-9326-9ece5b778144_1780x774.png 1272w, https://substackcdn.com/image/fetch/$s_!qQrS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7834a781-179d-479e-9326-9ece5b778144_1780x774.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qQrS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7834a781-179d-479e-9326-9ece5b778144_1780x774.png" width="594" height="258.24313186813185" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7834a781-179d-479e-9326-9ece5b778144_1780x774.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:633,&quot;width&quot;:1456,&quot;resizeWidth&quot;:594,&quot;bytes&quot;:512801,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qQrS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7834a781-179d-479e-9326-9ece5b778144_1780x774.png 424w, https://substackcdn.com/image/fetch/$s_!qQrS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7834a781-179d-479e-9326-9ece5b778144_1780x774.png 848w, https://substackcdn.com/image/fetch/$s_!qQrS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7834a781-179d-479e-9326-9ece5b778144_1780x774.png 1272w, https://substackcdn.com/image/fetch/$s_!qQrS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7834a781-179d-479e-9326-9ece5b778144_1780x774.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And this is the result after deobfuscation : </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Bu4y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc38880f-41fa-4482-ac61-b691d29fd838_1326x796.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bu4y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc38880f-41fa-4482-ac61-b691d29fd838_1326x796.png 424w, https://substackcdn.com/image/fetch/$s_!Bu4y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc38880f-41fa-4482-ac61-b691d29fd838_1326x796.png 848w, https://substackcdn.com/image/fetch/$s_!Bu4y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc38880f-41fa-4482-ac61-b691d29fd838_1326x796.png 1272w, https://substackcdn.com/image/fetch/$s_!Bu4y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc38880f-41fa-4482-ac61-b691d29fd838_1326x796.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bu4y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc38880f-41fa-4482-ac61-b691d29fd838_1326x796.png" width="544" height="326.56410256410254" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cc38880f-41fa-4482-ac61-b691d29fd838_1326x796.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:796,&quot;width&quot;:1326,&quot;resizeWidth&quot;:544,&quot;bytes&quot;:159473,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Bu4y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc38880f-41fa-4482-ac61-b691d29fd838_1326x796.png 424w, https://substackcdn.com/image/fetch/$s_!Bu4y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc38880f-41fa-4482-ac61-b691d29fd838_1326x796.png 848w, https://substackcdn.com/image/fetch/$s_!Bu4y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc38880f-41fa-4482-ac61-b691d29fd838_1326x796.png 1272w, https://substackcdn.com/image/fetch/$s_!Bu4y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc38880f-41fa-4482-ac61-b691d29fd838_1326x796.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Makes the code much more readable..</p><p>Obfuscation is a facinating topic overall. You can read more about it <a href="https://www.trickster.dev/post/javascript-obfuscation-techniques-by-example/">here</a>.</p><div><hr></div><p>Step 4. Static Analysis: Find the code that is responsible for your desired functionality.</p><p>I will take an example of bypassing licence activation.</p><p><strong>Note</strong>: I already own the app I am demonstrating this for. I don&#8217;t condone piracy. Just fkin pay for good software.</p><p>This is the license activation screen.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VF4g!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8f9972a-dfcd-405e-982b-4bec5c2939da_1048x804.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VF4g!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8f9972a-dfcd-405e-982b-4bec5c2939da_1048x804.png 424w, https://substackcdn.com/image/fetch/$s_!VF4g!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8f9972a-dfcd-405e-982b-4bec5c2939da_1048x804.png 848w, https://substackcdn.com/image/fetch/$s_!VF4g!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8f9972a-dfcd-405e-982b-4bec5c2939da_1048x804.png 1272w, https://substackcdn.com/image/fetch/$s_!VF4g!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8f9972a-dfcd-405e-982b-4bec5c2939da_1048x804.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VF4g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8f9972a-dfcd-405e-982b-4bec5c2939da_1048x804.png" width="382" height="293.0610687022901" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c8f9972a-dfcd-405e-982b-4bec5c2939da_1048x804.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:804,&quot;width&quot;:1048,&quot;resizeWidth&quot;:382,&quot;bytes&quot;:53938,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VF4g!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8f9972a-dfcd-405e-982b-4bec5c2939da_1048x804.png 424w, https://substackcdn.com/image/fetch/$s_!VF4g!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8f9972a-dfcd-405e-982b-4bec5c2939da_1048x804.png 848w, https://substackcdn.com/image/fetch/$s_!VF4g!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8f9972a-dfcd-405e-982b-4bec5c2939da_1048x804.png 1272w, https://substackcdn.com/image/fetch/$s_!VF4g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8f9972a-dfcd-405e-982b-4bec5c2939da_1048x804.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>Use search to find the exact phrase in the codebase..</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!B_1X!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60220c4c-b93a-4ea2-802d-93e346bf2ad1_1264x656.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!B_1X!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60220c4c-b93a-4ea2-802d-93e346bf2ad1_1264x656.png 424w, https://substackcdn.com/image/fetch/$s_!B_1X!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60220c4c-b93a-4ea2-802d-93e346bf2ad1_1264x656.png 848w, https://substackcdn.com/image/fetch/$s_!B_1X!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60220c4c-b93a-4ea2-802d-93e346bf2ad1_1264x656.png 1272w, https://substackcdn.com/image/fetch/$s_!B_1X!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60220c4c-b93a-4ea2-802d-93e346bf2ad1_1264x656.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!B_1X!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60220c4c-b93a-4ea2-802d-93e346bf2ad1_1264x656.png" width="450" height="233.54430379746836" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/60220c4c-b93a-4ea2-802d-93e346bf2ad1_1264x656.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:656,&quot;width&quot;:1264,&quot;resizeWidth&quot;:450,&quot;bytes&quot;:161451,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!B_1X!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60220c4c-b93a-4ea2-802d-93e346bf2ad1_1264x656.png 424w, https://substackcdn.com/image/fetch/$s_!B_1X!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60220c4c-b93a-4ea2-802d-93e346bf2ad1_1264x656.png 848w, https://substackcdn.com/image/fetch/$s_!B_1X!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60220c4c-b93a-4ea2-802d-93e346bf2ad1_1264x656.png 1272w, https://substackcdn.com/image/fetch/$s_!B_1X!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60220c4c-b93a-4ea2-802d-93e346bf2ad1_1264x656.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Use this to find out what function is getting called when you press the activate button. then back-track to find out the function where network call is being made. That is made typically to a licensing server.</p><p>Other ways to find out the code responsible for activation is :</p><ul><li><p>Network monitor. Start the electron app connect to postman&#8217;s proxy and intercept all the request: this may or may not work because the developers may not use simple protocalls to make requests.</p></li><li><p>Dev console. Use electron&#8217;s inbuilt dev-console to find out the request. This may also not work deu to the same reason above.</p></li><li><p>Wireshark/Burpsuite. Can work, have&#8217;t tried yet.. Wireshark support a large variety of protocols so you may find out server endpoint using it.</p></li><li><p>Search for https:// in the codebase. This is tricky and time consuming.</p></li></ul><p>After you&#8217;ve found out what part of code is responsible for making the request. Modify it so that it always returns a success. Also check all the downstream functions of that piece of code to bypass all of those checks too..</p><p>In my case I found out this part of code :<br></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2mSf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95396e61-762a-4d9a-b57a-bc126e316386_1734x1236.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2mSf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95396e61-762a-4d9a-b57a-bc126e316386_1734x1236.png 424w, https://substackcdn.com/image/fetch/$s_!2mSf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95396e61-762a-4d9a-b57a-bc126e316386_1734x1236.png 848w, https://substackcdn.com/image/fetch/$s_!2mSf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95396e61-762a-4d9a-b57a-bc126e316386_1734x1236.png 1272w, https://substackcdn.com/image/fetch/$s_!2mSf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95396e61-762a-4d9a-b57a-bc126e316386_1734x1236.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2mSf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95396e61-762a-4d9a-b57a-bc126e316386_1734x1236.png" width="572" height="407.7857142857143" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/95396e61-762a-4d9a-b57a-bc126e316386_1734x1236.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1038,&quot;width&quot;:1456,&quot;resizeWidth&quot;:572,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2mSf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95396e61-762a-4d9a-b57a-bc126e316386_1734x1236.png 424w, https://substackcdn.com/image/fetch/$s_!2mSf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95396e61-762a-4d9a-b57a-bc126e316386_1734x1236.png 848w, https://substackcdn.com/image/fetch/$s_!2mSf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95396e61-762a-4d9a-b57a-bc126e316386_1734x1236.png 1272w, https://substackcdn.com/image/fetch/$s_!2mSf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F95396e61-762a-4d9a-b57a-bc126e316386_1734x1236.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><code> It can simply be replaced by this to bypass all checks:</code></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iJkQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cea514a-cd9d-4c23-b18d-3fef8d866ac9_822x480.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iJkQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cea514a-cd9d-4c23-b18d-3fef8d866ac9_822x480.png 424w, https://substackcdn.com/image/fetch/$s_!iJkQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cea514a-cd9d-4c23-b18d-3fef8d866ac9_822x480.png 848w, https://substackcdn.com/image/fetch/$s_!iJkQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cea514a-cd9d-4c23-b18d-3fef8d866ac9_822x480.png 1272w, https://substackcdn.com/image/fetch/$s_!iJkQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cea514a-cd9d-4c23-b18d-3fef8d866ac9_822x480.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iJkQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cea514a-cd9d-4c23-b18d-3fef8d866ac9_822x480.png" width="420" height="245.25547445255475" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2cea514a-cd9d-4c23-b18d-3fef8d866ac9_822x480.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:480,&quot;width&quot;:822,&quot;resizeWidth&quot;:420,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iJkQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cea514a-cd9d-4c23-b18d-3fef8d866ac9_822x480.png 424w, https://substackcdn.com/image/fetch/$s_!iJkQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cea514a-cd9d-4c23-b18d-3fef8d866ac9_822x480.png 848w, https://substackcdn.com/image/fetch/$s_!iJkQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cea514a-cd9d-4c23-b18d-3fef8d866ac9_822x480.png 1272w, https://substackcdn.com/image/fetch/$s_!iJkQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2cea514a-cd9d-4c23-b18d-3fef8d866ac9_822x480.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Another part was the the function which persists the licence key across sessions :</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KbmH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb57113b9-63b5-48e4-9555-ab0a1d92f4b2_1598x1380.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KbmH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb57113b9-63b5-48e4-9555-ab0a1d92f4b2_1598x1380.png 424w, https://substackcdn.com/image/fetch/$s_!KbmH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb57113b9-63b5-48e4-9555-ab0a1d92f4b2_1598x1380.png 848w, https://substackcdn.com/image/fetch/$s_!KbmH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb57113b9-63b5-48e4-9555-ab0a1d92f4b2_1598x1380.png 1272w, https://substackcdn.com/image/fetch/$s_!KbmH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb57113b9-63b5-48e4-9555-ab0a1d92f4b2_1598x1380.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KbmH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb57113b9-63b5-48e4-9555-ab0a1d92f4b2_1598x1380.png" width="568" height="490.36813186813185" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b57113b9-63b5-48e4-9555-ab0a1d92f4b2_1598x1380.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1257,&quot;width&quot;:1456,&quot;resizeWidth&quot;:568,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!KbmH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb57113b9-63b5-48e4-9555-ab0a1d92f4b2_1598x1380.png 424w, https://substackcdn.com/image/fetch/$s_!KbmH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb57113b9-63b5-48e4-9555-ab0a1d92f4b2_1598x1380.png 848w, https://substackcdn.com/image/fetch/$s_!KbmH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb57113b9-63b5-48e4-9555-ab0a1d92f4b2_1598x1380.png 1272w, https://substackcdn.com/image/fetch/$s_!KbmH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb57113b9-63b5-48e4-9555-ab0a1d92f4b2_1598x1380.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This can also be simple bypassed: </p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GzGP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e67c195-e68b-418d-9da6-d1485356f330_1430x516.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GzGP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e67c195-e68b-418d-9da6-d1485356f330_1430x516.png 424w, https://substackcdn.com/image/fetch/$s_!GzGP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e67c195-e68b-418d-9da6-d1485356f330_1430x516.png 848w, https://substackcdn.com/image/fetch/$s_!GzGP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e67c195-e68b-418d-9da6-d1485356f330_1430x516.png 1272w, https://substackcdn.com/image/fetch/$s_!GzGP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e67c195-e68b-418d-9da6-d1485356f330_1430x516.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GzGP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e67c195-e68b-418d-9da6-d1485356f330_1430x516.png" width="642" height="231.65874125874126" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9e67c195-e68b-418d-9da6-d1485356f330_1430x516.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:516,&quot;width&quot;:1430,&quot;resizeWidth&quot;:642,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GzGP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e67c195-e68b-418d-9da6-d1485356f330_1430x516.png 424w, https://substackcdn.com/image/fetch/$s_!GzGP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e67c195-e68b-418d-9da6-d1485356f330_1430x516.png 848w, https://substackcdn.com/image/fetch/$s_!GzGP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e67c195-e68b-418d-9da6-d1485356f330_1430x516.png 1272w, https://substackcdn.com/image/fetch/$s_!GzGP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e67c195-e68b-418d-9da6-d1485356f330_1430x516.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Similarly you can find out all the places licence key is being fetched/stored/verified and mod out the functions.</p><div><hr></div><p>Step 5. Repackaging and assembling a new .app file.</p><p>Now after you&#8217;ve made all the changes. Repackage the app to an asar file using the asar cli again.</p><blockquote><p>npx asar pack extracted-app/ app.asar</p></blockquote><p>Now go to the original .app of your application, right click &gt; show package contents &gt; delete the original app.asar from the Resources folder and copy the modified newly packaged app.asar into it.</p><p>Reopen the app and see if your mods had any effect.</p><p>Note: Open the app without mods first just for macOS to pass package verification. Subsequent modifications will pass through just fine.</p><div><hr></div><p>Reverse engineering apps, especially obfuscated ones is really fun. It&#8217;s like solving an interesting math problem. <br>Will post more about the interesting/challenging techniques I encounter while reverse-engineering random apps in the future.</p><p>Adios till then &#128588;</p>]]></content:encoded></item><item><title><![CDATA[Reverse engineering a Smart Electricity Meter App.]]></title><description><![CDATA[and using apple shortcuts to geo-automate supply.]]></description><link>https://blog.danishjoshi.com/p/reverse-engineering-a-smart-electricity</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/reverse-engineering-a-smart-electricity</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Thu, 25 Jul 2024 09:30:45 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!vmJJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So my apartment has a prepaid meter system for electricity distribution where we can load up some money and the meter deducts the day&#8217;s electricity cost at EOD and updates the balance in app.</p><p>The app also has a feature to turn of the electricity supply. Which is&#8230; interesting. I really wanted to reverse engineer and pentest the app for vulns. So one fine weekend I decided to do just that. </p><p>Found some major-major privacy gaps (not validating the bearer when fetching my neighbour&#8217;s meter details ::skull_emoji::) which can be another blogpost in itself once they patch it.</p><p>For now we&#8217;ll be focussing on the turning off the supply part. </p><p>I used burpsute, frida and bluestacks to intercept the API requests as I demonstrated in detail in a <a href="https://danishjoshi.substack.com/p/reverse-engineering-truecaller-mobile-app-and-making-a-bot-out-of-the-exposed-apis">previous blog post.</a></p><p>But the major steps remain the same :</p><ol><li><p>Setup burpsuite proxy.</p></li><li><p>Connect to the burp proxy using any vpn app.</p></li><li><p>Use xposed to install FRIDA framework onto device. </p></li><li><p>Install the burp certificate.</p></li><li><p>Install the target app and turn on intercept to see the intercepted requests.</p></li></ol><p>This gave me the API endpoints that are called when the user hits the &#8220;turn meter off&#8221; button.</p><p>Now my idea was to use apple shortcuts app to simulate this request but it does&#8217;t allow me to put body data or auth tokens with the request. It just has a feature to call a URL with some parameter inside of it. </p><p>So to simulate this request I created a serverless function on deno deploy(tested out with cloudflare workers but it mysteriously refused to work on cloudflare).</p><p>After making two endpoints for the ON and OFF functionality, I created a new http shortcut on the iOS shortcuts app to trigger one of the endpoints whenever I leave or enter my apartment based on my geo location.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vmJJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vmJJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png 424w, https://substackcdn.com/image/fetch/$s_!vmJJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png 848w, https://substackcdn.com/image/fetch/$s_!vmJJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png 1272w, https://substackcdn.com/image/fetch/$s_!vmJJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vmJJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png" width="422" height="168.14573643410853" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:514,&quot;width&quot;:1290,&quot;resizeWidth&quot;:422,&quot;bytes&quot;:93281,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vmJJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png 424w, https://substackcdn.com/image/fetch/$s_!vmJJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png 848w, https://substackcdn.com/image/fetch/$s_!vmJJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png 1272w, https://substackcdn.com/image/fetch/$s_!vmJJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11b03931-a188-4ff2-99a4-4e4fc60cf012_1290x514.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>It works like a charm 80% of the time minus some random GPS fuckups and misfires. There seems to be some cool-down of about 5 minutes between on and off states to prevent abuse.</p><p></p>]]></content:encoded></item><item><title><![CDATA[Building RakuMend, a Conversational Recommendation Engine.]]></title><description><![CDATA[Post-hackathon writeup. RAG & Making instruct-tuned LLMs behave on super-long context lengths.]]></description><link>https://blog.danishjoshi.com/p/building-rakumend-a-conversational</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/building-rakumend-a-conversational</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Thu, 04 Jan 2024 22:19:48 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!W-bE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So I won(Second, $3.6K) a hackathon a couple of months back in September. It was organised by the Rakuten India and had generative AI as its theme. Finally got time to do a technical writeup.</p><p>Note: The LLM landscape has changed quite a lot since September, when I built this, so all the discussion in this post might not be completely relevant.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!W-bE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!W-bE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png 424w, https://substackcdn.com/image/fetch/$s_!W-bE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png 848w, https://substackcdn.com/image/fetch/$s_!W-bE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png 1272w, https://substackcdn.com/image/fetch/$s_!W-bE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!W-bE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png" width="498" height="138.1813186813187" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:404,&quot;width&quot;:1456,&quot;resizeWidth&quot;:498,&quot;bytes&quot;:121120,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!W-bE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png 424w, https://substackcdn.com/image/fetch/$s_!W-bE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png 848w, https://substackcdn.com/image/fetch/$s_!W-bE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png 1272w, https://substackcdn.com/image/fetch/$s_!W-bE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F953312ee-a437-43e6-bc79-3f9fc410f591_1514x420.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><figcaption class="image-caption">cheeky logo I designed :p</figcaption></figure></div><p>One of the two products I built was RakuMend, a conversational shopping and recommendation engine powered by GPT3.5 and Google&#8217;s vertex AI for image captioning needs (GPT4 Vision wasn&#8217;t a thing at that time).</p><p>Rakuten has a global website, rakuten.com, which is basically a brand aggregator, and they get a cut every time a purchase is made through it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pZsc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F002eea9e-d895-4dfc-b5a6-0e92d30d8dca_3334x1720.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pZsc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F002eea9e-d895-4dfc-b5a6-0e92d30d8dca_3334x1720.png 424w, https://substackcdn.com/image/fetch/$s_!pZsc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F002eea9e-d895-4dfc-b5a6-0e92d30d8dca_3334x1720.png 848w, https://substackcdn.com/image/fetch/$s_!pZsc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F002eea9e-d895-4dfc-b5a6-0e92d30d8dca_3334x1720.png 1272w, https://substackcdn.com/image/fetch/$s_!pZsc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F002eea9e-d895-4dfc-b5a6-0e92d30d8dca_3334x1720.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pZsc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F002eea9e-d895-4dfc-b5a6-0e92d30d8dca_3334x1720.png" width="1456" height="751" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/002eea9e-d895-4dfc-b5a6-0e92d30d8dca_3334x1720.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:751,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1987300,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pZsc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F002eea9e-d895-4dfc-b5a6-0e92d30d8dca_3334x1720.png 424w, https://substackcdn.com/image/fetch/$s_!pZsc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F002eea9e-d895-4dfc-b5a6-0e92d30d8dca_3334x1720.png 848w, https://substackcdn.com/image/fetch/$s_!pZsc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F002eea9e-d895-4dfc-b5a6-0e92d30d8dca_3334x1720.png 1272w, https://substackcdn.com/image/fetch/$s_!pZsc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F002eea9e-d895-4dfc-b5a6-0e92d30d8dca_3334x1720.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I wanted to build a recommendation system around it, so it takes a natural language query (e.g., I am going to a work trip this weekend; suggest something comfy yet semi-formal) and gives out product recommendations from the inventory.</p><h3>V1: ViT/CLIP + Cosine Similarity/Vector Search</h3><p>The first version was powered by a simple vector search engine in which I scraped approximately 10,000 products from Rakuten Ichiba (their Japanese counterpart). Divided into two product categories, tops and bottoms. I used Clip (OpenAI&#8217;s image captioning model) to get image vectors and did a cosine similarity search to find matching outfits from the DB. I used pinecone for my vector DB, but really, a numpy dict would have worked just fine.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xWn0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbadae7a-61a4-4927-b062-f1a28fdc8d30_1920x1040.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xWn0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbadae7a-61a4-4927-b062-f1a28fdc8d30_1920x1040.png 424w, https://substackcdn.com/image/fetch/$s_!xWn0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbadae7a-61a4-4927-b062-f1a28fdc8d30_1920x1040.png 848w, https://substackcdn.com/image/fetch/$s_!xWn0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbadae7a-61a4-4927-b062-f1a28fdc8d30_1920x1040.png 1272w, https://substackcdn.com/image/fetch/$s_!xWn0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbadae7a-61a4-4927-b062-f1a28fdc8d30_1920x1040.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xWn0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbadae7a-61a4-4927-b062-f1a28fdc8d30_1920x1040.png" width="1456" height="789" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bbadae7a-61a4-4927-b062-f1a28fdc8d30_1920x1040.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:789,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:4054197,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!xWn0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbadae7a-61a4-4927-b062-f1a28fdc8d30_1920x1040.png 424w, https://substackcdn.com/image/fetch/$s_!xWn0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbadae7a-61a4-4927-b062-f1a28fdc8d30_1920x1040.png 848w, https://substackcdn.com/image/fetch/$s_!xWn0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbadae7a-61a4-4927-b062-f1a28fdc8d30_1920x1040.png 1272w, https://substackcdn.com/image/fetch/$s_!xWn0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbbadae7a-61a4-4927-b062-f1a28fdc8d30_1920x1040.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;c8c66fbf-51fc-4318-a375-2fe9f0da6356&quot;,&quot;duration&quot;:null}"></div><p>It worked &#171;fine&#187;. It was too slow to be used on any production workload with 100s of categories. Also the recommendations weren&#8217;t that great tbh.</p><p>So onto the next version.</p><h3>V2: GPT Functions and Full Text Search</h3><p>Not having access to the whole product catalog was a bummer. But Rakuten&#8217;s full text search is really good.</p><p>So my idea was to leverage FTS with GPT function calling to get product ideas from GPT, generate search queries from it, scrape the top 5 results, and display them.</p><p>This was around the time when GPT unveiled function calling and models specifically tuned for that (instruction tuned).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oMB4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55ab127f-7a86-4979-9718-9813739c7228_3360x1222.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oMB4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55ab127f-7a86-4979-9718-9813739c7228_3360x1222.png 424w, https://substackcdn.com/image/fetch/$s_!oMB4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55ab127f-7a86-4979-9718-9813739c7228_3360x1222.png 848w, https://substackcdn.com/image/fetch/$s_!oMB4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55ab127f-7a86-4979-9718-9813739c7228_3360x1222.png 1272w, https://substackcdn.com/image/fetch/$s_!oMB4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55ab127f-7a86-4979-9718-9813739c7228_3360x1222.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oMB4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55ab127f-7a86-4979-9718-9813739c7228_3360x1222.png" width="1456" height="530" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/55ab127f-7a86-4979-9718-9813739c7228_3360x1222.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:530,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1252235,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!oMB4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55ab127f-7a86-4979-9718-9813739c7228_3360x1222.png 424w, https://substackcdn.com/image/fetch/$s_!oMB4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55ab127f-7a86-4979-9718-9813739c7228_3360x1222.png 848w, https://substackcdn.com/image/fetch/$s_!oMB4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55ab127f-7a86-4979-9718-9813739c7228_3360x1222.png 1272w, https://substackcdn.com/image/fetch/$s_!oMB4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55ab127f-7a86-4979-9718-9813739c7228_3360x1222.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>A Note about GPT Function Calling:</strong>&nbsp;Its not intuitive at all and is quite unreliable. I don&#8217;t know anyone using function calling in production. I recommend writing your own parser (do a simple regex on return streamed responses and manually call the function in Python).</p><p>This is almost like retrieval-augmented generation (except we use full text search instead of vector similarity to find the top k results):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xavP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c497389-fee1-42a2-90bd-4eff2ad63c42_3452x2046.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xavP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c497389-fee1-42a2-90bd-4eff2ad63c42_3452x2046.png 424w, https://substackcdn.com/image/fetch/$s_!xavP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c497389-fee1-42a2-90bd-4eff2ad63c42_3452x2046.png 848w, https://substackcdn.com/image/fetch/$s_!xavP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c497389-fee1-42a2-90bd-4eff2ad63c42_3452x2046.png 1272w, https://substackcdn.com/image/fetch/$s_!xavP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c497389-fee1-42a2-90bd-4eff2ad63c42_3452x2046.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xavP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c497389-fee1-42a2-90bd-4eff2ad63c42_3452x2046.png" width="1456" height="863" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2c497389-fee1-42a2-90bd-4eff2ad63c42_3452x2046.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:863,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1510983,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xavP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c497389-fee1-42a2-90bd-4eff2ad63c42_3452x2046.png 424w, https://substackcdn.com/image/fetch/$s_!xavP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c497389-fee1-42a2-90bd-4eff2ad63c42_3452x2046.png 848w, https://substackcdn.com/image/fetch/$s_!xavP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c497389-fee1-42a2-90bd-4eff2ad63c42_3452x2046.png 1272w, https://substackcdn.com/image/fetch/$s_!xavP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2c497389-fee1-42a2-90bd-4eff2ad63c42_3452x2046.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4>This is the final product I demoed at the hack.</h4><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;602e05e2-fdfd-4910-89b9-5d426bb3e68d&quot;,&quot;duration&quot;:null}"></div><h4><strong>How it works and the code:</strong></h4><blockquote><p>This is the scraping module that searches and returns the top n products for the given query from Rakuten&#8217;s website :</p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!f_i3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4948f469-aa92-4430-8802-e0fad482221d_2048x1848.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!f_i3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4948f469-aa92-4430-8802-e0fad482221d_2048x1848.png 424w, https://substackcdn.com/image/fetch/$s_!f_i3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4948f469-aa92-4430-8802-e0fad482221d_2048x1848.png 848w, https://substackcdn.com/image/fetch/$s_!f_i3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4948f469-aa92-4430-8802-e0fad482221d_2048x1848.png 1272w, https://substackcdn.com/image/fetch/$s_!f_i3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4948f469-aa92-4430-8802-e0fad482221d_2048x1848.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!f_i3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4948f469-aa92-4430-8802-e0fad482221d_2048x1848.png" width="1456" height="1314" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4948f469-aa92-4430-8802-e0fad482221d_2048x1848.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1314,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:412457,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!f_i3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4948f469-aa92-4430-8802-e0fad482221d_2048x1848.png 424w, https://substackcdn.com/image/fetch/$s_!f_i3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4948f469-aa92-4430-8802-e0fad482221d_2048x1848.png 848w, https://substackcdn.com/image/fetch/$s_!f_i3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4948f469-aa92-4430-8802-e0fad482221d_2048x1848.png 1272w, https://substackcdn.com/image/fetch/$s_!f_i3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4948f469-aa92-4430-8802-e0fad482221d_2048x1848.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><blockquote><p>This is the fastAPI endpoint that handles all the messages as well as user&#8217;s input images :</p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!L_bJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3925fab-1b7c-4870-b31a-5e541093223f_2048x2100.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!L_bJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3925fab-1b7c-4870-b31a-5e541093223f_2048x2100.png 424w, https://substackcdn.com/image/fetch/$s_!L_bJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3925fab-1b7c-4870-b31a-5e541093223f_2048x2100.png 848w, https://substackcdn.com/image/fetch/$s_!L_bJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3925fab-1b7c-4870-b31a-5e541093223f_2048x2100.png 1272w, https://substackcdn.com/image/fetch/$s_!L_bJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3925fab-1b7c-4870-b31a-5e541093223f_2048x2100.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!L_bJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3925fab-1b7c-4870-b31a-5e541093223f_2048x2100.png" width="1456" height="1493" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b3925fab-1b7c-4870-b31a-5e541093223f_2048x2100.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1493,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!L_bJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3925fab-1b7c-4870-b31a-5e541093223f_2048x2100.png 424w, https://substackcdn.com/image/fetch/$s_!L_bJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3925fab-1b7c-4870-b31a-5e541093223f_2048x2100.png 848w, https://substackcdn.com/image/fetch/$s_!L_bJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3925fab-1b7c-4870-b31a-5e541093223f_2048x2100.png 1272w, https://substackcdn.com/image/fetch/$s_!L_bJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb3925fab-1b7c-4870-b31a-5e541093223f_2048x2100.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The high_def flag&nbsp;is a flag I implemented when I wanted to get the image captioning results from reverse-engineered Bard&#8217;s web API instead of Vertex&#8217;s PALM API.</p><p>The previous messages are separated by a % delimiter. Each query sends a user preference (age and gender) with it to give our LLM more context about the user.</p><blockquote><p>This is the gpt responder module : It just parses the current user query and previous queries. Also appends system prompt before passing the whole thing to GPT3.5 api. LLM can be hot-swapped.</p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1EEF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1bdaa8b-02a6-4f64-8b60-65f8824cab1e_2048x1164.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1EEF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1bdaa8b-02a6-4f64-8b60-65f8824cab1e_2048x1164.png 424w, https://substackcdn.com/image/fetch/$s_!1EEF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1bdaa8b-02a6-4f64-8b60-65f8824cab1e_2048x1164.png 848w, https://substackcdn.com/image/fetch/$s_!1EEF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1bdaa8b-02a6-4f64-8b60-65f8824cab1e_2048x1164.png 1272w, https://substackcdn.com/image/fetch/$s_!1EEF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1bdaa8b-02a6-4f64-8b60-65f8824cab1e_2048x1164.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1EEF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1bdaa8b-02a6-4f64-8b60-65f8824cab1e_2048x1164.png" width="1456" height="828" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b1bdaa8b-02a6-4f64-8b60-65f8824cab1e_2048x1164.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:828,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1EEF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1bdaa8b-02a6-4f64-8b60-65f8824cab1e_2048x1164.png 424w, https://substackcdn.com/image/fetch/$s_!1EEF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1bdaa8b-02a6-4f64-8b60-65f8824cab1e_2048x1164.png 848w, https://substackcdn.com/image/fetch/$s_!1EEF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1bdaa8b-02a6-4f64-8b60-65f8824cab1e_2048x1164.png 1272w, https://substackcdn.com/image/fetch/$s_!1EEF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb1bdaa8b-02a6-4f64-8b60-65f8824cab1e_2048x1164.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Important Note:</strong> The key to making sure your instruction-tuned models follow instructions in long context lengths is to append the system prompt again at the end of the dialog chain. This has to do with the LLM architecture and how the attention heads function. You might not have to do this at all, depending on the model (e.g., mistral models are pretty good at this). This thing wasted a whole lot of my time figuring it out at the hack.</p><blockquote><p>Parse and replace module: regex(es) the GPT response and returns a structured output after searching for each term using rk_search module. This output is then rendered by my front end.</p></blockquote><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kDwG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce95c284-ce23-4a36-b20d-6eccc274ba54_2048x1524.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kDwG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce95c284-ce23-4a36-b20d-6eccc274ba54_2048x1524.png 424w, https://substackcdn.com/image/fetch/$s_!kDwG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce95c284-ce23-4a36-b20d-6eccc274ba54_2048x1524.png 848w, https://substackcdn.com/image/fetch/$s_!kDwG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce95c284-ce23-4a36-b20d-6eccc274ba54_2048x1524.png 1272w, https://substackcdn.com/image/fetch/$s_!kDwG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce95c284-ce23-4a36-b20d-6eccc274ba54_2048x1524.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kDwG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce95c284-ce23-4a36-b20d-6eccc274ba54_2048x1524.png" width="1456" height="1083" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ce95c284-ce23-4a36-b20d-6eccc274ba54_2048x1524.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1083,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!kDwG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce95c284-ce23-4a36-b20d-6eccc274ba54_2048x1524.png 424w, https://substackcdn.com/image/fetch/$s_!kDwG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce95c284-ce23-4a36-b20d-6eccc274ba54_2048x1524.png 848w, https://substackcdn.com/image/fetch/$s_!kDwG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce95c284-ce23-4a36-b20d-6eccc274ba54_2048x1524.png 1272w, https://substackcdn.com/image/fetch/$s_!kDwG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce95c284-ce23-4a36-b20d-6eccc274ba54_2048x1524.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><blockquote><p>Image captioning : Added a feature that allowed users to add their own outfits and clothing items to chat and ask LLM to give recommendation about it.</p></blockquote><p>Used google&#8217;s palm API (and bard&#8217;s reverse engineered API) to generate highly detailed image captions which were then fed to my LLM. </p><p>Here&#8217;s a demo of the feature :</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;984d563d-141c-4656-84e0-2762f715e2c3&quot;,&quot;duration&quot;:null}"></div><p></p><blockquote><p>Last but not least these were my prompts:</p></blockquote><p><a href="https://text.is/8Y0Y">https://text.is/8Y0Y</a></p><p></p><p>Here&#8217;s another demo vid of the complete project:</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;4c13cfad-ae0c-4d72-a7bc-1f1066a843c9&quot;,&quot;duration&quot;:null}"></div><p></p><p>This thing, coupled with another product I build (RakuTry, a virtual try-on extension [writeup soon]), was enough to get me a second (first being an internal team [usual tbh]).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-hTo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b0e4106-219c-4024-a52f-4d4692417a2f_2822x1736.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-hTo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b0e4106-219c-4024-a52f-4d4692417a2f_2822x1736.png 424w, https://substackcdn.com/image/fetch/$s_!-hTo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b0e4106-219c-4024-a52f-4d4692417a2f_2822x1736.png 848w, https://substackcdn.com/image/fetch/$s_!-hTo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b0e4106-219c-4024-a52f-4d4692417a2f_2822x1736.png 1272w, https://substackcdn.com/image/fetch/$s_!-hTo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b0e4106-219c-4024-a52f-4d4692417a2f_2822x1736.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-hTo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b0e4106-219c-4024-a52f-4d4692417a2f_2822x1736.png" width="1456" height="896" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9b0e4106-219c-4024-a52f-4d4692417a2f_2822x1736.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:896,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:5616178,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-hTo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b0e4106-219c-4024-a52f-4d4692417a2f_2822x1736.png 424w, https://substackcdn.com/image/fetch/$s_!-hTo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b0e4106-219c-4024-a52f-4d4692417a2f_2822x1736.png 848w, https://substackcdn.com/image/fetch/$s_!-hTo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b0e4106-219c-4024-a52f-4d4692417a2f_2822x1736.png 1272w, https://substackcdn.com/image/fetch/$s_!-hTo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b0e4106-219c-4024-a52f-4d4692417a2f_2822x1736.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><p>GG&#8217;s</p>]]></content:encoded></item><item><title><![CDATA[Receiving Android notifications anywhere.]]></title><description><![CDATA[Hacking together a universal notification system for android.]]></description><link>https://blog.danishjoshi.com/p/receiving-android-notifications-anywhere</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/receiving-android-notifications-anywhere</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Fri, 22 Dec 2023 20:05:00 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!f515!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I switched to an M1 Mac from a Kubuntu machine about a year ago. Everything&#8217;s been great so far. My productivity has skyrocketed; everything just works, and the battery life is awesome.</p><p>The only thing I miss is KDE Connect. More specifically, I miss the ability to receive my Android Push notification on my PC.</p><p>None of the ready-made solutions are simple or OSS enough, so I decided to build something myself.</p><p>Web-Push notification&#8217;s have been pretty standardized as of now, with even <a href="https://onesignal.com/blog/how-ios16-mobile-web-push-updates-change-the-game-for-web-first-companies/">iOS</a> supporting it. So I decided to build something on top of this.</p><p>The basic idea goes something like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!f515!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!f515!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png 424w, https://substackcdn.com/image/fetch/$s_!f515!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png 848w, https://substackcdn.com/image/fetch/$s_!f515!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png 1272w, https://substackcdn.com/image/fetch/$s_!f515!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!f515!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png" width="700" height="368" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:368,&quot;width&quot;:700,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!f515!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png 424w, https://substackcdn.com/image/fetch/$s_!f515!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png 848w, https://substackcdn.com/image/fetch/$s_!f515!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png 1272w, https://substackcdn.com/image/fetch/$s_!f515!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F54e89fcb-39cc-4275-b678-040f1c028c18_700x368.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">kudos to gpt for converting my brain-fart to a legible enough diagram.</figcaption></figure></div><p>The Android app will run in the background forever using <a href="https://developer.android.com/reference/android/service/notification/NotificationListenerService">NotificationListenerService</a> and send all the notification parameters to my server via a post request. The server will then validate the request and do some basic filtering (spam checks and app validation). Post-filtering, it&#8217;ll send a web-push notification to all the devices I&#8217;ve subscribed to (mac,iOS, etc., doesn&#8217;t matter; basically anything with a browser in it).</p><p>I decided to do validation and filtering on the server instead of doing it on the device because (a) recompiling or installing the app for a new ruleset is a chore as opposed to just pushing the changes on the server and letting github actions do the magic, and (b) I can use much more powerful filtering on the server than on the device.</p><p>I haven&#8217;t done Android development or written Java in a long, long time, so I decided to use GPt4 to help me with that. I realized that it is terrible at writing anything but Python.</p><p>So a giga-ton of prompts and pasting Android API references in the context window later... It finally worked (sort of) in just about an afternoon of work.</p><p><a href="https://github.com/SU1199/notilert">Here&#8217;s some ugly code</a> if you want to take a look (it directly sends push notifications from the app itself using a ready-made push notification provider (pushalert); I&nbsp;will implement the server-side features and my own notification server later).</p><p>**sort of, because my phone&#8217;s battery manager is aggressive asf. It kills any notification service when the device is locked. I've tried almost every solution from Don't Kill My App,&nbsp;but it&#8217;s still unreliable as hell. I might have to root my phone and make this a kernel function, or just switch phones all together.</p><p>I will post and update with server-side features soon.</p><p>Adios till then!</p>]]></content:encoded></item><item><title><![CDATA[DBChat : Experiments with recursive self-correcting LLM agents. (WIP)]]></title><description><![CDATA[This idea came to me when I was building a slack-bot for a client.]]></description><link>https://blog.danishjoshi.com/p/dbchat</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/dbchat</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Sat, 18 Nov 2023 17:51:24 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/4a8b7f3d-89c0-4d26-99d8-7f0f736968aa_1024x783.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This idea came to me when I was building a slack-bot for a client. It had to be connected to a postgres db and its job was to answer some predefined slash commands. Basic stuff.</p><p>This got me thinking if there was a way to make a universal DB wrapper using LLMs, that can answer natural language queries on any database, given only the database connection string. I mean automatically parse and understand the schema and generate sql/no-sql commands for each query.</p><p>The basic principle is to first somehow give the language mode enough context about the schema of our database and then get it generate correct sql for a give natural language query.</p><p>I had already tried to do it with the earlier versions of gpt3.5 turbo but failed miserably. earlier versions of 3.5 turbo were instruct tuned versions of pruned gpt3 model. It kinda worked for extremely toy databases but quickly fell apart for any real use-case.</p><p>But right around june of this year, OpenAI introduced function calling. With it came a new instruct tuned model (gpt-4-0613) which adhered to the instructions better. This combined with 16k context length meant that it understood large database better due to larger context length and understood the natural language better to write sql queries on the data.</p><p>Now the remaining challenge was to make a sure that GPT always returned the correct results and not f*ck up the sql queries it generated. This task seems simple on surface but took a lot of experimentation to make it kinda viable.</p><p>To benchmark the viability I used my good old nalanda library database that I scraped during my junior year in college. It has about 10k rows of data, multiple tables and relationships and is about 300mb in size. I wrote about 20 queries of varying complexities and benchmarked run-time and accuracy of each query for every experiment(manually).</p><p>Here was the first viable experiment :</p><p>I extract out the relevant part of schema with examples :</p><pre><code>db_params = {

}
import psycopg2

def fetch_database_info(db_params):
    result_str = ""

    connection = None
    try:
        # Establish a connection to the database
        connection = psycopg2.connect(**db_params)
        cursor = connection.cursor()
        
        # Fetch tables
        cursor.execute("""SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';""")
        tables = cursor.fetchall()
        
        tables_str = "Tables:\n"
        for table in tables:
            table = table[0]
            tables_str += f"  - {table}\n"
            
            # Fetch columns for each table
            cursor.execute(f"""SELECT column_name, data_type FROM information_schema.columns WHERE table_name = '{table}';""")
            columns = cursor.fetchall()
            columns_str = "    Columns:\n"
            for column in columns:
                column_name, data_type = column
                columns_str += f"      - {column_name} ({data_type})\n"
                
            # Fetch sample data (optional)
            cursor.execute(f"SELECT * FROM {table} LIMIT 5;")
            sample_data = cursor.fetchall()
            sample_data_str = "    Sample Data:\n"
            for row in sample_data:
                row = [str(item)[:30] + ('...' if len(str(item)) &gt; 30 else '') for item in row]
                sample_data_str += f"      - {row}\n"
            
            tables_str += columns_str + sample_data_str + "\n"
        
        result_str += tables_str
        
        # Fetch relationships (Foreign Key references)
        cursor.execute("""
        SELECT
            tc.table_name, kcu.column_name, 
            ccu.table_name AS foreign_table_name,
            ccu.column_name AS foreign_column_name 
        FROM 
            information_schema.table_constraints AS tc 
            JOIN information_schema.key_column_usage AS kcu
              ON tc.constraint_name = kcu.constraint_name
              AND tc.table_schema = kcu.table_schema
            JOIN information_schema.constraint_column_usage AS ccu
              ON ccu.constraint_name = tc.constraint_name
        WHERE tc.constraint_type = 'FOREIGN KEY';
        """)
        relationships = cursor.fetchall()
        relationships_str = "Relationships:\n"
        for rel in relationships:
            table, column, foreign_table, foreign_column = rel
            relationships_str += f"  - {table}.{column} -&gt; {foreign_table}.{foreign_column}\n"
        
        result_str += relationships_str
        
    except Exception as e:
        return f"Error: {e}"
    finally:
        if connection:
            connection.close()
    
    return result_str

# Call the function
database_info_str = fetch_database_info(db_params)

print(database_info_str)
</code></pre><p>This gives me output similar to this :</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Bv91!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05510fc2-3e2c-49fd-b1bc-b4f978817d6e_1024x783.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bv91!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05510fc2-3e2c-49fd-b1bc-b4f978817d6e_1024x783.png 424w, https://substackcdn.com/image/fetch/$s_!Bv91!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05510fc2-3e2c-49fd-b1bc-b4f978817d6e_1024x783.png 848w, https://substackcdn.com/image/fetch/$s_!Bv91!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05510fc2-3e2c-49fd-b1bc-b4f978817d6e_1024x783.png 1272w, https://substackcdn.com/image/fetch/$s_!Bv91!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05510fc2-3e2c-49fd-b1bc-b4f978817d6e_1024x783.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bv91!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05510fc2-3e2c-49fd-b1bc-b4f978817d6e_1024x783.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/05510fc2-3e2c-49fd-b1bc-b4f978817d6e_1024x783.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Bv91!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05510fc2-3e2c-49fd-b1bc-b4f978817d6e_1024x783.png 424w, https://substackcdn.com/image/fetch/$s_!Bv91!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05510fc2-3e2c-49fd-b1bc-b4f978817d6e_1024x783.png 848w, https://substackcdn.com/image/fetch/$s_!Bv91!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05510fc2-3e2c-49fd-b1bc-b4f978817d6e_1024x783.png 1272w, https://substackcdn.com/image/fetch/$s_!Bv91!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05510fc2-3e2c-49fd-b1bc-b4f978817d6e_1024x783.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Now to the gpt agent is quite simple :</p><p>Get natural language query from user &gt; give GPT context about the db + the user query and generate sql from it &gt; Validate and execute SQL &gt; Give back the SQL error to GPT recursively till valid query is generated &gt; Give output of that query + the input query to another agent to summarise &gt; display the summary.</p><pre><code>import subprocess
import psycopg2
import openai
import re
import schema

openai.api_key = ""

# Database connection parameters
db_params = {
}

def extract_sql(response):
    pattern = r'```sql\n(.*?)\n```'
    match = re.search(pattern, response, re.DOTALL)
    if match:
        return match.group(1).strip()
    else:
        return None

def get_valid_sql(messages, attempts=0):
    if attempts &gt;= 5:
        return None, []
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        temperature=1,
        messages=messages
    )
    rawResponse = response.choices[0].message['content']
    sqlCommand = extract_sql(rawResponse)
    try:
        cur.execute(sqlCommand)
        rows = cur.fetchall()
        return rawResponse, sqlCommand, rows
    except Exception as e:
        conn.rollback()  # Rollback the current transaction
        messages.append({"role": "user", "content": "It gave me this error please correct it." + str(e)})
        return get_valid_sql(messages, attempts + 1)

def convert_to_natural_language(rows, original_query):
    messages = [
        {"role": "system", "content": "You are a helper that interprets database results into natural language. Convert the given tuples into a human-readable answer based on the user's input question."},
        {"role": "user", "content": f"Original Question: {original_query}"},
        {"role": "user", "content": f"Database Results: {rows}"}
    ]
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=messages
    )
    return "\n\n"+response.choices[0].message['content']

def fetch_db_schema():
    return schema.fetch_database_info(db_params)
    # """
    # Fetch the database schema: list of tables, columns, and their types.
    # """
    # try:
    #     cur.execute("""
    #         SELECT 
    #             table_name, 
    #             column_name, 
    #             data_type 
    #         FROM 
    #             information_schema.columns 
    #         WHERE 
    #             table_schema = 'public' 
    #         ORDER BY 
    #             table_name, 
    #             ordinal_position
    #     """)
    #     rows = cur.fetchall()
    #     schema_desc = ""
    #     current_table = ""
    #     for row in rows:
    #         table_name, column_name, data_type = row
    #         if current_table != table_name:
    #             schema_desc += f"\nTable: {table_name}\n"
    #             current_table = table_name
    #         schema_desc += f"  {column_name} ({data_type})\n"
    #     print(schema_desc)
    #     return schema_desc
    # except Exception as e:
    #     print("Error fetching schema:", e)
    #     return ""

def handle_user_query(messages):
    while True:  # Continue indefinitely until the user decides to exit
        query = input("\nWhats the query? (or type 'exit' to stop) ")
        if query.lower() == 'exit':
            break
        messages.append({"role": "user", "content": query})
        rawResponse, sqlCommand, rows = get_valid_sql(messages)
        if sqlCommand:
            print("\nExecuted SQL Command:", sqlCommand)
            messages.append({"role": "assistant", "content": f"SQL: {rawResponse}"})  # Add SQL to messages list
            # print(messages)
            natural_language_response = convert_to_natural_language(rows, query)
            print(natural_language_response)
        else:
            print("\nFailed to generate a valid SQL command after 5 attempts.")

# Connect to the database
conn = psycopg2.connect(**db_params)
cur = conn.cursor()

# Get database schema
schema = schema.fetch_database_info(db_params)

# Prepare initial messages for SQL generation
messages = [
    {"role": "system", "content": "you are a sql generator program. user inputs their db schema and they query in english. Your job is to think step by step and generate sql for that query to the best of your ability. Important !! : user input is case insensitive. wrap the sql part in '''sql ''' so that its easy for me to understand."},
    {"role": "user", "content": schema}
]

# Start handling user queries
handle_user_query(messages)

# Close the database connection
cur.close()
conn.close()
</code></pre><p>Extremely rudimentary but works on 16/20 of my test queries.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oYXD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5efc32f0-ed71-4026-95f2-879a7b9c6daf_1024x239.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oYXD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5efc32f0-ed71-4026-95f2-879a7b9c6daf_1024x239.png 424w, https://substackcdn.com/image/fetch/$s_!oYXD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5efc32f0-ed71-4026-95f2-879a7b9c6daf_1024x239.png 848w, https://substackcdn.com/image/fetch/$s_!oYXD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5efc32f0-ed71-4026-95f2-879a7b9c6daf_1024x239.png 1272w, https://substackcdn.com/image/fetch/$s_!oYXD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5efc32f0-ed71-4026-95f2-879a7b9c6daf_1024x239.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oYXD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5efc32f0-ed71-4026-95f2-879a7b9c6daf_1024x239.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5efc32f0-ed71-4026-95f2-879a7b9c6daf_1024x239.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!oYXD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5efc32f0-ed71-4026-95f2-879a7b9c6daf_1024x239.png 424w, https://substackcdn.com/image/fetch/$s_!oYXD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5efc32f0-ed71-4026-95f2-879a7b9c6daf_1024x239.png 848w, https://substackcdn.com/image/fetch/$s_!oYXD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5efc32f0-ed71-4026-95f2-879a7b9c6daf_1024x239.png 1272w, https://substackcdn.com/image/fetch/$s_!oYXD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5efc32f0-ed71-4026-95f2-879a7b9c6daf_1024x239.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xvL-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc18b58e-1636-4c79-8116-4cc9440a52fe_1024x575.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xvL-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc18b58e-1636-4c79-8116-4cc9440a52fe_1024x575.png 424w, https://substackcdn.com/image/fetch/$s_!xvL-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc18b58e-1636-4c79-8116-4cc9440a52fe_1024x575.png 848w, https://substackcdn.com/image/fetch/$s_!xvL-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc18b58e-1636-4c79-8116-4cc9440a52fe_1024x575.png 1272w, https://substackcdn.com/image/fetch/$s_!xvL-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc18b58e-1636-4c79-8116-4cc9440a52fe_1024x575.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xvL-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc18b58e-1636-4c79-8116-4cc9440a52fe_1024x575.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc18b58e-1636-4c79-8116-4cc9440a52fe_1024x575.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!xvL-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc18b58e-1636-4c79-8116-4cc9440a52fe_1024x575.png 424w, https://substackcdn.com/image/fetch/$s_!xvL-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc18b58e-1636-4c79-8116-4cc9440a52fe_1024x575.png 848w, https://substackcdn.com/image/fetch/$s_!xvL-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc18b58e-1636-4c79-8116-4cc9440a52fe_1024x575.png 1272w, https://substackcdn.com/image/fetch/$s_!xvL-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc18b58e-1636-4c79-8116-4cc9440a52fe_1024x575.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!k7QY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abfd5ee-b0a3-4f15-b332-35275cc4e926_1024x974.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!k7QY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abfd5ee-b0a3-4f15-b332-35275cc4e926_1024x974.png 424w, https://substackcdn.com/image/fetch/$s_!k7QY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abfd5ee-b0a3-4f15-b332-35275cc4e926_1024x974.png 848w, https://substackcdn.com/image/fetch/$s_!k7QY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abfd5ee-b0a3-4f15-b332-35275cc4e926_1024x974.png 1272w, https://substackcdn.com/image/fetch/$s_!k7QY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abfd5ee-b0a3-4f15-b332-35275cc4e926_1024x974.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!k7QY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abfd5ee-b0a3-4f15-b332-35275cc4e926_1024x974.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3abfd5ee-b0a3-4f15-b332-35275cc4e926_1024x974.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!k7QY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abfd5ee-b0a3-4f15-b332-35275cc4e926_1024x974.png 424w, https://substackcdn.com/image/fetch/$s_!k7QY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abfd5ee-b0a3-4f15-b332-35275cc4e926_1024x974.png 848w, https://substackcdn.com/image/fetch/$s_!k7QY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abfd5ee-b0a3-4f15-b332-35275cc4e926_1024x974.png 1272w, https://substackcdn.com/image/fetch/$s_!k7QY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3abfd5ee-b0a3-4f15-b332-35275cc4e926_1024x974.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Next part is making it more robust for complex databases and making it modular to work on any given database string. I'll also share my benchmark and testing suite in the next part. I'll also be testing <a href="https://github.com/defog-ai/sqlcoder">this</a>(https://github.com/defog-ai/sqlcoder) OSS llm on my bench.</p><p>To be continued....</p>]]></content:encoded></item><item><title><![CDATA[Training LLMs for fun(and profit).]]></title><description><![CDATA[This is an active collection of resources I've found on understanding, training and fine-tuning, large language models.]]></description><link>https://blog.danishjoshi.com/p/training-llms-for-funand-profit</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/training-llms-for-funand-profit</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Mon, 08 May 2023 19:54:12 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b15ae046-f448-47f1-aab0-c31f4ed412bb_1357x758.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MiCB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffea301ed-b611-4802-b652-79977eab23c2_1357x758.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MiCB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffea301ed-b611-4802-b652-79977eab23c2_1357x758.jpeg 424w, https://substackcdn.com/image/fetch/$s_!MiCB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffea301ed-b611-4802-b652-79977eab23c2_1357x758.jpeg 848w, https://substackcdn.com/image/fetch/$s_!MiCB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffea301ed-b611-4802-b652-79977eab23c2_1357x758.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!MiCB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffea301ed-b611-4802-b652-79977eab23c2_1357x758.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MiCB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffea301ed-b611-4802-b652-79977eab23c2_1357x758.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fea301ed-b611-4802-b652-79977eab23c2_1357x758.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!MiCB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffea301ed-b611-4802-b652-79977eab23c2_1357x758.jpeg 424w, https://substackcdn.com/image/fetch/$s_!MiCB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffea301ed-b611-4802-b652-79977eab23c2_1357x758.jpeg 848w, https://substackcdn.com/image/fetch/$s_!MiCB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffea301ed-b611-4802-b652-79977eab23c2_1357x758.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!MiCB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffea301ed-b611-4802-b652-79977eab23c2_1357x758.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>This is an active collection of resources I've found on understanding, training and fine-tuning, large language models.</p><p><a href="https://fluff-ambulance-944.notion.site/TLLM-Resources-af3dec61ecf0449986aa7deb95be8b03">I plan to update this often and it's much easier to do It in notion than on my blog so here's the notion link.</a></p><p>May your shoggoth be aligned with you &#128126;</p>]]></content:encoded></item><item><title><![CDATA[Making a better twitter recommendation engine. Part(1) Scraping Following's Followings.]]></title><description><![CDATA[I have a simple need.]]></description><link>https://blog.danishjoshi.com/p/making-a-better-twitter-recommendation-engine-part1-scraping-followings-followings</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/making-a-better-twitter-recommendation-engine-part1-scraping-followings-followings</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Thu, 20 Apr 2023 11:35:29 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/88c3839d-303e-40f9-9322-f7aabfdbf99f_1024x118.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have a simple need. Show me tweets of people who are followed by the accounts I follow (but I don't). I believe this would create a much better "For You" page than whatever shit elon's been cooking in there (seriously.... the for you page is so bad its honestly appalling). I'll add momentum based recommendation (trending) later once I have a system to reliably get the tweets of the people who I follow, follow (if you get what I mean &#128517;)</p><p>So as for part 1 lets make a twitter scrape that scrapes all the handles of accounts a person follows. To help me make sense of this clusterfuck of an API I'm gonna use the divine powers of GPT4 .</p><p>Its honestly pretty surprising how good is gpt, at understanding the graph api twitter uses. It reduced the time to build this thing from like a weekend to like a couple of hours.Freakin magical.</p><p>This is the request twitter makes to make the initial fetch of the follower list :</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YIR1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9205c291-f48f-4dce-aeb1-ec2848d692b0_1024x237.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YIR1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9205c291-f48f-4dce-aeb1-ec2848d692b0_1024x237.png 424w, https://substackcdn.com/image/fetch/$s_!YIR1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9205c291-f48f-4dce-aeb1-ec2848d692b0_1024x237.png 848w, https://substackcdn.com/image/fetch/$s_!YIR1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9205c291-f48f-4dce-aeb1-ec2848d692b0_1024x237.png 1272w, https://substackcdn.com/image/fetch/$s_!YIR1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9205c291-f48f-4dce-aeb1-ec2848d692b0_1024x237.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YIR1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9205c291-f48f-4dce-aeb1-ec2848d692b0_1024x237.png" width="840" height="194" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9205c291-f48f-4dce-aeb1-ec2848d692b0_1024x237.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:194,&quot;width&quot;:840,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!YIR1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9205c291-f48f-4dce-aeb1-ec2848d692b0_1024x237.png 424w, https://substackcdn.com/image/fetch/$s_!YIR1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9205c291-f48f-4dce-aeb1-ec2848d692b0_1024x237.png 848w, https://substackcdn.com/image/fetch/$s_!YIR1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9205c291-f48f-4dce-aeb1-ec2848d692b0_1024x237.png 1272w, https://substackcdn.com/image/fetch/$s_!YIR1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9205c291-f48f-4dce-aeb1-ec2848d692b0_1024x237.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>Looking closely these are the variables encoded in the URL of the request :</p><pre><code>{"userId":"183749519","count":20,"includePromotedContent":false}
{"blue_business_profile_image_shape_enabled":true,"responsive_web_graphql_exclude_directive_enabled":true,"verified_phone_label_enabled":true,"responsive_web_graphql_timeline_navigation_enabled":true,"responsive_web_graphql_skip_user_profile_image_extensions_enabled":false,"tweetypie_unmention_optimization_enabled":true,"vibe_api_enabled":true,"responsive_web_edit_tweet_api_enabled":true,"graphql_is_translatable_rweb_tweet_is_translatable_enabled":true,"view_counts_everywhere_api_enabled":true,"longform_notetweets_consumption_enabled":true,"tweet_awards_web_tipping_enabled":false,"freedom_of_speech_not_reach_fetch_enabled":false,"standardized_nudges_misinfo":true,"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled":false,"interactive_text_enabled":true,"responsive_web_text_conversations_enabled":false,"longform_notetweets_rich_text_read_enabled":true,"responsive_web_enhance_cards_enabled":false}</code></pre><p>In the second scroll of the list a variable called cursor gets added to the request which specified the sub-list of followers to fetch. This cursor is returned from the previous request as the timeline cursor.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nAIl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fac2a8f-8b67-4094-b6bd-94184d82c6bc_1024x118.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nAIl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fac2a8f-8b67-4094-b6bd-94184d82c6bc_1024x118.png 424w, https://substackcdn.com/image/fetch/$s_!nAIl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fac2a8f-8b67-4094-b6bd-94184d82c6bc_1024x118.png 848w, https://substackcdn.com/image/fetch/$s_!nAIl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fac2a8f-8b67-4094-b6bd-94184d82c6bc_1024x118.png 1272w, https://substackcdn.com/image/fetch/$s_!nAIl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fac2a8f-8b67-4094-b6bd-94184d82c6bc_1024x118.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nAIl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fac2a8f-8b67-4094-b6bd-94184d82c6bc_1024x118.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1fac2a8f-8b67-4094-b6bd-94184d82c6bc_1024x118.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!nAIl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fac2a8f-8b67-4094-b6bd-94184d82c6bc_1024x118.png 424w, https://substackcdn.com/image/fetch/$s_!nAIl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fac2a8f-8b67-4094-b6bd-94184d82c6bc_1024x118.png 848w, https://substackcdn.com/image/fetch/$s_!nAIl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fac2a8f-8b67-4094-b6bd-94184d82c6bc_1024x118.png 1272w, https://substackcdn.com/image/fetch/$s_!nAIl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fac2a8f-8b67-4094-b6bd-94184d82c6bc_1024x118.png 1456w" sizes="100vw"></picture><div></div></div></a></figure></div><pre><code>{"userId":"183749519","count":20,"cursor":"1763689340909851626|1649001226504765398","includePromotedContent":false}</code></pre><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uN9O!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e3aa9f7-89ab-49ab-9d92-aa01c9b28e56_1024x237.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uN9O!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e3aa9f7-89ab-49ab-9d92-aa01c9b28e56_1024x237.png 424w, https://substackcdn.com/image/fetch/$s_!uN9O!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e3aa9f7-89ab-49ab-9d92-aa01c9b28e56_1024x237.png 848w, https://substackcdn.com/image/fetch/$s_!uN9O!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e3aa9f7-89ab-49ab-9d92-aa01c9b28e56_1024x237.png 1272w, https://substackcdn.com/image/fetch/$s_!uN9O!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e3aa9f7-89ab-49ab-9d92-aa01c9b28e56_1024x237.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uN9O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e3aa9f7-89ab-49ab-9d92-aa01c9b28e56_1024x237.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9e3aa9f7-89ab-49ab-9d92-aa01c9b28e56_1024x237.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!uN9O!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e3aa9f7-89ab-49ab-9d92-aa01c9b28e56_1024x237.png 424w, https://substackcdn.com/image/fetch/$s_!uN9O!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e3aa9f7-89ab-49ab-9d92-aa01c9b28e56_1024x237.png 848w, https://substackcdn.com/image/fetch/$s_!uN9O!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e3aa9f7-89ab-49ab-9d92-aa01c9b28e56_1024x237.png 1272w, https://substackcdn.com/image/fetch/$s_!uN9O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e3aa9f7-89ab-49ab-9d92-aa01c9b28e56_1024x237.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>So to fetch all the list of followers of an account I just need to loop this request with different cursor till the beginning of cursor reaches 0. ie the request returns 0|xyz as the cursor value.</p><p>Now to build the parser I could study the whole response orrrrr I can just pass the resonse to GPT4 and ask it to build a parser for me &#129327;.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!clGP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8deaa847-24c7-498a-8824-362aadde990e_1024x211.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!clGP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8deaa847-24c7-498a-8824-362aadde990e_1024x211.png 424w, https://substackcdn.com/image/fetch/$s_!clGP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8deaa847-24c7-498a-8824-362aadde990e_1024x211.png 848w, https://substackcdn.com/image/fetch/$s_!clGP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8deaa847-24c7-498a-8824-362aadde990e_1024x211.png 1272w, https://substackcdn.com/image/fetch/$s_!clGP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8deaa847-24c7-498a-8824-362aadde990e_1024x211.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!clGP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8deaa847-24c7-498a-8824-362aadde990e_1024x211.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8deaa847-24c7-498a-8824-362aadde990e_1024x211.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!clGP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8deaa847-24c7-498a-8824-362aadde990e_1024x211.png 424w, https://substackcdn.com/image/fetch/$s_!clGP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8deaa847-24c7-498a-8824-362aadde990e_1024x211.png 848w, https://substackcdn.com/image/fetch/$s_!clGP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8deaa847-24c7-498a-8824-362aadde990e_1024x211.png 1272w, https://substackcdn.com/image/fetch/$s_!clGP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8deaa847-24c7-498a-8824-362aadde990e_1024x211.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">write me python code to extract all the usernames (screen_name) and the pagination number (bottom from these type of json responses (don't rewrite the whole json text just give me a function):</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0VxV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f4cc2cc-f477-4c9c-a4b3-514142532d44_1024x744.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0VxV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f4cc2cc-f477-4c9c-a4b3-514142532d44_1024x744.png 424w, https://substackcdn.com/image/fetch/$s_!0VxV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f4cc2cc-f477-4c9c-a4b3-514142532d44_1024x744.png 848w, https://substackcdn.com/image/fetch/$s_!0VxV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f4cc2cc-f477-4c9c-a4b3-514142532d44_1024x744.png 1272w, https://substackcdn.com/image/fetch/$s_!0VxV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f4cc2cc-f477-4c9c-a4b3-514142532d44_1024x744.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0VxV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f4cc2cc-f477-4c9c-a4b3-514142532d44_1024x744.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6f4cc2cc-f477-4c9c-a4b3-514142532d44_1024x744.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!0VxV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f4cc2cc-f477-4c9c-a4b3-514142532d44_1024x744.png 424w, https://substackcdn.com/image/fetch/$s_!0VxV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f4cc2cc-f477-4c9c-a4b3-514142532d44_1024x744.png 848w, https://substackcdn.com/image/fetch/$s_!0VxV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f4cc2cc-f477-4c9c-a4b3-514142532d44_1024x744.png 1272w, https://substackcdn.com/image/fetch/$s_!0VxV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6f4cc2cc-f477-4c9c-a4b3-514142532d44_1024x744.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>The pagination code was Incorrect as i wasn't specific enough to what exact attribute to extract so I ask it to modify the code.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yqzk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43f1ab23-b8c3-4dda-8629-bc38e1aaa29b_1024x91.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yqzk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43f1ab23-b8c3-4dda-8629-bc38e1aaa29b_1024x91.png 424w, https://substackcdn.com/image/fetch/$s_!yqzk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43f1ab23-b8c3-4dda-8629-bc38e1aaa29b_1024x91.png 848w, https://substackcdn.com/image/fetch/$s_!yqzk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43f1ab23-b8c3-4dda-8629-bc38e1aaa29b_1024x91.png 1272w, https://substackcdn.com/image/fetch/$s_!yqzk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43f1ab23-b8c3-4dda-8629-bc38e1aaa29b_1024x91.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yqzk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43f1ab23-b8c3-4dda-8629-bc38e1aaa29b_1024x91.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/43f1ab23-b8c3-4dda-8629-bc38e1aaa29b_1024x91.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!yqzk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43f1ab23-b8c3-4dda-8629-bc38e1aaa29b_1024x91.png 424w, https://substackcdn.com/image/fetch/$s_!yqzk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43f1ab23-b8c3-4dda-8629-bc38e1aaa29b_1024x91.png 848w, https://substackcdn.com/image/fetch/$s_!yqzk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43f1ab23-b8c3-4dda-8629-bc38e1aaa29b_1024x91.png 1272w, https://substackcdn.com/image/fetch/$s_!yqzk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F43f1ab23-b8c3-4dda-8629-bc38e1aaa29b_1024x91.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">write me python code to extract the pagination number (bottom) eg: "value" "0|1648981762677669836""cursorType"."Bottom"}: I need "value" "0|1648981762677669836") from these type of ison responses (don't requrite the whole json text just give me a function):</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!M7tI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c744071-ab31-4503-b280-93b56164bc84_1024x409.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!M7tI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c744071-ab31-4503-b280-93b56164bc84_1024x409.png 424w, https://substackcdn.com/image/fetch/$s_!M7tI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c744071-ab31-4503-b280-93b56164bc84_1024x409.png 848w, https://substackcdn.com/image/fetch/$s_!M7tI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c744071-ab31-4503-b280-93b56164bc84_1024x409.png 1272w, https://substackcdn.com/image/fetch/$s_!M7tI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c744071-ab31-4503-b280-93b56164bc84_1024x409.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!M7tI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c744071-ab31-4503-b280-93b56164bc84_1024x409.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5c744071-ab31-4503-b280-93b56164bc84_1024x409.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!M7tI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c744071-ab31-4503-b280-93b56164bc84_1024x409.png 424w, https://substackcdn.com/image/fetch/$s_!M7tI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c744071-ab31-4503-b280-93b56164bc84_1024x409.png 848w, https://substackcdn.com/image/fetch/$s_!M7tI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c744071-ab31-4503-b280-93b56164bc84_1024x409.png 1272w, https://substackcdn.com/image/fetch/$s_!M7tI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c744071-ab31-4503-b280-93b56164bc84_1024x409.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>All of this worked the first try OFC. Now the only thing left was to loop this shit till the end of cursor. For this I gave it all the code it had previously written to modify and make the final script.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iZia!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6230f08b-8849-40bb-a7e4-d166b5c65083_1024x188.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iZia!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6230f08b-8849-40bb-a7e4-d166b5c65083_1024x188.png 424w, https://substackcdn.com/image/fetch/$s_!iZia!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6230f08b-8849-40bb-a7e4-d166b5c65083_1024x188.png 848w, https://substackcdn.com/image/fetch/$s_!iZia!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6230f08b-8849-40bb-a7e4-d166b5c65083_1024x188.png 1272w, https://substackcdn.com/image/fetch/$s_!iZia!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6230f08b-8849-40bb-a7e4-d166b5c65083_1024x188.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iZia!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6230f08b-8849-40bb-a7e4-d166b5c65083_1024x188.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6230f08b-8849-40bb-a7e4-d166b5c65083_1024x188.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!iZia!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6230f08b-8849-40bb-a7e4-d166b5c65083_1024x188.png 424w, https://substackcdn.com/image/fetch/$s_!iZia!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6230f08b-8849-40bb-a7e4-d166b5c65083_1024x188.png 848w, https://substackcdn.com/image/fetch/$s_!iZia!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6230f08b-8849-40bb-a7e4-d166b5c65083_1024x188.png 1272w, https://substackcdn.com/image/fetch/$s_!iZia!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6230f08b-8849-40bb-a7e4-d166b5c65083_1024x188.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">modify this code to take an input from cli of user id. and fetch all of thier list of followers using extract user names and using a loop for pagination variable. the first part of pagination number becomes 0 xyz when we reach end of the list of followers. this the sample payload {"userld":"1556925600459268098""count":20,"cursor":"1761587287535449529|1648969075902119784",includePromotedContent":false} you'll have to mondiy the pagination number for each request.</figcaption></figure></div><p>aaaand It worked. On the first attempt nonetheless lmao.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ctlO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd3375-5815-447b-b800-64e12643b7a0_1024x471.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ctlO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd3375-5815-447b-b800-64e12643b7a0_1024x471.png 424w, https://substackcdn.com/image/fetch/$s_!ctlO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd3375-5815-447b-b800-64e12643b7a0_1024x471.png 848w, https://substackcdn.com/image/fetch/$s_!ctlO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd3375-5815-447b-b800-64e12643b7a0_1024x471.png 1272w, https://substackcdn.com/image/fetch/$s_!ctlO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd3375-5815-447b-b800-64e12643b7a0_1024x471.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ctlO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd3375-5815-447b-b800-64e12643b7a0_1024x471.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/62bd3375-5815-447b-b800-64e12643b7a0_1024x471.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!ctlO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd3375-5815-447b-b800-64e12643b7a0_1024x471.png 424w, https://substackcdn.com/image/fetch/$s_!ctlO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd3375-5815-447b-b800-64e12643b7a0_1024x471.png 848w, https://substackcdn.com/image/fetch/$s_!ctlO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd3375-5815-447b-b800-64e12643b7a0_1024x471.png 1272w, https://substackcdn.com/image/fetch/$s_!ctlO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62bd3375-5815-447b-b800-64e12643b7a0_1024x471.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>It was truly wild seeing it understand the api response so well.</p><p>I am planning to create an llm agent that automates all of this by just giving it a url of a webpage and a prompt about what things to scrape... but first lemme fix my twitter recommendations real quick.</p>]]></content:encoded></item><item><title><![CDATA[{scraping} will set you free. jk.. unless...]]></title><link>https://blog.danishjoshi.com/p/scraping-will-set-you-free-jk-unless</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/scraping-will-set-you-free-jk-unless</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Fri, 03 Feb 2023 17:41:04 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/072536af-64f3-4849-90b1-6e50aa3d3d5f_640x724.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!43Va!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086a1f75-df45-49f8-9d62-161bd96ef1d4_640x724.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!43Va!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086a1f75-df45-49f8-9d62-161bd96ef1d4_640x724.png 424w, https://substackcdn.com/image/fetch/$s_!43Va!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086a1f75-df45-49f8-9d62-161bd96ef1d4_640x724.png 848w, https://substackcdn.com/image/fetch/$s_!43Va!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086a1f75-df45-49f8-9d62-161bd96ef1d4_640x724.png 1272w, https://substackcdn.com/image/fetch/$s_!43Va!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086a1f75-df45-49f8-9d62-161bd96ef1d4_640x724.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!43Va!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086a1f75-df45-49f8-9d62-161bd96ef1d4_640x724.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/086a1f75-df45-49f8-9d62-161bd96ef1d4_640x724.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!43Va!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086a1f75-df45-49f8-9d62-161bd96ef1d4_640x724.png 424w, https://substackcdn.com/image/fetch/$s_!43Va!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086a1f75-df45-49f8-9d62-161bd96ef1d4_640x724.png 848w, https://substackcdn.com/image/fetch/$s_!43Va!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086a1f75-df45-49f8-9d62-161bd96ef1d4_640x724.png 1272w, https://substackcdn.com/image/fetch/$s_!43Va!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086a1f75-df45-49f8-9d62-161bd96ef1d4_640x724.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div>]]></content:encoded></item><item><title><![CDATA[Building a mass college surveillance system using google's facenet + faiss + postgres.]]></title><description><![CDATA[Consider this a part 3 of the series , where I scraped a (1) college's vulnerable library database and (2) made a face mash/hot||not clone.]]></description><link>https://blog.danishjoshi.com/p/building-a-mass-college-surveillance-system-using-googles-facenet-faiss-postgres</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/building-a-mass-college-surveillance-system-using-googles-facenet-faiss-postgres</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Sun, 22 Jan 2023 08:47:48 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2cAq!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7e1fe32-995e-43d3-a1a8-3cf0e738c614_469x469.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Consider this a part 3 of the series , where I scraped a (1) college's vulnerable library database and (2) made a face mash/hot||not clone. For the third part, I am going to deploy a SOTA facial recognition model for all the 8000+ student faces I scraped from the library's site.</p><p>If you, like me, haven't been following the state of the art in facial recognition, would't be aware that how GOOD these models have gotten over the years.</p><p>Experiments show that human beings have 97.53% accuracy on facial recognition tasks whereas some models like googles facenet have already reached and passed that accuracy level. (facet has 99.65% accuracy on Labeled Faces in the Wild&nbsp; benchmark)</p><p><a href="https://github.com/serengil">serengil</a> has made an awesome wrapper for all the popular soda models like facenet, egg-face etc. called <a href="https://github.com/serengil">deepFace</a> (not to be confused with facebook's deepface model).</p><p>First order of business is getting all the images from our database with all the enums.</p><p>We do so by using this simple command &gt;</p><p>Next we'll need to convert these images to vector embeddings generated by the facenet mode. We'll use deepFace deepface.represent() method to do the same. It can take in base64 image as its input, which is perfect for our use case.</p><p>Then we package this data into a 1d vector and push into a representation list. faiss library we'll use in the future will required a 2d vector. So we'll use a simple for loop to get a vector of (8000,512) dims (facenet512 produces a array of 512 chunks).</p><p>Then we encode everything into a numpy array and save it on the disk. This way we won't have to generate the embeddings again when we deploy it to production later.</p><p>Next we pass this numpy array to the faiss library to index. Without faiss we would have to calculate the cosine distance between each vector when we search for a similarity match for a face. Faiss is pretty neat overall and allow us to run a nearest neighbour search that runs in millisecond even on gigantic multi-million vector datasets. check it out <a href="https://engineering.fb.com/2017/03/29/data-infrastructure/faiss-a-library-for-efficient-similarity-search/">here.</a></p><p>To search for a match in an image we first convert the image to its vector representation then make a 3d np array and use index.search method to find the k most similar faces in the database.</p><p>Faiss return the index of the vector, we can pass this index to our representation vector to get the enum of the face.</p><p>And voila! we have made ourselves a super scalable surveillance system. Now to actually deploy this we'll first have to go over some trivial hurdles.</p><p>Here's the quick and dirty jupyter notebook showcasing what I described above.</p><p>In&nbsp;[&nbsp;]:</p><pre><code>mName = "Facenet512"
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>#Connect to DB

import psycopg2

try:
    conn = psycopg2.connect("dbname='nalanda' user='postgres' host='localhost' password='password'")
    print("connected")
except:
    print("I am unable to connect to the database")
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>cur = conn.cursor()
        
cur.execute("SELECT enum,profile from raw limit 500")

rows = cur.fetchall()

len(rows)
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>from deepface import DeepFace
import numpy as np

representation = []
failed_enums = []
for row in rows:
    try:
        vector = DeepFace.represent(row[1],model_name=mName)
    except:
        print("failed to process enum",row[0])
        failed_enums.append(row[0])
        continue
    pair = []
    pair.append(row[0])
    print(row[0])
    pair.append(vector)
    representation.append(pair)

embeddings = []
for i in range(0, len(representation)):
    embedding = representation[i][1]
    embeddings.append(embedding)

embeddings = np.array(embeddings, dtype='f')

np.save("embeddings",embeddings)
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>import faiss                   # make faiss available
index = faiss.IndexFlatL2(embeddings.shape[1])   # build the index
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>index.add(embeddings)
print(index.ntotal)
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>testVector = DeepFace.represent(img_path = "test.jpg",model_name=mName)
target_representation = np.array(testVector, dtype='f')
target_representation = np.expand_dims(target_representation, axis=0)
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>k = 20
distances, neighbors = index.search(target_representation, k)

representation[neighbors[0][0]][0]
# distances, neighbors
</code></pre><h2>Connecting DB and Making it deployable to &#9729;&#65039;</h2><p>In&nbsp;[&nbsp;]:</p><pre><code>#Connect to DB

import psycopg2

try:
    conn = psycopg2.connect("dbname='nalanda' user='postgres' host='localhost' password='password'")
    print("connected")
except:
    print("I am unable to connect to the database")
cur = conn.cursor()
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>import numpy as np
embeddings = np.load("all_embeddings.npy",allow_pickle=True)
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>import faiss                   # make faiss available
index = faiss.IndexFlatL2(embeddings.shape[1])   # build the index
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>index.add(embeddings)
print(index.ntotal)
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>from deepface import DeepFace
mName = "Facenet512"
testVector = DeepFace.represent(img_path = "d.jpeg",model_name=mName)
target_representation = np.array(testVector, dtype='f')
target_representation = np.expand_dims(target_representation, axis=0)
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>k = 5
distances, neighbors = index.search(target_representation, k)

ids = (int(neighbors[0][0]),int(neighbors[0][1]),int(neighbors[0][2]),int(neighbors[0][3]),int(neighbors[0][4]))
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>cur.execute("select student.fname, student.lname from student join address on student.enum=address.enum join contact on student.enum=contact.enum join raw on student.enum=raw.enum join facenet on student.enum=facenet.enum where facenet.index=%s or facenet.index= %s or facenet.index= %s or facenet.index= %s or facenet.index= %s;",(ids))
cur.fetchall()
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>cur.execute("select * from student join address on student.enum=address.enum join contact on student.enum=contact.enum join raw on student.enum=raw.enum join facenet on student.enum=facenet.enum where facenet.index=%s;",(int(neighbors[0][0]),))
cur.fetchall()
</code></pre><p>I created a new table with all the enums of the people whose images were available in the database with the index of those enums in the faiss database. Then it was just the game of converting input images to vectors and running a faiss search to get the nearest neighbor and find the enum of that index number in the DB and joinig it with the rest of tables to get the complete info.</p><p>Here's the modified notebook which does the same while making embeddings.</p><p>In&nbsp;[&nbsp;]:</p><pre><code>mName = "Facenet512"
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>#Connect to DB

import psycopg2

try:
    conn = psycopg2.connect("dbname='nalanda' user='postgres' host='localhost' password='password'")
    print("connected")
except:
    print("I am unable to connect to the database")
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>cur = conn.cursor()
        
cur.execute("SELECT enum,profile from raw where LENGTH(profile) &gt; 100 order by enum limit 10")

rows = cur.fetchall()

len(rows)
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>from deepface import DeepFace
import numpy as np

index = 0 #representation length

representation = []
failed_enums = []
for row in rows:
    try:
        vector = DeepFace.represent(row[1],model_name=mName)
        cur.execute("INSERT INTO facenet (enum, index) VALUES (%s, %s)",(row[0],index))
        conn.commit()
    except:
        print("failed to process enum",row[0])
        failed_enums.append(row[0])
        continue
    pair = []
    pair.append(row[0])
    print(row[0])
    pair.append(vector)
    representation.append(pair)
    index+=1

embeddings = []
for i in range(0, len(representation)):
    embedding = representation[i][1]
    embeddings.append(embedding)

embeddings = np.array(embeddings, dtype='f')

np.save("embeddings",embeddings)
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>import faiss                   # make faiss available
index = faiss.IndexFlatL2(embeddings.shape[1])   # build the index
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>import numpy as np
embeddings = np.load("all_embeddings.npy",allow_pickle=True).shape
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>index.add(embeddings)
print(index.ntotal)
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>testVector = DeepFace.represent(img_path = "test.jpg",model_name=mName)
target_representation = np.array(testVector, dtype='f')
target_representation = np.expand_dims(target_representation, axis=0)
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code>k = 20
distances, neighbors = index.search(target_representation, k)

representation[neighbors[0][0]][0]
# distances, neighbors
</code></pre><p>In&nbsp;[&nbsp;]:</p><pre><code> 
</code></pre><p>In part 2 I'll explain how I made a custom gradio frontend for it and pushed it to the cloud for ez inference.</p>]]></content:encoded></item><item><title><![CDATA[Reverse engineering truecaller mobile app.... and making a bot out of the exposed APIs]]></title><description><![CDATA[So here's the thing....]]></description><link>https://blog.danishjoshi.com/p/reverse-engineering-truecaller-mobile-app-and-making-a-bot-out-of-the-exposed-apis</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/reverse-engineering-truecaller-mobile-app-and-making-a-bot-out-of-the-exposed-apis</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Fri, 19 Aug 2022 09:26:33 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/35bf59ae-9898-44c0-af00-55454e632425_1024x564.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So here's the thing.... I really like the concept of knowing the contact info of an unknown number but hate the part where I give the whole dialer + contact_list + last_seen access to an app to publish it in a public database with questionable security.</p><p>Which lead me to creating this project.</p><h3>&gt; Getting the endpoints from truecaller web-app</h3><p>After logging into the web-app the tc server generates a session token which is used to AUTH subsequent requests.</p><p>The problem I ran into was that truecaller only allows the lookup of 10 numbers/day on its website. For anything more than this you have to use their mobile app. So onto the next step..... breaking their andorid app.</p><h3>&gt; Reverse engineering the android app</h3><p>We can use tools like burpsuite proxy to intercept normal requests on any device (android, iOS etc.) by just installing a custom ca certificate onto the device to trust and routing all the traffic through the proxy.</p><p><a href="https://portswigger.net/support/configuring-an-android-device-to-work-with-burp">Here's</a> how to do it with burp.</p><p>But modern apps use something called SSl-pinning. This allows them to use their own ssl certificate store instead of trusting the device's own certificates.</p><p>Detailed writeup <a href="https://owasp.org/www-community/controls/Certificate_and_Public_Key_Pinning">here.</a></p><p>So if we want to intercept network requests of an SSL pinned app we must first find a way to disable it or add our own certificate to the app's trusted cert store. This involves roughly these steps -&gt;</p><ul><li><p>Decompile the app using<a href="https://ibotpeaches.github.io/Apktool/"> apk-tool </a>to generate smali code for the app.</p></li><li><p>Remove all the certificate verification checks from the code (actually hard depending on implementation)</p></li><li><p>Recompile the app and <a href="https://github.com/patrickfav/uber-apk-signer">sign it.</a></p></li></ul><p>Luckily shroudedcode has made an <a href="https://github.com/shroudedcode/apk-mitm">awesome cli app</a> to do just that.</p><p>This method may or may not work depending on the app's version as its implementation of ssl-pinning may differ from what apk-mitm aims to patch. I reccomend trying out any older version of the app if the tool fails on the newer one.</p><p>Another frequently used technique used by app-sec professionals is<a href="https://github.com/frida/frida"> frida</a>. Which is described best as greasy monkey for andorid apps. If you don't have a rooted device for frida runtime. You can use a sub-framework called <a href="https://github.com/sensepost/objection">objection</a> to embed frida runtime in the app itself.</p><p>Last technique to disable cert-pinning, which is also my favorite one so far is using good old <a href="https://repo.xposed.info/module/de.robv.android.xposed.installer">xposed</a> framework with <a href="https://github.com/Fuzion24/JustTrustMe">justtrustme</a> module. This disables ssl-pinning across the board for the whole device.</p><p>Setting up environment -&gt;</p><p>I went with bluestacks instead of avdmanager because it didn't want the bloat(android studio) that comes with it.</p><p>After installing bluestacks, I recommend <a href="https://bstweaker.tk/">this tool </a>to root the vm and install xposed framework on it with minimal hassle.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1POe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6eb337fe-83a2-42c8-ba1a-f7e43fd9d9c6_1024x564.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1POe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6eb337fe-83a2-42c8-ba1a-f7e43fd9d9c6_1024x564.png 424w, https://substackcdn.com/image/fetch/$s_!1POe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6eb337fe-83a2-42c8-ba1a-f7e43fd9d9c6_1024x564.png 848w, https://substackcdn.com/image/fetch/$s_!1POe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6eb337fe-83a2-42c8-ba1a-f7e43fd9d9c6_1024x564.png 1272w, https://substackcdn.com/image/fetch/$s_!1POe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6eb337fe-83a2-42c8-ba1a-f7e43fd9d9c6_1024x564.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1POe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6eb337fe-83a2-42c8-ba1a-f7e43fd9d9c6_1024x564.png" width="711" height="391" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6eb337fe-83a2-42c8-ba1a-f7e43fd9d9c6_1024x564.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:391,&quot;width&quot;:711,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!1POe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6eb337fe-83a2-42c8-ba1a-f7e43fd9d9c6_1024x564.png 424w, https://substackcdn.com/image/fetch/$s_!1POe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6eb337fe-83a2-42c8-ba1a-f7e43fd9d9c6_1024x564.png 848w, https://substackcdn.com/image/fetch/$s_!1POe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6eb337fe-83a2-42c8-ba1a-f7e43fd9d9c6_1024x564.png 1272w, https://substackcdn.com/image/fetch/$s_!1POe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6eb337fe-83a2-42c8-ba1a-f7e43fd9d9c6_1024x564.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>After doing that, use <a href="https://play.google.com/store/apps/details?id=io.oxylabs.proxymanager&amp;hl=en_IN&amp;gl=US">oxyproxy</a> to proxy to our burpsuite machine. and install the burpsuite ca certificate using <a href="https://play.google.com/store/apps/details?id=net.jolivier.cert.Importer&amp;hl=en_IN&amp;gl=US">this</a> app. After doing all of that just install the truecaller app on your vm and you are ready for some interception.</p><p>I used a fake mobile number from some sketch sms-recieve site to register for the app.</p><p>Also, If for some reason the verification fails and you are blocked for x amount of hours before retrying, just change the android-id and imei fom the bluestacks-tweaker's device section.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nPKN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83dc1996-3fb8-4088-becd-7b3e6ee26dfb_1013x342.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nPKN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83dc1996-3fb8-4088-becd-7b3e6ee26dfb_1013x342.png 424w, https://substackcdn.com/image/fetch/$s_!nPKN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83dc1996-3fb8-4088-becd-7b3e6ee26dfb_1013x342.png 848w, https://substackcdn.com/image/fetch/$s_!nPKN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83dc1996-3fb8-4088-becd-7b3e6ee26dfb_1013x342.png 1272w, https://substackcdn.com/image/fetch/$s_!nPKN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83dc1996-3fb8-4088-becd-7b3e6ee26dfb_1013x342.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nPKN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83dc1996-3fb8-4088-becd-7b3e6ee26dfb_1013x342.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/83dc1996-3fb8-4088-becd-7b3e6ee26dfb_1013x342.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!nPKN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83dc1996-3fb8-4088-becd-7b3e6ee26dfb_1013x342.png 424w, https://substackcdn.com/image/fetch/$s_!nPKN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83dc1996-3fb8-4088-becd-7b3e6ee26dfb_1013x342.png 848w, https://substackcdn.com/image/fetch/$s_!nPKN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83dc1996-3fb8-4088-becd-7b3e6ee26dfb_1013x342.png 1272w, https://substackcdn.com/image/fetch/$s_!nPKN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F83dc1996-3fb8-4088-becd-7b3e6ee26dfb_1013x342.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>This is the request that the app sends to log in a user -&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_zkQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea264f0-0260-40e4-b3ad-473b4ec92da2_466x879.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_zkQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea264f0-0260-40e4-b3ad-473b4ec92da2_466x879.png 424w, https://substackcdn.com/image/fetch/$s_!_zkQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea264f0-0260-40e4-b3ad-473b4ec92da2_466x879.png 848w, https://substackcdn.com/image/fetch/$s_!_zkQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea264f0-0260-40e4-b3ad-473b4ec92da2_466x879.png 1272w, https://substackcdn.com/image/fetch/$s_!_zkQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea264f0-0260-40e4-b3ad-473b4ec92da2_466x879.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_zkQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea264f0-0260-40e4-b3ad-473b4ec92da2_466x879.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3ea264f0-0260-40e4-b3ad-473b4ec92da2_466x879.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!_zkQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea264f0-0260-40e4-b3ad-473b4ec92da2_466x879.png 424w, https://substackcdn.com/image/fetch/$s_!_zkQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea264f0-0260-40e4-b3ad-473b4ec92da2_466x879.png 848w, https://substackcdn.com/image/fetch/$s_!_zkQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea264f0-0260-40e4-b3ad-473b4ec92da2_466x879.png 1272w, https://substackcdn.com/image/fetch/$s_!_zkQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ea264f0-0260-40e4-b3ad-473b4ec92da2_466x879.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Once successful it returns a session token which is valid till you logout of the app.</p><p>Now when you try to search for a number it generates this request -&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WkvM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc594dd4-7443-41a5-a776-cd71cfb812f9_623x301.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WkvM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc594dd4-7443-41a5-a776-cd71cfb812f9_623x301.png 424w, https://substackcdn.com/image/fetch/$s_!WkvM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc594dd4-7443-41a5-a776-cd71cfb812f9_623x301.png 848w, https://substackcdn.com/image/fetch/$s_!WkvM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc594dd4-7443-41a5-a776-cd71cfb812f9_623x301.png 1272w, https://substackcdn.com/image/fetch/$s_!WkvM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc594dd4-7443-41a5-a776-cd71cfb812f9_623x301.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WkvM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc594dd4-7443-41a5-a776-cd71cfb812f9_623x301.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bc594dd4-7443-41a5-a776-cd71cfb812f9_623x301.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!WkvM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc594dd4-7443-41a5-a776-cd71cfb812f9_623x301.png 424w, https://substackcdn.com/image/fetch/$s_!WkvM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc594dd4-7443-41a5-a776-cd71cfb812f9_623x301.png 848w, https://substackcdn.com/image/fetch/$s_!WkvM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc594dd4-7443-41a5-a776-cd71cfb812f9_623x301.png 1272w, https://substackcdn.com/image/fetch/$s_!WkvM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc594dd4-7443-41a5-a776-cd71cfb812f9_623x301.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>This returns a json response with plethora of information. Everything form public email addresses to profile pics to social media links.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!33T8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4bcbca48-16d6-4ae5-a7c3-8d6e3bf5bb48_560x737.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!33T8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4bcbca48-16d6-4ae5-a7c3-8d6e3bf5bb48_560x737.png 424w, https://substackcdn.com/image/fetch/$s_!33T8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4bcbca48-16d6-4ae5-a7c3-8d6e3bf5bb48_560x737.png 848w, https://substackcdn.com/image/fetch/$s_!33T8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4bcbca48-16d6-4ae5-a7c3-8d6e3bf5bb48_560x737.png 1272w, https://substackcdn.com/image/fetch/$s_!33T8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4bcbca48-16d6-4ae5-a7c3-8d6e3bf5bb48_560x737.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!33T8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4bcbca48-16d6-4ae5-a7c3-8d6e3bf5bb48_560x737.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4bcbca48-16d6-4ae5-a7c3-8d6e3bf5bb48_560x737.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!33T8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4bcbca48-16d6-4ae5-a7c3-8d6e3bf5bb48_560x737.png 424w, https://substackcdn.com/image/fetch/$s_!33T8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4bcbca48-16d6-4ae5-a7c3-8d6e3bf5bb48_560x737.png 848w, https://substackcdn.com/image/fetch/$s_!33T8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4bcbca48-16d6-4ae5-a7c3-8d6e3bf5bb48_560x737.png 1272w, https://substackcdn.com/image/fetch/$s_!33T8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4bcbca48-16d6-4ae5-a7c3-8d6e3bf5bb48_560x737.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Mission successful ! now all we gotta do is replicate this request and give it a better front end.</p><h3>Making a telegram bot out of it -&gt;</h3><p>Wrapping all of this up I replicated this request in go and used <a href="https://pkg.go.dev/github.com/go-telegram-bot-api/telegram-bot-api/v5">this</a> library to make a telegram bot out of it.</p><p>Here's the <a href="https://gist.github.com/SU1199/4d6860a748ad7cd2f45e95f019727559">github gist </a>for the same. Just replace the session token and bot auth token with your session token and bot token and you are good to go.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qhvN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddbf70c-656d-4343-b8a9-37dfc63b3f15_434x872.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qhvN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddbf70c-656d-4343-b8a9-37dfc63b3f15_434x872.png 424w, https://substackcdn.com/image/fetch/$s_!qhvN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddbf70c-656d-4343-b8a9-37dfc63b3f15_434x872.png 848w, https://substackcdn.com/image/fetch/$s_!qhvN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddbf70c-656d-4343-b8a9-37dfc63b3f15_434x872.png 1272w, https://substackcdn.com/image/fetch/$s_!qhvN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddbf70c-656d-4343-b8a9-37dfc63b3f15_434x872.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qhvN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddbf70c-656d-4343-b8a9-37dfc63b3f15_434x872.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2ddbf70c-656d-4343-b8a9-37dfc63b3f15_434x872.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!qhvN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddbf70c-656d-4343-b8a9-37dfc63b3f15_434x872.png 424w, https://substackcdn.com/image/fetch/$s_!qhvN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddbf70c-656d-4343-b8a9-37dfc63b3f15_434x872.png 848w, https://substackcdn.com/image/fetch/$s_!qhvN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddbf70c-656d-4343-b8a9-37dfc63b3f15_434x872.png 1272w, https://substackcdn.com/image/fetch/$s_!qhvN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ddbf70c-656d-4343-b8a9-37dfc63b3f15_434x872.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p><strong>Some notes -&gt;</strong></p><ul><li><p>Officially tc limits the free accounts to 100 lookups a month, but I was able to do much more than that. IDK how...</p></li><li><p>I am just marshalling the json responses into a string, and pretty-printing to the telegram chat {too lazy to make gigaton of structs and massaging the json o/p)</p></li></ul>]]></content:encoded></item><item><title><![CDATA[Making a facemash clone : using elo algorithm to rate two pictures against each other.]]></title><description><![CDATA[So after my last post I decided to put the data I scraped to some (im)practical use.]]></description><link>https://blog.danishjoshi.com/p/making-a-facemash-clone-using-elo-algorithm-to-rate-two-pictures-against-each-other</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/making-a-facemash-clone-using-elo-algorithm-to-rate-two-pictures-against-each-other</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Tue, 19 Apr 2022 18:02:14 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/98c72db9-4892-43ba-b93c-0c0891c41cb3_671x155.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So after my last post I decided to put the data I scraped to some (im)practical use.</p><p>Having watched David Fincher's fine fictional work. I put on &nbsp;Atticus Ross's and Trent Reznor's music on loop and wrote a facemash clone in a plan to get rusticated from my college.</p><h4>forking off main database -&gt;</h4><p>first off I forked out my postgres database using the following command in order to avaoid performing triple joins every time a picture gets rated.-&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IjIk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a99b63-3707-43d6-bbc7-ec61b380d133_671x155.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IjIk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a99b63-3707-43d6-bbc7-ec61b380d133_671x155.png 424w, https://substackcdn.com/image/fetch/$s_!IjIk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a99b63-3707-43d6-bbc7-ec61b380d133_671x155.png 848w, https://substackcdn.com/image/fetch/$s_!IjIk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a99b63-3707-43d6-bbc7-ec61b380d133_671x155.png 1272w, https://substackcdn.com/image/fetch/$s_!IjIk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a99b63-3707-43d6-bbc7-ec61b380d133_671x155.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IjIk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a99b63-3707-43d6-bbc7-ec61b380d133_671x155.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b7a99b63-3707-43d6-bbc7-ec61b380d133_671x155.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!IjIk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a99b63-3707-43d6-bbc7-ec61b380d133_671x155.png 424w, https://substackcdn.com/image/fetch/$s_!IjIk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a99b63-3707-43d6-bbc7-ec61b380d133_671x155.png 848w, https://substackcdn.com/image/fetch/$s_!IjIk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a99b63-3707-43d6-bbc7-ec61b380d133_671x155.png 1272w, https://substackcdn.com/image/fetch/$s_!IjIk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7a99b63-3707-43d6-bbc7-ec61b380d133_671x155.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>and added some more columns to it -&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!E7on!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F930cc669-f6d9-4581-8b61-140003fd264f_643x89.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!E7on!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F930cc669-f6d9-4581-8b61-140003fd264f_643x89.png 424w, https://substackcdn.com/image/fetch/$s_!E7on!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F930cc669-f6d9-4581-8b61-140003fd264f_643x89.png 848w, https://substackcdn.com/image/fetch/$s_!E7on!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F930cc669-f6d9-4581-8b61-140003fd264f_643x89.png 1272w, https://substackcdn.com/image/fetch/$s_!E7on!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F930cc669-f6d9-4581-8b61-140003fd264f_643x89.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!E7on!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F930cc669-f6d9-4581-8b61-140003fd264f_643x89.png" width="556" height="77" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/930cc669-f6d9-4581-8b61-140003fd264f_643x89.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:77,&quot;width&quot;:556,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!E7on!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F930cc669-f6d9-4581-8b61-140003fd264f_643x89.png 424w, https://substackcdn.com/image/fetch/$s_!E7on!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F930cc669-f6d9-4581-8b61-140003fd264f_643x89.png 848w, https://substackcdn.com/image/fetch/$s_!E7on!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F930cc669-f6d9-4581-8b61-140003fd264f_643x89.png 1272w, https://substackcdn.com/image/fetch/$s_!E7on!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F930cc669-f6d9-4581-8b61-140003fd264f_643x89.png 1456w" sizes="100vw"></picture><div></div></div></a></figure></div><h4>the algo -&gt;</h4><p>Giving in to following fincher's work I went with <a href="https://en.wikipedia.org/wiki/Elo_rating_system">elo rating system</a> instead of using <a href="https://en.wikipedia.org/wiki/Glicko_rating_system">better options</a>.</p><p>Here's how this algorithm calculates the probability of a player winning the match-up -&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UnEi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10ad574-d165-4963-b9e5-02b249f6dadb_290x84.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UnEi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10ad574-d165-4963-b9e5-02b249f6dadb_290x84.png 424w, https://substackcdn.com/image/fetch/$s_!UnEi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10ad574-d165-4963-b9e5-02b249f6dadb_290x84.png 848w, https://substackcdn.com/image/fetch/$s_!UnEi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10ad574-d165-4963-b9e5-02b249f6dadb_290x84.png 1272w, https://substackcdn.com/image/fetch/$s_!UnEi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10ad574-d165-4963-b9e5-02b249f6dadb_290x84.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UnEi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10ad574-d165-4963-b9e5-02b249f6dadb_290x84.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d10ad574-d165-4963-b9e5-02b249f6dadb_290x84.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!UnEi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10ad574-d165-4963-b9e5-02b249f6dadb_290x84.png 424w, https://substackcdn.com/image/fetch/$s_!UnEi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10ad574-d165-4963-b9e5-02b249f6dadb_290x84.png 848w, https://substackcdn.com/image/fetch/$s_!UnEi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10ad574-d165-4963-b9e5-02b249f6dadb_290x84.png 1272w, https://substackcdn.com/image/fetch/$s_!UnEi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd10ad574-d165-4963-b9e5-02b249f6dadb_290x84.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Here's the formula for final rating of the player which won -&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xoA2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14919468-6679-4af0-91bf-e287d98fc828_289x46.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xoA2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14919468-6679-4af0-91bf-e287d98fc828_289x46.png 424w, https://substackcdn.com/image/fetch/$s_!xoA2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14919468-6679-4af0-91bf-e287d98fc828_289x46.png 848w, https://substackcdn.com/image/fetch/$s_!xoA2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14919468-6679-4af0-91bf-e287d98fc828_289x46.png 1272w, https://substackcdn.com/image/fetch/$s_!xoA2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14919468-6679-4af0-91bf-e287d98fc828_289x46.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xoA2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14919468-6679-4af0-91bf-e287d98fc828_289x46.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/14919468-6679-4af0-91bf-e287d98fc828_289x46.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!xoA2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14919468-6679-4af0-91bf-e287d98fc828_289x46.png 424w, https://substackcdn.com/image/fetch/$s_!xoA2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14919468-6679-4af0-91bf-e287d98fc828_289x46.png 848w, https://substackcdn.com/image/fetch/$s_!xoA2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14919468-6679-4af0-91bf-e287d98fc828_289x46.png 1272w, https://substackcdn.com/image/fetch/$s_!xoA2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F14919468-6679-4af0-91bf-e287d98fc828_289x46.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Here's my golang implementation -&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BlCY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6ae4721-b96c-4d45-bcd6-4f9ee8d944ea_876x263.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BlCY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6ae4721-b96c-4d45-bcd6-4f9ee8d944ea_876x263.png 424w, https://substackcdn.com/image/fetch/$s_!BlCY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6ae4721-b96c-4d45-bcd6-4f9ee8d944ea_876x263.png 848w, https://substackcdn.com/image/fetch/$s_!BlCY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6ae4721-b96c-4d45-bcd6-4f9ee8d944ea_876x263.png 1272w, https://substackcdn.com/image/fetch/$s_!BlCY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6ae4721-b96c-4d45-bcd6-4f9ee8d944ea_876x263.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!BlCY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6ae4721-b96c-4d45-bcd6-4f9ee8d944ea_876x263.png" width="598" height="179" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d6ae4721-b96c-4d45-bcd6-4f9ee8d944ea_876x263.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:179,&quot;width&quot;:598,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!BlCY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6ae4721-b96c-4d45-bcd6-4f9ee8d944ea_876x263.png 424w, https://substackcdn.com/image/fetch/$s_!BlCY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6ae4721-b96c-4d45-bcd6-4f9ee8d944ea_876x263.png 848w, https://substackcdn.com/image/fetch/$s_!BlCY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6ae4721-b96c-4d45-bcd6-4f9ee8d944ea_876x263.png 1272w, https://substackcdn.com/image/fetch/$s_!BlCY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6ae4721-b96c-4d45-bcd6-4f9ee8d944ea_876x263.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>i am using this function to test the various values of k,d and s to see, after how many number of losses the score of a player went negative.Then adjusted the base rating accordingly to a reasonable 200-ish match-ups till negative.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Pf59!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fede944-d03a-4a6a-9d69-964fbc652e0d_315x206.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Pf59!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fede944-d03a-4a6a-9d69-964fbc652e0d_315x206.png 424w, https://substackcdn.com/image/fetch/$s_!Pf59!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fede944-d03a-4a6a-9d69-964fbc652e0d_315x206.png 848w, https://substackcdn.com/image/fetch/$s_!Pf59!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fede944-d03a-4a6a-9d69-964fbc652e0d_315x206.png 1272w, https://substackcdn.com/image/fetch/$s_!Pf59!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fede944-d03a-4a6a-9d69-964fbc652e0d_315x206.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Pf59!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fede944-d03a-4a6a-9d69-964fbc652e0d_315x206.png" width="263" height="172" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3fede944-d03a-4a6a-9d69-964fbc652e0d_315x206.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:172,&quot;width&quot;:263,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Pf59!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fede944-d03a-4a6a-9d69-964fbc652e0d_315x206.png 424w, https://substackcdn.com/image/fetch/$s_!Pf59!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fede944-d03a-4a6a-9d69-964fbc652e0d_315x206.png 848w, https://substackcdn.com/image/fetch/$s_!Pf59!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fede944-d03a-4a6a-9d69-964fbc652e0d_315x206.png 1272w, https://substackcdn.com/image/fetch/$s_!Pf59!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3fede944-d03a-4a6a-9d69-964fbc652e0d_315x206.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h4>making the website :</h4><p>onto the worst part. making the front end. Opting the laziest way out, I used the example code from <a href="https://mdbootstrap.com/">material bootstrap library</a>, modified it and used go's inbuilt templating engine to make the rankings and profile page.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4Reg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff91c38c-a81e-464f-81fe-53b4c10eed47_1024x309.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4Reg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff91c38c-a81e-464f-81fe-53b4c10eed47_1024x309.png 424w, https://substackcdn.com/image/fetch/$s_!4Reg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff91c38c-a81e-464f-81fe-53b4c10eed47_1024x309.png 848w, https://substackcdn.com/image/fetch/$s_!4Reg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff91c38c-a81e-464f-81fe-53b4c10eed47_1024x309.png 1272w, https://substackcdn.com/image/fetch/$s_!4Reg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff91c38c-a81e-464f-81fe-53b4c10eed47_1024x309.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4Reg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff91c38c-a81e-464f-81fe-53b4c10eed47_1024x309.png" width="738" height="222" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ff91c38c-a81e-464f-81fe-53b4c10eed47_1024x309.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:222,&quot;width&quot;:738,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!4Reg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff91c38c-a81e-464f-81fe-53b4c10eed47_1024x309.png 424w, https://substackcdn.com/image/fetch/$s_!4Reg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff91c38c-a81e-464f-81fe-53b4c10eed47_1024x309.png 848w, https://substackcdn.com/image/fetch/$s_!4Reg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff91c38c-a81e-464f-81fe-53b4c10eed47_1024x309.png 1272w, https://substackcdn.com/image/fetch/$s_!4Reg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff91c38c-a81e-464f-81fe-53b4c10eed47_1024x309.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h4>wrangling database :</h4><p>using the following sql query I fetched two random images with their enums from the DB to hydrate the page every-time it was refreshed.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6lOr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3066e2a-3aed-44cb-b8f2-26a766c6e196_613x40.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6lOr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3066e2a-3aed-44cb-b8f2-26a766c6e196_613x40.png 424w, https://substackcdn.com/image/fetch/$s_!6lOr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3066e2a-3aed-44cb-b8f2-26a766c6e196_613x40.png 848w, https://substackcdn.com/image/fetch/$s_!6lOr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3066e2a-3aed-44cb-b8f2-26a766c6e196_613x40.png 1272w, https://substackcdn.com/image/fetch/$s_!6lOr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3066e2a-3aed-44cb-b8f2-26a766c6e196_613x40.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6lOr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3066e2a-3aed-44cb-b8f2-26a766c6e196_613x40.png" width="613" height="40" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c3066e2a-3aed-44cb-b8f2-26a766c6e196_613x40.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:40,&quot;width&quot;:613,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!6lOr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3066e2a-3aed-44cb-b8f2-26a766c6e196_613x40.png 424w, https://substackcdn.com/image/fetch/$s_!6lOr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3066e2a-3aed-44cb-b8f2-26a766c6e196_613x40.png 848w, https://substackcdn.com/image/fetch/$s_!6lOr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3066e2a-3aed-44cb-b8f2-26a766c6e196_613x40.png 1272w, https://substackcdn.com/image/fetch/$s_!6lOr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc3066e2a-3aed-44cb-b8f2-26a766c6e196_613x40.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>and this query to get the top 15 for the rankings page -&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8ycM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F599d8647-1c49-4a4d-8aba-d0208ffbf062_608x31.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8ycM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F599d8647-1c49-4a4d-8aba-d0208ffbf062_608x31.png 424w, https://substackcdn.com/image/fetch/$s_!8ycM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F599d8647-1c49-4a4d-8aba-d0208ffbf062_608x31.png 848w, https://substackcdn.com/image/fetch/$s_!8ycM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F599d8647-1c49-4a4d-8aba-d0208ffbf062_608x31.png 1272w, https://substackcdn.com/image/fetch/$s_!8ycM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F599d8647-1c49-4a4d-8aba-d0208ffbf062_608x31.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8ycM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F599d8647-1c49-4a4d-8aba-d0208ffbf062_608x31.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/599d8647-1c49-4a4d-8aba-d0208ffbf062_608x31.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!8ycM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F599d8647-1c49-4a4d-8aba-d0208ffbf062_608x31.png 424w, https://substackcdn.com/image/fetch/$s_!8ycM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F599d8647-1c49-4a4d-8aba-d0208ffbf062_608x31.png 848w, https://substackcdn.com/image/fetch/$s_!8ycM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F599d8647-1c49-4a4d-8aba-d0208ffbf062_608x31.png 1272w, https://substackcdn.com/image/fetch/$s_!8ycM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F599d8647-1c49-4a4d-8aba-d0208ffbf062_608x31.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>after each vote the <strong>/vote</strong> endpoint is called with winner and looser enums which updates the database with the new ranking of both winners and losers according to the elo algorithm. I'll need to add rate limiting to prevent abuse if I ever decide to release this app to a wider audience (which is never gonna happen).</p><h2>Finished result -&gt;</h2><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;0c6bda49-52dc-4861-91dc-3a1d63db1bd8&quot;,&quot;duration&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Scraping student data from a library database using worker pools in go.]]></title><description><![CDATA[So, I was playing around with a college's library site when I noticed they were using the default creds for their library management software.]]></description><link>https://blog.danishjoshi.com/p/scraping-a-library-database-using-worker-pools-in-go</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/scraping-a-library-database-using-worker-pools-in-go</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Tue, 19 Apr 2022 12:23:48 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/95915775-3860-42ea-a5c0-383af9bbf0e3_1024x438.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So, I was playing around with a college's<a href="https://library.thapar.edu/"> library site</a> when I noticed they were using the default creds for their library management software. This leaves the data of mode than 8000 students vulnerable to scraping using their default creds or by using sql injection on the librarian console (yes, people still don't use prepared statement in commercial software).</p><p>So I decided to to just that. Scraping data of current (and past) students studying in the college. All in good faith (obviously).</p><p>Here was the plan -&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WzBI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0809dd4-c456-43d3-89ef-521cc421a11f_1024x473.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WzBI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0809dd4-c456-43d3-89ef-521cc421a11f_1024x473.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WzBI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0809dd4-c456-43d3-89ef-521cc421a11f_1024x473.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WzBI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0809dd4-c456-43d3-89ef-521cc421a11f_1024x473.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WzBI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0809dd4-c456-43d3-89ef-521cc421a11f_1024x473.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WzBI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0809dd4-c456-43d3-89ef-521cc421a11f_1024x473.jpeg" width="565" height="261" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b0809dd4-c456-43d3-89ef-521cc421a11f_1024x473.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:261,&quot;width&quot;:565,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!WzBI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0809dd4-c456-43d3-89ef-521cc421a11f_1024x473.jpeg 424w, https://substackcdn.com/image/fetch/$s_!WzBI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0809dd4-c456-43d3-89ef-521cc421a11f_1024x473.jpeg 848w, https://substackcdn.com/image/fetch/$s_!WzBI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0809dd4-c456-43d3-89ef-521cc421a11f_1024x473.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!WzBI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0809dd4-c456-43d3-89ef-521cc421a11f_1024x473.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>generating enums :</h2><p>I don't know what the complete roll numbers of all the students are. But I do know what first 4 digits represent.</p><p>If I could brute-force the rest of the 5 digits without breaking or alerting the library servers I could hypothetically scan for the successful hits and scrape the data.</p><p>So I wrote this program that takes the year of students as input and generates all the permutations of the roll numbers. Then stores it in a Postgres table with the following fields.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZuTC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c590359-99ce-4a62-940e-4665e2456027_1024x438.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZuTC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c590359-99ce-4a62-940e-4665e2456027_1024x438.png 424w, https://substackcdn.com/image/fetch/$s_!ZuTC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c590359-99ce-4a62-940e-4665e2456027_1024x438.png 848w, https://substackcdn.com/image/fetch/$s_!ZuTC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c590359-99ce-4a62-940e-4665e2456027_1024x438.png 1272w, https://substackcdn.com/image/fetch/$s_!ZuTC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c590359-99ce-4a62-940e-4665e2456027_1024x438.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZuTC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c590359-99ce-4a62-940e-4665e2456027_1024x438.png" width="842" height="360" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5c590359-99ce-4a62-940e-4665e2456027_1024x438.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:360,&quot;width&quot;:842,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!ZuTC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c590359-99ce-4a62-940e-4665e2456027_1024x438.png 424w, https://substackcdn.com/image/fetch/$s_!ZuTC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c590359-99ce-4a62-940e-4665e2456027_1024x438.png 848w, https://substackcdn.com/image/fetch/$s_!ZuTC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c590359-99ce-4a62-940e-4665e2456027_1024x438.png 1272w, https://substackcdn.com/image/fetch/$s_!ZuTC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c590359-99ce-4a62-940e-4665e2456027_1024x438.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!elOJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F931637eb-95f1-49b8-9d84-20ca82026764_828x395.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!elOJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F931637eb-95f1-49b8-9d84-20ca82026764_828x395.png 424w, https://substackcdn.com/image/fetch/$s_!elOJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F931637eb-95f1-49b8-9d84-20ca82026764_828x395.png 848w, https://substackcdn.com/image/fetch/$s_!elOJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F931637eb-95f1-49b8-9d84-20ca82026764_828x395.png 1272w, https://substackcdn.com/image/fetch/$s_!elOJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F931637eb-95f1-49b8-9d84-20ca82026764_828x395.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!elOJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F931637eb-95f1-49b8-9d84-20ca82026764_828x395.png" width="487" height="232" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/931637eb-95f1-49b8-9d84-20ca82026764_828x395.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:232,&quot;width&quot;:487,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!elOJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F931637eb-95f1-49b8-9d84-20ca82026764_828x395.png 424w, https://substackcdn.com/image/fetch/$s_!elOJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F931637eb-95f1-49b8-9d84-20ca82026764_828x395.png 848w, https://substackcdn.com/image/fetch/$s_!elOJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F931637eb-95f1-49b8-9d84-20ca82026764_828x395.png 1272w, https://substackcdn.com/image/fetch/$s_!elOJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F931637eb-95f1-49b8-9d84-20ca82026764_828x395.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eJFH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f5a289-65d0-454f-8e3c-0af5c4f8c1b9_299x184.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eJFH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f5a289-65d0-454f-8e3c-0af5c4f8c1b9_299x184.png 424w, https://substackcdn.com/image/fetch/$s_!eJFH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f5a289-65d0-454f-8e3c-0af5c4f8c1b9_299x184.png 848w, https://substackcdn.com/image/fetch/$s_!eJFH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f5a289-65d0-454f-8e3c-0af5c4f8c1b9_299x184.png 1272w, https://substackcdn.com/image/fetch/$s_!eJFH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f5a289-65d0-454f-8e3c-0af5c4f8c1b9_299x184.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eJFH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f5a289-65d0-454f-8e3c-0af5c4f8c1b9_299x184.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/77f5a289-65d0-454f-8e3c-0af5c4f8c1b9_299x184.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!eJFH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f5a289-65d0-454f-8e3c-0af5c4f8c1b9_299x184.png 424w, https://substackcdn.com/image/fetch/$s_!eJFH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f5a289-65d0-454f-8e3c-0af5c4f8c1b9_299x184.png 848w, https://substackcdn.com/image/fetch/$s_!eJFH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f5a289-65d0-454f-8e3c-0af5c4f8c1b9_299x184.png 1272w, https://substackcdn.com/image/fetch/$s_!eJFH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77f5a289-65d0-454f-8e3c-0af5c4f8c1b9_299x184.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>We'll use this table as a reference of the successful hits and the the enums not yet touched.</p><h2>reverse engineering the login flow :</h2><p>Next logical step is figuring out the api endpoints and see how server authenticates the requests one logged in.</p><p>In this case one you submit the used id and password, it called a perl script which sends back session token as cookie header if you were authenticated successfully.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pmQR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ec69652-58be-4468-91d8-85b8e94a8b62_448x288.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pmQR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ec69652-58be-4468-91d8-85b8e94a8b62_448x288.png 424w, https://substackcdn.com/image/fetch/$s_!pmQR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ec69652-58be-4468-91d8-85b8e94a8b62_448x288.png 848w, https://substackcdn.com/image/fetch/$s_!pmQR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ec69652-58be-4468-91d8-85b8e94a8b62_448x288.png 1272w, https://substackcdn.com/image/fetch/$s_!pmQR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ec69652-58be-4468-91d8-85b8e94a8b62_448x288.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pmQR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ec69652-58be-4468-91d8-85b8e94a8b62_448x288.png" width="362" height="233" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4ec69652-58be-4468-91d8-85b8e94a8b62_448x288.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:233,&quot;width&quot;:362,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!pmQR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ec69652-58be-4468-91d8-85b8e94a8b62_448x288.png 424w, https://substackcdn.com/image/fetch/$s_!pmQR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ec69652-58be-4468-91d8-85b8e94a8b62_448x288.png 848w, https://substackcdn.com/image/fetch/$s_!pmQR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ec69652-58be-4468-91d8-85b8e94a8b62_448x288.png 1272w, https://substackcdn.com/image/fetch/$s_!pmQR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4ec69652-58be-4468-91d8-85b8e94a8b62_448x288.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>The gotcha in this login flow is that the server still sends a 200-Ok request with with a session cookie even if you weren't logged successfully.</p><p>So to figure out if the uid-password combo was correct, I had to see what was inside the request, parse it and see if I was logged in successfully.</p><p>This snippet of code does just that. It scans the 45 character of the response data and checks of it a particular character. If yes, then classifies this as a successful hit and stores the session token.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QMhW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24b71dd5-f1f4-496d-9624-e6ca6886c2cb_470x195.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QMhW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24b71dd5-f1f4-496d-9624-e6ca6886c2cb_470x195.png 424w, https://substackcdn.com/image/fetch/$s_!QMhW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24b71dd5-f1f4-496d-9624-e6ca6886c2cb_470x195.png 848w, https://substackcdn.com/image/fetch/$s_!QMhW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24b71dd5-f1f4-496d-9624-e6ca6886c2cb_470x195.png 1272w, https://substackcdn.com/image/fetch/$s_!QMhW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24b71dd5-f1f4-496d-9624-e6ca6886c2cb_470x195.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QMhW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24b71dd5-f1f4-496d-9624-e6ca6886c2cb_470x195.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/24b71dd5-f1f4-496d-9624-e6ca6886c2cb_470x195.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!QMhW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24b71dd5-f1f4-496d-9624-e6ca6886c2cb_470x195.png 424w, https://substackcdn.com/image/fetch/$s_!QMhW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24b71dd5-f1f4-496d-9624-e6ca6886c2cb_470x195.png 848w, https://substackcdn.com/image/fetch/$s_!QMhW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24b71dd5-f1f4-496d-9624-e6ca6886c2cb_470x195.png 1272w, https://substackcdn.com/image/fetch/$s_!QMhW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24b71dd5-f1f4-496d-9624-e6ca6886c2cb_470x195.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h2>sending 500k request's to the server concurrently without raising any red flags :</h2><p>the problem with using brute-force to find out successful enum hits is that every request take at least 1.4 seconds to complete (even on local network) and 2+ seconds if it is a successful hit. This is server side latency and there;s nothing I can do about it.</p><p>I however can uses go's robust inbuilt concurrency model to send a lot of requests concurrently . This presents the risk of dosing the library's server and getting my IP blocked.</p><p>The solution of all of this is using a concurrency pattern called worker pools. Worker pools uses go's inbuild channels to build a jobs queue from which my (limited) pool of goroutines can concurrently fetch jobs to do.</p><p><a href="https://www.youtube.com/watch?v=LvgVSSpwND8">This video </a>explains all of this and more pretty lucidly.</p><p>This snippet of code makes two separate channels, creates n number of go routines and then fills the jobs channels with data it fetched from the permutation's db. At last it waits for the workers to finish their jobs by listening to the results channels.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NUOu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b003117-5b16-4377-b72a-2989819a5a2f_498x465.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NUOu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b003117-5b16-4377-b72a-2989819a5a2f_498x465.png 424w, https://substackcdn.com/image/fetch/$s_!NUOu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b003117-5b16-4377-b72a-2989819a5a2f_498x465.png 848w, https://substackcdn.com/image/fetch/$s_!NUOu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b003117-5b16-4377-b72a-2989819a5a2f_498x465.png 1272w, https://substackcdn.com/image/fetch/$s_!NUOu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b003117-5b16-4377-b72a-2989819a5a2f_498x465.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NUOu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b003117-5b16-4377-b72a-2989819a5a2f_498x465.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9b003117-5b16-4377-b72a-2989819a5a2f_498x465.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!NUOu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b003117-5b16-4377-b72a-2989819a5a2f_498x465.png 424w, https://substackcdn.com/image/fetch/$s_!NUOu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b003117-5b16-4377-b72a-2989819a5a2f_498x465.png 848w, https://substackcdn.com/image/fetch/$s_!NUOu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b003117-5b16-4377-b72a-2989819a5a2f_498x465.png 1272w, https://substackcdn.com/image/fetch/$s_!NUOu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b003117-5b16-4377-b72a-2989819a5a2f_498x465.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h2>parsing all the data from the profiles page :</h2><p>each student has a my profile page in which they can change their personal details all of this comes pre-hydrated as an HTML page and NOT as a json response which means I had to write my own parser.</p><p>Go's <a href="https://pkg.go.dev/golang.org/x/net/html">inbuilt </a>html parsing engine is way too complicated for my wrap my head around in the time-frame of this project. So I went with an awesome library called <a href="https://github.com/PuerkitoBio/goquery">goquery</a> which implements jquery in native go and is used by other major scraping libs like colly.</p><p>The parser I wrote is way too ugly and and duck-taped together to be discussed in this post but ye can have a look at it <a href="https://github.com/SU1199/nalanda/blob/main/parser/parser.go">here.</a></p><h3>handling images :</h3><p>to scrape images I wrote a separate module which requested the png (&lt;60kb) form the server, converted it into base64 url string compatible with chrome and chucked it into my database.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6ki8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1433f22e-af40-43eb-a832-598fc1d89ac8_1024x587.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6ki8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1433f22e-af40-43eb-a832-598fc1d89ac8_1024x587.png 424w, https://substackcdn.com/image/fetch/$s_!6ki8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1433f22e-af40-43eb-a832-598fc1d89ac8_1024x587.png 848w, https://substackcdn.com/image/fetch/$s_!6ki8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1433f22e-af40-43eb-a832-598fc1d89ac8_1024x587.png 1272w, https://substackcdn.com/image/fetch/$s_!6ki8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1433f22e-af40-43eb-a832-598fc1d89ac8_1024x587.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6ki8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1433f22e-af40-43eb-a832-598fc1d89ac8_1024x587.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1433f22e-af40-43eb-a832-598fc1d89ac8_1024x587.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!6ki8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1433f22e-af40-43eb-a832-598fc1d89ac8_1024x587.png 424w, https://substackcdn.com/image/fetch/$s_!6ki8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1433f22e-af40-43eb-a832-598fc1d89ac8_1024x587.png 848w, https://substackcdn.com/image/fetch/$s_!6ki8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1433f22e-af40-43eb-a832-598fc1d89ac8_1024x587.png 1272w, https://substackcdn.com/image/fetch/$s_!6ki8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1433f22e-af40-43eb-a832-598fc1d89ac8_1024x587.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h2>Other notes :</h2><p>for my database I went with postgres as its awesome and I had a some experience writing highly concurrent go apps with it. It does not disappoint or fuck-up ever unlike its nosql counterparts.</p><p>I was able to run ~50 gophers concurrently without experiencing some sort of throttling.</p><p>Modularising the apps smary can save you and others tonns of headches and makes the overall experice of working on an project more fun.</p><p>I still don't how how to write good tests form my code.</p><h2>final result :</h2><p>this was the final size of the db after hitting the library server 500k times scraping data of more than than 8000 students.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JjFC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c3fc705-7407-40a1-923d-9644de7165a8_1024x124.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JjFC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c3fc705-7407-40a1-923d-9644de7165a8_1024x124.png 424w, https://substackcdn.com/image/fetch/$s_!JjFC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c3fc705-7407-40a1-923d-9644de7165a8_1024x124.png 848w, https://substackcdn.com/image/fetch/$s_!JjFC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c3fc705-7407-40a1-923d-9644de7165a8_1024x124.png 1272w, https://substackcdn.com/image/fetch/$s_!JjFC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c3fc705-7407-40a1-923d-9644de7165a8_1024x124.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JjFC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c3fc705-7407-40a1-923d-9644de7165a8_1024x124.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6c3fc705-7407-40a1-923d-9644de7165a8_1024x124.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!JjFC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c3fc705-7407-40a1-923d-9644de7165a8_1024x124.png 424w, https://substackcdn.com/image/fetch/$s_!JjFC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c3fc705-7407-40a1-923d-9644de7165a8_1024x124.png 848w, https://substackcdn.com/image/fetch/$s_!JjFC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c3fc705-7407-40a1-923d-9644de7165a8_1024x124.png 1272w, https://substackcdn.com/image/fetch/$s_!JjFC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c3fc705-7407-40a1-923d-9644de7165a8_1024x124.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ih2l!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656ffbaf-f8c6-4bd5-bf2f-80c06d66b5f4_450x330.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ih2l!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656ffbaf-f8c6-4bd5-bf2f-80c06d66b5f4_450x330.png 424w, https://substackcdn.com/image/fetch/$s_!Ih2l!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656ffbaf-f8c6-4bd5-bf2f-80c06d66b5f4_450x330.png 848w, https://substackcdn.com/image/fetch/$s_!Ih2l!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656ffbaf-f8c6-4bd5-bf2f-80c06d66b5f4_450x330.png 1272w, https://substackcdn.com/image/fetch/$s_!Ih2l!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656ffbaf-f8c6-4bd5-bf2f-80c06d66b5f4_450x330.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ih2l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656ffbaf-f8c6-4bd5-bf2f-80c06d66b5f4_450x330.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/656ffbaf-f8c6-4bd5-bf2f-80c06d66b5f4_450x330.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Ih2l!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656ffbaf-f8c6-4bd5-bf2f-80c06d66b5f4_450x330.png 424w, https://substackcdn.com/image/fetch/$s_!Ih2l!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656ffbaf-f8c6-4bd5-bf2f-80c06d66b5f4_450x330.png 848w, https://substackcdn.com/image/fetch/$s_!Ih2l!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656ffbaf-f8c6-4bd5-bf2f-80c06d66b5f4_450x330.png 1272w, https://substackcdn.com/image/fetch/$s_!Ih2l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F656ffbaf-f8c6-4bd5-bf2f-80c06d66b5f4_450x330.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wpq_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6c01429-c1a9-4e7f-b960-81543b972ef4_1024x538.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wpq_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6c01429-c1a9-4e7f-b960-81543b972ef4_1024x538.png 424w, https://substackcdn.com/image/fetch/$s_!wpq_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6c01429-c1a9-4e7f-b960-81543b972ef4_1024x538.png 848w, https://substackcdn.com/image/fetch/$s_!wpq_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6c01429-c1a9-4e7f-b960-81543b972ef4_1024x538.png 1272w, https://substackcdn.com/image/fetch/$s_!wpq_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6c01429-c1a9-4e7f-b960-81543b972ef4_1024x538.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wpq_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6c01429-c1a9-4e7f-b960-81543b972ef4_1024x538.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a6c01429-c1a9-4e7f-b960-81543b972ef4_1024x538.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;hnGhskfyYDAAAAABJRU5ErkJggg== (1814&#215;953)&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="hnGhskfyYDAAAAABJRU5ErkJggg== (1814&#215;953)" title="hnGhskfyYDAAAAABJRU5ErkJggg== (1814&#215;953)" srcset="https://substackcdn.com/image/fetch/$s_!wpq_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6c01429-c1a9-4e7f-b960-81543b972ef4_1024x538.png 424w, https://substackcdn.com/image/fetch/$s_!wpq_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6c01429-c1a9-4e7f-b960-81543b972ef4_1024x538.png 848w, https://substackcdn.com/image/fetch/$s_!wpq_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6c01429-c1a9-4e7f-b960-81543b972ef4_1024x538.png 1272w, https://substackcdn.com/image/fetch/$s_!wpq_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa6c01429-c1a9-4e7f-b960-81543b972ef4_1024x538.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><a href="https://github.com/SU1199/nalanda">This project's source is open on my github.</a></p>]]></content:encoded></item><item><title><![CDATA[Building a "serverless™" pastebin using cloudflare workers + kv with auth and sharing.]]></title><description><![CDATA[This pastebin will be an update to my previous pastebin project which has become the single most used self-made tool since I've built...]]></description><link>https://blog.danishjoshi.com/p/building-a-serverless-pastebin-using-cloudflare-workers-kv-with-auth-and-sharing</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/building-a-serverless-pastebin-using-cloudflare-workers-kv-with-auth-and-sharing</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Thu, 24 Feb 2022 22:04:10 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/07bdb625-5533-4c71-86bd-46ff2d02f023_915x438.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This pastebin will be an update to my <a href="http://blog.danishjoshi.com/creating-a-private-pastebin-with-client-side-encryption/">previous pastebin project</a> which has become the single most used self-made tool since I've built... despite being super insecure and janky. It has made sharing data between my college's lab systems and my mobile devices a breeze. So I decided to give it an update. This version has these features -&gt;</p><ul><li><p>Authentication and authorisation using jwt tokens.</p></li><li><p>Customizable sessions where I can set a particular time for jwt token expiry (one of my labs had restrictions on opening incognito tabs so this removes the need to open incognito again)</p></li><li><p>CRD -&gt; I purposefully removed update feature for better consistency when sharing (I'll get to this point later).</p></li><li><p>CORS support and CSRF protections.</p></li><li><p>micro (&lt;15mb) file storage solution.</p></li></ul><p>I decided to go with cloudflare workers as I've used their other services before and I really like the company. Also I wanted to see what can workers KV actually so I've tried incorporating all of its features into it.</p><p>Building a cf project is pretty simple, you just need to install <a href="https://developers.cloudflare.com/workers/cli-wrangler">wrangler cli </a>and login into your cf account. The cli will guide you through the rest of the process.</p><p>It will generate a project structure kind of like this -&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!V-dP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04b2e413-ca9d-4cef-92bb-43e151c7c2b9_248x469.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!V-dP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04b2e413-ca9d-4cef-92bb-43e151c7c2b9_248x469.png 424w, https://substackcdn.com/image/fetch/$s_!V-dP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04b2e413-ca9d-4cef-92bb-43e151c7c2b9_248x469.png 848w, https://substackcdn.com/image/fetch/$s_!V-dP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04b2e413-ca9d-4cef-92bb-43e151c7c2b9_248x469.png 1272w, https://substackcdn.com/image/fetch/$s_!V-dP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04b2e413-ca9d-4cef-92bb-43e151c7c2b9_248x469.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!V-dP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04b2e413-ca9d-4cef-92bb-43e151c7c2b9_248x469.png" width="200" height="378" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/04b2e413-ca9d-4cef-92bb-43e151c7c2b9_248x469.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:378,&quot;width&quot;:200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!V-dP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04b2e413-ca9d-4cef-92bb-43e151c7c2b9_248x469.png 424w, https://substackcdn.com/image/fetch/$s_!V-dP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04b2e413-ca9d-4cef-92bb-43e151c7c2b9_248x469.png 848w, https://substackcdn.com/image/fetch/$s_!V-dP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04b2e413-ca9d-4cef-92bb-43e151c7c2b9_248x469.png 1272w, https://substackcdn.com/image/fetch/$s_!V-dP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04b2e413-ca9d-4cef-92bb-43e151c7c2b9_248x469.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The main worker script will reside in the index.js file and the worker configurations will reside in the wrangler.toml file.</p><p>My tooling file looks like this -&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1zLK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F257f49e9-6c23-41e2-bfe4-bff95449d0a3_915x438.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1zLK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F257f49e9-6c23-41e2-bfe4-bff95449d0a3_915x438.png 424w, https://substackcdn.com/image/fetch/$s_!1zLK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F257f49e9-6c23-41e2-bfe4-bff95449d0a3_915x438.png 848w, https://substackcdn.com/image/fetch/$s_!1zLK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F257f49e9-6c23-41e2-bfe4-bff95449d0a3_915x438.png 1272w, https://substackcdn.com/image/fetch/$s_!1zLK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F257f49e9-6c23-41e2-bfe4-bff95449d0a3_915x438.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1zLK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F257f49e9-6c23-41e2-bfe4-bff95449d0a3_915x438.png" width="711" height="340" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/257f49e9-6c23-41e2-bfe4-bff95449d0a3_915x438.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:340,&quot;width&quot;:711,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!1zLK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F257f49e9-6c23-41e2-bfe4-bff95449d0a3_915x438.png 424w, https://substackcdn.com/image/fetch/$s_!1zLK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F257f49e9-6c23-41e2-bfe4-bff95449d0a3_915x438.png 848w, https://substackcdn.com/image/fetch/$s_!1zLK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F257f49e9-6c23-41e2-bfe4-bff95449d0a3_915x438.png 1272w, https://substackcdn.com/image/fetch/$s_!1zLK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F257f49e9-6c23-41e2-bfe4-bff95449d0a3_915x438.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here name is the name of project and type is webpack. cf supports(officially) building workers in rust(compiled using wasm) , pure javascript or using a bundler like webpack. Do note not all node compatible package are cross compatible with cloudflare, especially the once using node's standard library. Because unlike other server-less solutions workers run on bare isolated v8 instances instead of spinning up a node container every time a request comes through. This effectively eliminates the cold start problem I've faced with gcp .</p><p>kv namepaces variable hold our namespaces ids and their aliases along with the preview id's reuired when running the workers dev server.</p><p>The [vars] are the global environment variables which get stored in the cloudflare's secret store. I have my main passkey for the pastebin and my jwt signature stored here. It recommended to use a thrid paarty secrets manager if you are deploying it in production tho.</p><p>You can install the npm packages using the standard npm commands and then use wrangler build command to build the project.</p><p>wrangler dev -&gt; spins up a test server for locally testing the workers</p><p>wrangler publish -&gt; builds and publishes the workers on the cf web.</p><p>So lets look at our index.js file . Interestingly most of it (minus cors) was written in just under 4 hours and its barely 150 LOC for the WHOLE api !</p><pre><code>import { Router } from 'itty-router'
const jwt = require('@tsndr/cloudflare-worker-jwt')

const router = Router()

//Csrf Headers -&gt; change before prod
const myHeaders = new Headers();
myHeaders.set("Access-Control-Allow-Origin", '*');
myHeaders.set("Access-Control-Allow-Headers", '*');
myHeaders.set("Access-Control-Allow-Methods", "GET,HEAD,POST,OPTIONS");
myHeaders.set("Access-Control-Max-Age", "86400");
// myHeaders.set("Access-Control-Allow-Credentials", "true")


//Root Page
router.get("/", async () =&gt; {
  myHeaders.set("content-type", "text/html")
  return new Response(html, { status: 200, headers: myHeaders })
})

//Cookie Parser
function getToken(request) {
  var list = {};
  const cookieHeader = request.headers.get("Cookie")
  if (!cookieHeader) return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" //bandaid plz fix before prod
  cookieHeader.split(';')
    .map(v =&gt; v.split('='))
    .reduce((acc, v) =&gt; {
      acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim());
      list = acc
    }, {});
  const token = list["passkey"]
  return token
}

//Pass all the csrf preflight -&gt; chage before prod
router.options("*", async () =&gt; {
  return new Response("OK", { status: 200, headers: myHeaders })
})

//Jwt generator
router.get("/authgen", async request =&gt; {
  const pass = request.headers.get("passkey")
  const exp = request.headers.get("expires")
  if (pass == passkey) {
    const token = await jwt.sign({
      name: 'doom slayer',
      email: 'okdoomer@lol.com',
      exp: Math.floor(Date.now() / 1000) + (parseFloat(exp) * (60 * 60)) // Expires: Now + Xh
    }, signature)
    myHeaders.set('Set-Cookie', `passkey=${token}; Path=/ ;Max-Age=${(parseFloat(exp) * (60 * 60))}; Secure; HttpOnly;`)//add  SameSite=None to cookie props for cors "stuff"
    return new Response(token, { status: 200, headers: myHeaders })
  }
  else {
    return new Response("401, wrong passkey", { status: 401, headers: myHeaders })
  }
})

//view a single post
router.get("/view", async request =&gt; {
  const token = getToken(request)
  const isValid = await jwt.verify(token, signature)
  if (isValid == true) {
    const pid = request.headers.get("pid")
    const paste = await pastebin.get(pid);
    return new Response(paste, { status: 200, headers: myHeaders })
  }
  else if (valid == false) {
    return new Response("401, wrong passkey", { status: 401, headers: myHeaders })
  }
})


//list all posts
router.get("/list", async request =&gt; {
  const token = getToken(request)
  const isValid = await jwt.verify(token, signature)
  if (isValid == true) {
    const value = await pastebin.list()
    const json = JSON.stringify(value)
    myHeaders.set("content-type", "application/json;charset=UTF-8")
    return new Response(json, { status: 200, headers: myHeaders })
  }
  else {
    return new Response("401, token expired or invalid", { status: 401, headers: myHeaders })
  }
})

//view a shared post
router.get("/share/:id", async ({ params }) =&gt; {
  let input = params.id
  const paste = await publicbin.get(input);
  return new Response(paste, { status: 200, headers: myHeaders })
})

//create a new post
router.post("/create", async request =&gt; {
  const token = getToken(request)
  const isValid = await jwt.verify(token, signature)
  const body = await request.formData()
  const ct = body.get('content')
  const title_ = body.get('title')
  let flag = body.get('public')
  if (flag == null) {
    flag = "0"
  }
  const ts = Date.now()
  if (isValid == true &amp;&amp; ct != null) {
    await pastebin.put(ts, ct, { metadata: { title: title_, timeStamp: Date.now(), isPublic: flag } })
    if (flag == "1") {
      await publicbin.put(ts, ct, { metadata: { title: title_ } })
    }
    return new Response(Date.now(), { status: 200, headers: myHeaders })
  }
  else {
    return new Response("401, wrong passkey or invalid request idk", { status: 401, headers: myHeaders })
  }
})

//Delete a post
router.get("/delete", async request =&gt; {
  const token = getToken(request)
  const isValid = await jwt.verify(token, signature)
  const pid = request.headers.get("pid")
  let isPublic = request.headers.get("isPublic")
  if (isPublic == null) {
    isPublic = "0";
  }
  if (isValid == true &amp;&amp; pid != null) {
    if (isPublic == "1") {
      await publicbin.delete(pid)
    }
    await pastebin.delete(pid)
    return new Response("done", { status: 200, headers: myHeaders })
  }
  else {
    return new Response("401, wrong passkey or invalid request idk", { status: 401, headers: myHeaders })
  }
})

//404
router.all("*", () =&gt; new Response("404, not found!", { status: 404, headers: myHeaders }))

//Connect to router
addEventListener('fetch', (e) =&gt; {
  e.respondWith(router.handle(e.request))
})


addEventListener("fetch", event =&gt; {
  event.respondWith(handleRequest(event.request))
})
</code></pre><p>The code is kind of crude with some band-aids here and there. You should probably configure cors and csrf stuff as your liking. I've given a rough template on how it should happen.</p><p>I've used two namespace for kv store. One of all the private+public stuff and one for exclusively public stuff, which helps me separating the public facing - no auth side of my api more efficiently.</p><p>I've used the<a href="https://github.com/kwhitley/itty-router"> itty-router</a> library for basic routing and <a href="https://www.npmjs.com/package/@tsndr/cloudflare-worker-jwt">cloudflare-worker-jwt library</a> for generating and validating jwt tokens . both of these are specifically written for cf workers.</p><p>I also wrote a super sketchy frontend using materialise which took me more then 6 hours to finish and reminded me why I only do backend these days.</p><p>The frontend is served through the root route "/" using the worker itself thus making my cors pains a little bit better (and believe me cors is a yuuge PITA esp if you're working on compliance).</p><p>Now storing files is kinda tricky. I thought about adding dropbox/gdrve api to the worker but building such system without using o-auth is an uphill battle. I've used my previous pastebin at some extremely sketchy locations/cyber-cafes so I need a robust way of storing and accessing files quickly. Also my upload requirements are pretty basic (its mostly code I wrote someplace else, pdfs or word files).</p><p>I landed up on this solution -&gt; encode the files in base64 url string -&gt; chuck it into database -&gt; use browser's built in decode function to decode and download the file -&gt; (optional: for larger files, shard the url in chunks and store it in different kv's with its access table written in keys metadata making a adhoc linked list)</p><p>workers kv supports the value size of upto 25MB.. keeping in mind the 33% penalty for base64 encoding, it gives me 16.75MB of file storage per record which is plenty for my current use case. I may add shardng in a future update.</p><p>ggs till then</p><p>ps: here's the demo</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="blob:http://blog.danishjoshi.com/7b7a032d-39cf-4bc8-9bcb-174460786391" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="blob:http://blog.danishjoshi.com/7b7a032d-39cf-4bc8-9bcb-174460786391 424w, blob:http://blog.danishjoshi.com/7b7a032d-39cf-4bc8-9bcb-174460786391 848w, blob:http://blog.danishjoshi.com/7b7a032d-39cf-4bc8-9bcb-174460786391 1272w, blob:http://blog.danishjoshi.com/7b7a032d-39cf-4bc8-9bcb-174460786391 1456w" sizes="100vw"><img src="blob:http://blog.danishjoshi.com/7b7a032d-39cf-4bc8-9bcb-174460786391" data-attrs="{&quot;src&quot;:&quot;blob:http://blog.danishjoshi.com/7b7a032d-39cf-4bc8-9bcb-174460786391&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="blob:http://blog.danishjoshi.com/7b7a032d-39cf-4bc8-9bcb-174460786391 424w, blob:http://blog.danishjoshi.com/7b7a032d-39cf-4bc8-9bcb-174460786391 848w, blob:http://blog.danishjoshi.com/7b7a032d-39cf-4bc8-9bcb-174460786391 1272w, blob:http://blog.danishjoshi.com/7b7a032d-39cf-4bc8-9bcb-174460786391 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div>]]></content:encoded></item><item><title><![CDATA[Making a sub 10ms response time WIFI HID device.]]></title><description><![CDATA[I've always wondered why haven't we tried making wifi enabled keyboards.]]></description><link>https://blog.danishjoshi.com/p/making-a-sub-10ms-response-time-wifi-hid-device</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/making-a-sub-10ms-response-time-wifi-hid-device</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Thu, 30 Sep 2021 10:17:30 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2cAq!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7e1fe32-995e-43d3-a1a8-3cf0e738c614_469x469.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've always wondered why haven't we tried making wifi enabled keyboards. I mean we've already tried Bluetooth and RF ...... what's wrong with Wi-Fi. So I wanted to find out. On my pervious post on this topic I scratched the surface of making an HID device using esp8266. It was okay as a first proof concept but it was an unreliable mess. The latency spikes, sudden disconnects, terrible average response times and incompatibility across different systems out-of-the-box made it pretty terrible even for hobbyist use. So I set on to see what can I improve for version 2.0.</p><p>First thing that I wanted to do was replace python with some compiled language. Python is a great language for lightening fast prototyping but its interpreted nature makes it terrible for high-performance applications. This bundled with the difficulty to package/ship it and make it cross compatible - is a a huge pain in the culo. Believe me I've tried everything from freezing to virtual environments to py2exe. I just could not get the packaging right.</p><p>In the end I had two options on my plate ..... GoLang and C++. I had more experience building stuff in C++ than go, so I knew how much pain in the ass it would to write somewhat decent c++ code. So decided to give golang a try and honestly.... my dev journey with it was better than I expected. I feel like the go has best of both worlds. Flexibility, prototype(ability?) , and readability of python and performance and bundled/compiled nature of c++.</p><p>Second I wanted to reduce the latency. Like REALLY eliminate it. Because I have a project in mind to use this for custom bindings in doom eternal and if you lag even for a 100ms on you UN run its probably run over for you. I tried using http requests - which were slow as a turtle with 50-60ms average response times. Tried using MQTT(the protocol) - which was supposed to be fast but still hung around at 20-25ms ping (I have no clue why. Maybe somewhere I fucked it up somewhere in my implementation of it.... not sure.... maybe I'll retry using MQTT in the future). In the end I decided to give pain old TCP sockets a try and here were the results -&gt; average latency over 10000 requests -&gt; 5-7ms average response time. :D</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rHdR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99029aee-eba3-43c1-a33c-75d6c3d66fef_488x86.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rHdR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99029aee-eba3-43c1-a33c-75d6c3d66fef_488x86.png 424w, https://substackcdn.com/image/fetch/$s_!rHdR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99029aee-eba3-43c1-a33c-75d6c3d66fef_488x86.png 848w, https://substackcdn.com/image/fetch/$s_!rHdR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99029aee-eba3-43c1-a33c-75d6c3d66fef_488x86.png 1272w, https://substackcdn.com/image/fetch/$s_!rHdR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99029aee-eba3-43c1-a33c-75d6c3d66fef_488x86.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rHdR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99029aee-eba3-43c1-a33c-75d6c3d66fef_488x86.png" width="377" height="66" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/99029aee-eba3-43c1-a33c-75d6c3d66fef_488x86.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:66,&quot;width&quot;:377,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!rHdR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99029aee-eba3-43c1-a33c-75d6c3d66fef_488x86.png 424w, https://substackcdn.com/image/fetch/$s_!rHdR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99029aee-eba3-43c1-a33c-75d6c3d66fef_488x86.png 848w, https://substackcdn.com/image/fetch/$s_!rHdR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99029aee-eba3-43c1-a33c-75d6c3d66fef_488x86.png 1272w, https://substackcdn.com/image/fetch/$s_!rHdR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F99029aee-eba3-43c1-a33c-75d6c3d66fef_488x86.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-Hzu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F904f3af6-5a3a-445d-8a5d-82019853df45_668x461.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-Hzu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F904f3af6-5a3a-445d-8a5d-82019853df45_668x461.png 424w, https://substackcdn.com/image/fetch/$s_!-Hzu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F904f3af6-5a3a-445d-8a5d-82019853df45_668x461.png 848w, https://substackcdn.com/image/fetch/$s_!-Hzu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F904f3af6-5a3a-445d-8a5d-82019853df45_668x461.png 1272w, https://substackcdn.com/image/fetch/$s_!-Hzu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F904f3af6-5a3a-445d-8a5d-82019853df45_668x461.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-Hzu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F904f3af6-5a3a-445d-8a5d-82019853df45_668x461.png" width="387" height="267" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/904f3af6-5a3a-445d-8a5d-82019853df45_668x461.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:267,&quot;width&quot;:387,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!-Hzu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F904f3af6-5a3a-445d-8a5d-82019853df45_668x461.png 424w, https://substackcdn.com/image/fetch/$s_!-Hzu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F904f3af6-5a3a-445d-8a5d-82019853df45_668x461.png 848w, https://substackcdn.com/image/fetch/$s_!-Hzu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F904f3af6-5a3a-445d-8a5d-82019853df45_668x461.png 1272w, https://substackcdn.com/image/fetch/$s_!-Hzu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F904f3af6-5a3a-445d-8a5d-82019853df45_668x461.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Compare this to the flagship wireless HID technology in the market -<a href="https://www.logitechg.com/en-in/innovation/lightspeed.html"> Logitech lightspeed wireless </a>- coming in at 1ms.... My iteration was not too shabby. Its good enough for my TAG1 UN run.</p><p>Third thing was battery life...... Which I still haven't figured out yet. ESP consumes around 100mA during normal mode. When couple with a single AAA battery with a boost converter gives about ~8 Hours of use time. (Compare this to the 250 hours I get on my g305). WIFI(esp) consumes wayyyyyy too much power for a portable battery powered device. Which is the reason I guess why Wi-Fi HID devices haven't been popular. Stay tuned for part 3 when/if I figure it out to make this thing last longer either by using a different SOC or using sleep and interrupts on esp.</p><p><a href="https://github.com/SU1199/Wi-Fi-HID">Here's the source....</a></p><p>I am planning to create a go HID library to support precise thumbstick/mouse inputs for CAD applications. Now that I can achieve sub 10ms this shouldn't be impractical. So stay tuned for that. GGs till then.</p>]]></content:encoded></item><item><title><![CDATA[Anonymously saving instagram stories to personal cloud.]]></title><description><![CDATA[Holy sheit its been a long time since I wrote here.]]></description><link>https://blog.danishjoshi.com/p/anonymously-saving-instagram-stories-to-personal-cloud</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/anonymously-saving-instagram-stories-to-personal-cloud</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Wed, 22 Sep 2021 17:05:58 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2cAq!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7e1fe32-995e-43d3-a1a8-3cf0e738c614_469x469.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Holy sheit its been a long time since I wrote here. Been busy with some big personal projects and college. FeelsBadMan. :-/</p><p>Anyways.... I recently (last night) built an OSINT tool to save instagram stories to dropbox anonymously. Here's how it works -&gt;</p><ul><li><p>Use headless chrome to visit this page -&gt; 'https://www.anonigviewer.com/profile.php?u='+userName . Why use a third party website ? Because I am lazy asf and was trying to speedrun this project. moving on....</p></li><li><p>Find x-paths of all the latest stories and extract the media uris using almighty regex.</p></li><li><p>Download the media using requests whilst ignoring all the ssl warnings. (don't do this in prod)</p></li><li><p>Maintain a local database of the stories you've downloaded with timestamps and stuff.</p></li><li><p>Upload all of the media you ripped to dropbox using their awesome api (seriously, they have the best api-docs I've read in a while).</p></li></ul><p><a href="https://gist.github.com/SU1199/261a3e56f0352cf36bdb0badcef18285">Here's the code -&gt;</a></p><pre><code>from selenium import webdriver
import time
import re
from selenium.webdriver.common.by import By
from selenium import webdriver
import time
import re
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import requests
import dropbox
from tinydb import TinyDB, Query

# Declare yo user
user = 'doom'
storeFolder = "sauce/"

driver = webdriver.Chrome('chromedriver.exe')
driver.get('https://www.anonigviewer.com/profile.php?u='+user)

# Upload to dropbox
uriList = []

def dropUpload(uris):
&#9;dropbox_access_token= "" #Yo acess token goes here
&#9;client = dropbox.Dropbox(dropbox_access_token)
&#9;print("DataStore Connected")
&#9;for uri in uris:
&#9;&#9;to_path= "/"+uri
&#9;&#9;from_path=uri
&#9;&#9;client.files_upload(open(from_path, "rb").read(), to_path)
&#9;&#9;print("Upload Komplete")


# Poor man's nosql store omegalul

def isPresent(url):
&#9;db = TinyDB('db.json')
&#9;p = Query()
&#9;present = db.search(p.link==url)
&#9;if(len(present)==0):
&#9;&#9;db.insert({'link': url, 'timestamp': time.time()})
&#9;&#9;return False
&#9;else:
&#9;&#9;return True

# Coutesy Of StackOverFlow lol

def download_file(url,type):
&#9;if(isPresent(url)==False):
&#9;&#9;timestr = time.strftime("%Y%m%d-%H%M%S")
&#9;&#9;local_filename = storeFolder+timestr+type
&#9;&#9;r = requests.get(url,verify=False, stream=True)
&#9;&#9;with open(local_filename, 'wb') as f:
&#9;&#9;&#9;for chunk in r.iter_content(chunk_size=1024): 
&#9;&#9;&#9;&#9;if chunk:
&#9;&#9;&#9;&#9;&#9;f.write(chunk)
&#9;&#9;uriList.append(local_filename)
&#9;&#9;return local_filename

# Ugly code don't look

wait = WebDriverWait(driver, 50)&#9;# 50 Sec of summer
sauceCheck = wait.until(EC.visibility_of_element_located((By.XPATH, '/html/body/div[4]/div[3]/div/div[1]/div[1]/div/div')))
sauces = driver.find_elements_by_class_name('mb-4')
print(len(sauces))
i=1
preSauces = []
for sauce in sauces:
&#9;preSauces.append(driver.find_element_by_xpath('/html/body/div[4]/div[3]/div/div[1]/div['+str(i)+']/div/div').get_attribute("onclick"))
&#9;i=i+1

driver.close()

# Video or an Image ?

for preSauce in preSauces:
&#9;if preSauce.find("GraphVideo")!=-1:
&#9;&#9;type_ = ".mp4"
&#9;elif preSauce.find("GraphImage")!=-1:
&#9;&#9;type_ = ".jpg"
&#9;link = re.findall(r'(https?://\S+)', preSauce)[0].split('"')[0]
&#9;download_file(link,type_)

dropUpload(uriList)</code></pre><p>Couple of things to take care of -&gt;</p><p>Dropbox requires to start directory names with <strong>"/"</strong> . Make sure to you give appropriate write permissions in the app console.</p><p>Now just package this script -&gt; add it to a cron-job on a remote server and bam. Speedrun insta stalker any% complete xD.</p><p>Btw I am finishing up working on a really cool low-level driver written in go. I'll post something about it soon. GGs till then.</p><p>edit1: Here's some modified code if you want to run it on an ubuntu server :</p><pre><code>from selenium import webdriver
import os
import time
import re
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import requests
import dropbox
from tinydb import TinyDB, Query
from selenium.webdriver.chrome.options import Options

# Declare yo user
user = 'public user goes here'
storeFolder = "sauce/"

#Chrome Config
chrome_options = Options()
chrome_options.add_argument("--disable-extensions")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--no-sandbox") # linux only
chrome_options.add_argument("--headless")


driver = webdriver.Chrome(options=chrome_options)
driver.get('https://www.anonigviewer.com/profile.php?u='+user)

# Upload to dropbox
uriList = []

def dropUpload(uris):
        dropbox_access_token= "access token goes here"
        client = dropbox.Dropbox(dropbox_access_token)
        print("DataStore Connected")
        for uri in uris:
                to_path= "/"+uri
                from_path=uri
                client.files_upload(open(from_path, "rb").read(), to_path)
                print("Upload Komplete")


# Poor man's nosql store omegalul

def isPresent(url):
        db = TinyDB('db.json')
        p = Query()
        present = db.search(p.link==url)
        if(len(present)==0):
                db.insert({'link': url, 'timestamp': time.time()})
                return False
        else:
                return True

# Coutesy Of StackOverFlow lol

def download_file(url,type):
        if(isPresent(url)==False):
                timestr = time.strftime("%Y%m%d-%H%M%S")
                local_filename = storeFolder+timestr+type
                # NOTE the stream=True parameter
                r = requests.get(url,verify=False, stream=True)
                with open(local_filename, 'wb') as f:
                        for chunk in r.iter_content(chunk_size=1024):
                                if chunk: # filter out keep-alive new chunks
                                        f.write(chunk)
                uriList.append(local_filename)
                return local_filename

# Ugly code don't look

wait = WebDriverWait(driver, 50)        # 50 Sec of summer
try:
        sauceCheck = wait.until(EC.visibility_of_element_located((By.XPATH, '/html/body/div[4]/section[3]/div[1]/div/div[1]/div[1]/div/div'))) #/html/body/div[4]/section[3]/div[1]/div/div[1]/div[1]/div/div
except:
        driver.close()
        os.system("sudo killall chromedriver")
        exit()
sauces = driver.find_elements_by_class_name('mb-4')
print(len(sauces))
i=1
preSauces = []
for sauce in sauces:
        preSauces.append(driver.find_element_by_xpath('/html/body/div[4]/section[3]/div[1]/div/div[1]/div['+str(i)+']/div/div').get_attribute("onclick"))
        i=i+1

driver.close()

for preSauce in preSauces:
        if preSauce.find("GraphVideo")!=-1:
                type_ = ".mp4"
        elif preSauce.find("GraphImage")!=-1:
                type_ = ".jpg"
        link = re.findall(r'(https?://\S+)', preSauce)[0].split('"')[0]
        download_file(link,type_)

dropUpload(uriList)
</code></pre>]]></content:encoded></item><item><title><![CDATA[Creating a private PasteBin with client side encryption.]]></title><description><![CDATA[There have been multiple instance where I quickly wanted to move text between my devices.]]></description><link>https://blog.danishjoshi.com/p/creating-a-private-pastebin-with-client-side-encryption</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/creating-a-private-pastebin-with-client-side-encryption</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Sun, 24 May 2020 18:57:46 GMT</pubDate><enclosure url="http://150.136.174.254/wp-content/uploads/2020/05/image-1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There have been multiple instance where I quickly wanted to move text between my devices. Most common ways I used to do this was by emailing myself or using google keep. Which is very inefficient and dumb. So I decided to create a personal pastebin clone.</p><p>It stores the text in a public database, fully encrypted and decrypts it on the client side using credential stored on client's browser.</p><p>Here's some crucial code samples and explanations -</p><pre><code>var CryptoJS = require("crypto-js");
import Cookies from 'js-cookie'
var fb = require('./store.js');

if (Cookies.get('key_')) {
    var unlocked = true;
    var key_ = Cookies.get('key_');
} else if (!Cookies.get('key_')) {
    var unlocked = false;
    var key_ = null;
    alert("&#175;\_(&#12484;)_/&#175;")
}
var inputField_;
export default {
    name: 'App',
    beforeCreate() {
        fb.db.collection("bin").doc("paste")
            .onSnapshot(function (doc) {
                inputField_ = decrypt(doc.data().field);
                this.inputField = decrypt(doc.data().field);
            });
    },
    updated() {
        inputField_ = this.inputField
    },
    data() {
        return {
            unlocked_: unlocked,
            inputField: inputField_,
            password: null,
        }
    },
    methods: {
        unlock: function (event) {
            if (checkKey(this.password)) {
                Cookies.set('key_', this.password, {
                    expires: 365
                })
                if (this.password) {
                    this.unlocked_ = true;
                    this.decrypted = true;
                }
            }
        },
        save: function (event) {
            // Add a new document in collection "cities"
            fb.db.collection("bin").doc("paste").set({
                    field: encrypt(this.inputField)
                })
                .then(function () {
                    console.log("Document successfully written!");
                    window.navigator.vibrate(200);
                })
                .catch(function (error) {
                    console.error("Error writing document: ", error);
                });
        },
        update: function (event) {
            this.inputField = inputField_
        }
    },
    computed: {
        shit: function () {
            alert(inputField_)
            return inputField_;
        }
    }
}

function decrypt(data_) {
    if (key_) {
        try {
            var decrypted = CryptoJS.AES.decrypt(data_, key_);
            return decrypted.toString(CryptoJS.enc.Utf8);
        } catch (e) {
            return data_
            console.log(e)
        }
    } else {
        return data_
        console.log(e)
    }
}

function encrypt(data_) {
    if (key_) {
        var encrypted = CryptoJS.AES.encrypt(data_, key_);
        return encrypted.toString();
    } else {
        return data_
        console.log(e)
    }
}

function checkKey(input_) {
    var decrypted = CryptoJS.AES.decrypt('U2FsdGVkX19CZxyjXIRZeb3N+ffdvboRFIyQELM1ab0=', input_);
    if (decrypted.toString(CryptoJS.enc.Utf8) == "aezakmi") {
        return true;
    }
}</code></pre><ul><li><p>The app uses vue.js so this is the script part of the app.vue file.</p></li><li><p>It uses a javascript library <a href="https://github.com/brix/crypto-js">- cryptojs</a> to encrypt and decrypt the text on the browser side .</p></li><li><p>First it checks for the decryption key in the browser cookies and throws out the error for the uses to enter the key. The key is stored in the browser for 1 year.</p></li><li><p>decrypt() function decrypts the aes256 strings obtained from public database.</p></li><li><p>encrypt() function encrypts the text to aes256 string using the key from cookies.</p></li><li><p>the checkKey() function is used to check if the entered key is correct or not by verifying if the entered key decrypts a predetermined text.</p></li><li><p>They whole thing uses firebase for a database WITHOUT any public rules.</p></li><li><p>As the data is encrypted to the highest(actually 2nd highest) standard before storing , any 3rd party won't be able to see the data (unless they are able to steal your browser cookies).</p></li></ul><p>This is the final result ! &gt;&gt;</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="http://150.136.174.254/wp-content/uploads/2020/05/image-1.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="http://150.136.174.254/wp-content/uploads/2020/05/image-1.png 424w, http://150.136.174.254/wp-content/uploads/2020/05/image-1.png 848w, http://150.136.174.254/wp-content/uploads/2020/05/image-1.png 1272w, http://150.136.174.254/wp-content/uploads/2020/05/image-1.png 1456w" sizes="100vw"><img src="http://150.136.174.254/wp-content/uploads/2020/05/image-1.png" data-attrs="{&quot;src&quot;:&quot;http://150.136.174.254/wp-content/uploads/2020/05/image-1.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="http://150.136.174.254/wp-content/uploads/2020/05/image-1.png 424w, http://150.136.174.254/wp-content/uploads/2020/05/image-1.png 848w, http://150.136.174.254/wp-content/uploads/2020/05/image-1.png 1272w, http://150.136.174.254/wp-content/uploads/2020/05/image-1.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="http://150.136.174.254/wp-content/uploads/2020/05/image-1024x360.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="http://150.136.174.254/wp-content/uploads/2020/05/image-1024x360.png 424w, http://150.136.174.254/wp-content/uploads/2020/05/image-1024x360.png 848w, http://150.136.174.254/wp-content/uploads/2020/05/image-1024x360.png 1272w, http://150.136.174.254/wp-content/uploads/2020/05/image-1024x360.png 1456w" sizes="100vw"><img src="http://150.136.174.254/wp-content/uploads/2020/05/image-1024x360.png" data-attrs="{&quot;src&quot;:&quot;http://150.136.174.254/wp-content/uploads/2020/05/image-1024x360.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="http://150.136.174.254/wp-content/uploads/2020/05/image-1024x360.png 424w, http://150.136.174.254/wp-content/uploads/2020/05/image-1024x360.png 848w, http://150.136.174.254/wp-content/uploads/2020/05/image-1024x360.png 1272w, http://150.136.174.254/wp-content/uploads/2020/05/image-1024x360.png 1456w" sizes="100vw"></picture><div></div></div></a></figure></div><p>Here's the complete <a href="https://gist.github.com/SU1199/02745f081cdb2d0c7dad0e2d82a264ad">app.vue</a> file for reference. New suggestions are welcome ... Enjoy!</p>]]></content:encoded></item><item><title><![CDATA[It's time to Build]]></title><description><![CDATA[Marc Andreessen , the CEO of a16z venture firm and the creator of Netscape browser recently wrote a very inspiring piece about building stuff.]]></description><link>https://blog.danishjoshi.com/p/its-time-to-build</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/its-time-to-build</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Sun, 19 Apr 2020 04:14:32 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2cAq!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7e1fe32-995e-43d3-a1a8-3cf0e738c614_469x469.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Marc Andreessen , the CEO of a16z venture firm and the creator of Netscape browser recently <a href="https://a16z.com/2020/04/18/its-time-to-build/">wrote a very inspiring piece about building</a> stuff. The article delves into some of the key aspects the America is slipping in its position as a global technology hub and what are the things the people have to do to bring it back to its previous status as the nation who build great stuff.</p><p>Here's some key point I liked from the article -</p><ul><li><p>Every Western institution was unprepared for the coronavirus pandemic, despite many prior warnings.</p></li><li><p>&nbsp;And that is a failure of action, and specifically our widespread inability to *build*.</p></li><li><p>A government that collects money from all its citizens and businesses each year has never built a system to distribute money to us when it&#8217;s needed most.</p></li><li><p>You don&#8217;t just see this smug complacency, this satisfaction with the status quo and the unwillingness to build, in the pandemic, or in healthcare generally. You see it throughout Western life, and specifically throughout American life.</p></li><li><p>Why not educate every 18 year old? Isn&#8217;t that the most important thing we can possibly do?&nbsp;</p></li><li><p>We know how to build highly automated factories. We know the enormous number of higher paying jobs we would create to design and build and operate those factories.</p></li><li><p>Is the problem capitalism? I&#8217;m with Nicholas Stern when he says that capitalism is how we take care of people we don&#8217;t know &#8212; all of these fields are highly lucrative already and should be prime stomping grounds for capitalist investment, good both for the investor and the customers who are served.</p></li><li><p>The problem is inertia. We need to want these things more than we want to prevent these things.</p></li><li><p>The right must fight hard against crony capitalism, regulatory capture, ossified oligopolies, risk-inducing offshoring, and investor-friendly buybacks in lieu of customer-friendly (and, over a longer period of time, even more investor-friendly) innovation</p></li><li><p>Milton Friedman once said the great public sector mistake is to judge policies and programs by their intentions rather than their results. Instead of taking that as an insult, take it as a challenge &#8212; build new things and show the results!</p></li><li><p>Why can&#8217;t 100,000 or 1 million students a year attend Harvard? Why shouldn&#8217;t regulators and taxpayers demand that Harvard build? Solve the climate crisis by building.</p></li><li><p>We need to demand more of our political leaders, of our CEOs, our entrepreneurs, our investors.&nbsp;</p></li><li><p>We&#8217;re all necessary, and we can all contribute, to building.</p></li><li><p>Every step of the way, to everyone around us, we should be asking the question, what are you building?</p></li><li><p>If the work you&#8217;re doing isn&#8217;t either leading to something being built or taking care of people directly, we&#8217;ve failed you, and we need to get you into a position, an occupation, a career where you can contribute to building.&nbsp;</p></li><li><p>There are always outstanding people in even the most broken systems &#8212; we need to get all the talent we can on the biggest problems we have, and on building the answers to those problems.</p></li></ul><p>The last paragraph was the most moving one -</p><blockquote><p>Our nation and our civilization were built on production, on building. Our forefathers and foremothers built roads and trains, farms and factories, then the computer, the microchip, the smartphone, and uncounted thousands of other things that we now take for granted, that are all around us, that define our lives and provide for our well-being. There is only one way to honor their legacy and to create the future we want for our own children and grandchildren, and that&#8217;s to build.</p><p>Marc Andreessen</p></blockquote>]]></content:encoded></item><item><title><![CDATA[Using ESP-8266/32 as a wireless HID device. part_1]]></title><description><![CDATA[HID or Human Interface Devices are the peripherals used to get human input.]]></description><link>https://blog.danishjoshi.com/p/using-esp-8266-32-as-a-wireless-hid-device-part_1</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/using-esp-8266-32-as-a-wireless-hid-device-part_1</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Thu, 02 Apr 2020 09:35:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2cAq!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7e1fe32-995e-43d3-a1a8-3cf0e738c614_469x469.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>HID or Human Interface Devices are the peripherals used to get human input. Examples include your mouse, keyboards , game controllers etc.</p><p>Now I wanted to control my systems over the wifi. SSH or telnet would't suffice as I NEEDED mouse input. (Basically wanted to make a wifi enabled scroll wheel). This problem gave birth to this project.</p><div><hr></div><h3>Basic idea -</h3><ul><li><p>Set up a local server to get requests from the local network.</p></li><li><p>Use esp to send get request to the server. Request may include specific data (like mouse coordinates or keystrokes) or just Boolean data to tell system to perform a specific function.</p></li><li><p>Every time a server gets a request, perform the specific function by using appropriate system level commands to send hid events to system.</p></li><li><p>Reduce the input lag as much as possible by maintaining a constant connection between server and the esp.</p></li></ul><h2>1. Setting UP the server :</h2><p>To server the requests I decided to use <a href="https://flask.palletsprojects.com/">FLASK </a>- A lightweight-micro web framework written in python. I selected it for two reasons - 1) I have used it before(duh!) , 2) Its laughably simple to get up and running , 3) Its based on python so I can use plethora of libraries to interface with the I/O.</p><p>Here's the basic setup -&gt;</p><pre><code>import flask

app = flask.Flask(__name__)
app.config["DEBUG"] = True


@app.route('/', methods=['GET'])
def home():
    return "&lt;h1&gt;SUP!&lt;h1&gt;"

app.run(host = '0.0.0.0')</code></pre><p>Only important thing to note here is that we are running it at 0.0.0.0 instead of localhost to make it visible to the whole network network.</p><h2>2. Generating hard-coded HID events :</h2><p>To send keystrokes or mouse input we are going to use <a href="https://github.com/asweigart/pyautogui">pyautogui</a> . It an amazing cross platform library which hides all the complexity in interacting with different de(s) for different os(es). To quote from its official github page :</p><pre><code>On Windows, PyAutoGUI accesses the Windows API (also called the WinAPI or win32 API) through the built-in&nbsp;ctypes&nbsp;module. 
On macOS, PyAutoGUI uses the&nbsp;rubicon-objc&nbsp;module to access the Cocoa API.
On Linux, PyAutoGUI uses the&nbsp;Xlib&nbsp;module to access the X11 or X Window System.</code></pre><p>Install it on your system using :</p><pre><code>pip install pyautogui
#for linux only
sudo apt-get install python3-xlib</code></pre><p>Try it by running the following on your system :</p><pre><code>import flask
import pyautogui 

app = flask.Flask(__name__)
app.config["DEBUG"] = True


@app.route('/up', methods=['GET'])
def home():
    pyautogui.scroll(-20) 
    return "&lt;h1&gt;Scrolling Up&lt;h1&gt;"

app.run(host = '0.0.0.0')</code></pre><p>After running this script(<strong>in su mode!</strong>) go to your pc's local ip address on your default port (in my case it 192.168.1.78:8888) and see if reloading the page sends scroll down command to the system.</p><p>If it works good !. If it doesn't go <a href="https://pyautogui.readthedocs.io/">here</a> to troubleshoot.</p><h2>3. Sending get requests using esp :</h2><p>To do this first you have to connect your esp module to your local wireless network, detect hardware input and send send the get request to the server's address.</p><p>Here's the code :</p><pre><code>#include &lt;ESP8266WiFi.h&gt;

#include &lt;ESP8266HTTPClient.h&gt;

const char * ssid = "ssid";
const char * password = "pass";

void setup() {

  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {

    delay(1000);
    Serial.print("Connecting..");
  }

}

void loop() {

  if (WiFi.status() == WL_CONNECTED) { //check connection

    HTTPClient http;
    if (digitalRead(BUTTON) == LOW) {
      http.begin("DESTINATION"); //request destination
      int httpCode = http.GET();
      if (httpCode &gt; 0) {
        String payload = http.getString();
        Serial.println(payload); //response
      }
      http.end();
    }
  }
}</code></pre><p>Replace "ssid" , "password" with your wifi details. Replace "DESTINATION" with the address you entered in your browser in the last step. Replace (BUTTON) with the pin number your connected your trigger to.</p><h2>4. Sending KeyStrokes/Dynamic data :</h2><p>To receive dynamic in flask change -</p><pre><code>@app.route('/', methods=['GET'])</code></pre><p>to -</p><pre><code>@app.route('/&lt;stroke&gt;', methods=['GET'])</code></pre><p>To send keystrokes use :</p><pre><code>pyautogui.typewrite(stroke, interval=0)</code></pre><p>Refer to <a href="https://pyautogui.readthedocs.io/en/latest/keyboard.html">this document </a>to get into details.</p><p>Here's the final code :</p><pre><code>import flask
import pyautogui 

app = flask.Flask(__name__)
app.config["DEBUG"] = True

@app.route('/&lt;stroke&gt;', methods=['GET'])
def home():
    pyautogui.typewrite(stroke, interval=0)
    return "&lt;h1&gt;done&lt;h1&gt;"

app.run(host = '0.0.0.0')</code></pre><p>Now your can send keystokes to your system by editing the url after you ip (eg: http://192.168.1.78:8888/hello)</p><div><hr></div><p>This is it for part one. In part two i will be assembling this shit into a neatly structured library with all the hid options from joysticks to scroll wheels, and game controllers. I will also try to reduce the lag/latency between hardware button presses and actual input by using something better to send requests .</p>]]></content:encoded></item><item><title><![CDATA[Making finance bots using python and bs4]]></title><description><![CDATA[I recently discovered something about myself, that I prefer asking a bot to get some quick info than searching for and opening a website.]]></description><link>https://blog.danishjoshi.com/p/making-financial-bots-using-python-and-bs4</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/making-financial-bots-using-python-and-bs4</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Sat, 28 Mar 2020 08:13:10 GMT</pubDate><enclosure url="http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently discovered something about myself, that I prefer asking a bot to get some quick info than searching for and opening a website.</p><p>So as a trial I decided to make financial bots for telegram using python and bs4.</p><h3>bot_1 : StonkBoi</h3><p>This bot scrapes the live stock data of a company from yahoo finance and reports back on telegram. It uses bs4 and requests to search and scrape the data and telegram python library to get the commands and send the info.</p><p>Bot is divided into two files the first file dataFetch.py has all the scraping goodness organised into different functions which are called in the tradeBot.py file.</p><p>Here's some sample code for the dataFetch.py :</p><pre><code>def lastTradedPrice(ticker):
    page = requests.get("https://in.finance.yahoo.com/quote/"+ticker)
    soup = BeautifulSoup(page.content, 'html.parser')
    val = soup.findAll("span", {"class": "Trsdu(0.3s) Trsdu(0.3s) Fw(b) Fz(36px) Mb(-4px) D(b)"})
    if len(val) &gt;=1 :
        return val[0].get_text()
    else:
        return "Invalid Request"</code></pre><p>Here function lastTradedPrice request the whole yfinance page for the given ticker and then beautiful soup fetches the price element using its findAll function to filter for specific class( in this case : Trsdu(0.3s) Trsdu(0.3s) Fw(b) Fz(36px) Mb(-4px) D(b)). The function returns "Invalid request" it it detects the value is null . We cannot use the response code of the requests function as the page still returns the not found page and send the 200 status code.</p><p><a href="https://github.com/SU1199/stonk-bot">Here's the complete source code for the bot.</a></p><p>Here is the list of commands :</p><pre><code>Enter '$&lt;ticker&gt; x' where x can be 
sum =&gt; summary 
ltp =&gt; Last Traded Price 
mktcap =&gt; Market Cap 
chg =&gt; Day's price change 
prevclose =&gt; Previous Close Price 
openprice =&gt; Opening Price 
dayrange =&gt; Day's price range 
52range =&gt; 52 Week Range
vol =&gt; volume
pe =&gt; P/E Ratio 
div =&gt; Dividend Yields 
 Example =&gt; $SPY sum 
 Example-2 =&gt; $HDFCBANK.NS ltp</code></pre><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg 424w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg 848w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg 1272w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg 1456w" sizes="100vw"><img src="http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg" width="353" height="627" data-attrs="{&quot;src&quot;:&quot;http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:627,&quot;width&quot;:353,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg 424w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg 848w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg 1272w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217882-1-576x1024.jpg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>bot_2 : MarginsBoi</h2><p>This bot fetches the latest margins info provided by my stonk broker - Zerodha. It can find latest margins on commodities, equities, equity futures and currency futures.</p><p>The scraping part of the bot is also accessible through command line/terminal.</p><p>Here's some sample code of the scraping part :</p><pre><code>def equityFutures(ticker):
    j =0
    page = requests.get("https://zerodha.com/margin-calculator/Futures/")
    soup = BeautifulSoup(page.content, 'html.parser')
    table = soup.find("table", {"class": "data futures"})
    table_rows = table.find_all('tr')
    head = 'Contract\tExpiry\tLot Size\tPrice\tNRML Margin\tNRML Margin Rate \tMWPS\n\n'
    data = ''
    for tr in table_rows:
        if j&gt;=1:
            td = tr.find_all('td')
            row = [i.text for i in td]
            completeRow = ''
            if ticker.lower() == row[1].lower().replace('\n', '').replace('\t', ''):
                for index, cell in enumerate(row, start=0): 
                    if index &lt;= 7 and index &gt;=1 :
                        completeRow = completeRow + cell.replace('\n', '').replace('\t', '') + '\t\t'
                data = data + completeRow + '\n'
        j = j+1
    return head + data</code></pre><p>Here the bot scrapes the whole margins page for equity futures using requests and finds the desired table using bs4. Then a for loop parses every row of the table and a conditional checks if the second element of row (stonk name) matches the input ticker. It then goes on to return all the futures derivatives of the given ticker after cleaning the data for '\n\ &amp; '\t' characters.</p><p><a href="https://github.com/SU1199/ZerodhaMargins">Here's the complete source for the python script.</a></p><p>Here is the list of terminal commands :</p><pre><code>Enter 'python3 marginBoi.py &lt;TICKER&gt; &lt;x&gt;' where x can be : &nbsp;
'com' : Commodity 
'eq' : Equities 
'eqfut' : Equity Futures 
'fxfut' : Currency Futures 
Example : 'python3 marginBoi.py BHEL eqfut'</code></pre><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217883-576x1024.jpg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217883-576x1024.jpg 424w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217883-576x1024.jpg 848w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217883-576x1024.jpg 1272w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217883-576x1024.jpg 1456w" sizes="100vw"><img src="http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217883-576x1024.jpg" width="365" height="648" data-attrs="{&quot;src&quot;:&quot;http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217883-576x1024.jpg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:648,&quot;width&quot;:365,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217883-576x1024.jpg 424w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217883-576x1024.jpg 848w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217883-576x1024.jpg 1272w, http://150.136.174.254/wp-content/uploads/2020/03/photo6339235544529217883-576x1024.jpg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>I plan of adding more robust features to stonk-boi like maybe trade execution and stonk alerts.... Stay tuned !</p>]]></content:encoded></item><item><title><![CDATA[COVID-19 a.k.a BeerFlu Telegram Bot]]></title><description><![CDATA[Covid19 pandemic will go down as the inflection point for our generation.]]></description><link>https://blog.danishjoshi.com/p/covid-19-a-k-a-beerflu-telegram-bot</link><guid isPermaLink="false">https://blog.danishjoshi.com/p/covid-19-a-k-a-beerflu-telegram-bot</guid><dc:creator><![CDATA[su1199]]></dc:creator><pubDate>Wed, 18 Mar 2020 17:28:14 GMT</pubDate><enclosure url="http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Covid19 pandemic will go down as the inflection point for our generation. Just like 9/11, 2008 mortgage crisis, 1920 stock crash and Spanish flu, its many disasters rolled into one. Stock market drop (steepest in history) + highly contagious virus with 2%+ mortality + epic trade wars with a spicy topping of incompetent leadership = one hell of a disaster.</p><p>As a tribute to this epic event I made a telegram bot to notify me about the total number of cases and the total number of deaths due to beer-flu at any give time - live. This was the first telegram bot I actually hosted on a cloud server. All of my previous bots were either self hosted on a SBC or used serverless functions to do the trick but this time I wanted to do it differently. I bought a cheapo $2/mo vps on 1&amp;1 (cheapest vps plan I could find) pushed the script using SSH and ran it after detaching the terminal. All of this in under 30 minutes !</p><p>Here's some really poorly written code &gt;</p><pre><code>import logging
import telegram
from telegram.error import NetworkError, Unauthorized
from time import sleep
import requests
from bs4 import BeautifulSoup

update_id = None

countries = 'China\nItaly\nUSA\nSpain\nGermany\nIran\nFrance\nS. Korea\nSwitzerland\nUK\nNetherlands\nAustria\nBelgium\nNorway\nSweden\nCanada\nDenmark\nAustralia\nPortugal\nMalaysia\nBrazil\nJapan\nCzechia\nTurkey\nIsrael\nIreland\nDiamond Princess\nLuxembourg\nPakistan\nThailand\nChile\nPoland\nEcuador\nGreece\nFinland\nQatar\nIceland\nIndonesia\nSingapore\nSaudi Arabia\nSlovenia\nPhilippines\nRomania\nIndia\nPeru\nBahrain\nRussia\nEstonia\nEgypt\nHong Kong\nMexico\nPanama\nSouth Africa\nLebanon\nArgentina\nIraq\nColombia\nCroatia\nArmenia\nSerbia\nSlovakia\nKuwait\nBulgaria\nSan Marino\nTaiwan\nUAE\nAlgeria\nUruguay\nHungary\nLatvia\nCosta Rica\nDominican Republic\nLithuania\nJordan\nMorocco\nVietnam\nBosnia and Herzegovina\nFaeroe Islands\nAndorra\nNorth Macedonia\nCyprus\nBrunei \nMoldova\nSri Lanka\nAlbania\nBelarus\nMalta\nVenezuela\nNew Zealand\nBurkina Faso\nTunisia\nGuadeloupe\nSenegal\nGeorgia\nKazakhstan\nAzerbaijan\nCambodia\nPalestine\nOman\nTrinidad and Tobago\nUkraine\nR&#233;union\nUzbekistan\nCameroon\nMartinique\nLiechtenstein\nChannel Islands\nHonduras\nBangladesh\nAfghanistan\nDRC\nParaguay\nNigeria\nCuba\nGhana\nPuerto Rico\nJamaica\nMacao\nBolivia\nGuyana\nMonaco\nFrench Guiana\nGuatemala\nRwanda\nMontenegro\nTogo\nFrench Polynesia\nGuam\nMauritius\nBarbados\nIvory Coast\nKyrgyzstan\nMaldives\nMayotte\nGibraltar\nMongolia\nEthiopia\nAruba\nKenya\nSeychelles\nEquatorial Guinea\nTanzania\nU.S. Virgin Islands\nGabon\nSaint Martin\nSuriname\nBahamas\nNew Caledonia\nEswatini\nCayman Islands\nCura&#231;ao\nCabo Verde\nCAR\nCongo\nEl Salvador\nLiberia\nMadagascar\nNamibia\nSt. Barth\nZimbabwe\nSudan\nAngola\nBenin\nBermuda\nBhutan\nFiji\nGreenland\nGuinea\nHaiti\nIsle of Man\nMauritania\nNicaragua\nSaint Lucia\nZambia\nNepal\nAntigua and Barbuda\nChad\nDjibouti\nEritrea\nGambia\nVatican City\nMontserrat\nNiger\nPapua New Guinea\nSt. Vincent Grenadines\nSint Maarten\nSomalia\nTimor-Leste\nUganda'

instructions = "Enter 'info' to get summary of the world.\nEnter 'country &lt;country name&gt;' for Country-Wise Info.\nEnter 'list' to get list of available countries."

def main():
    global update_id
    bot = telegram.Bot('TOKEN')

    try:
        update_id = bot.get_updates()[0].update_id
    except IndexError:
        update_id = None

    logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    while True:
        try:
            echo(bot)
        except NetworkError:
            sleep(1)
        except Unauthorized:
            update_id += 1


def echo(bot):
    global update_id
    for update in bot.get_updates(offset=update_id, timeout=10):
        update_id = update.update_id + 1

        if update.message:
            if update.message.text.lower() == "info":
                update.message.reply_text(info())
            elif update.message.text.lower().split(" ",1)[0] == "country":
                update.message.reply_text(data(update.message.text.split(" ",1)[1]))
            elif update.message.text.lower() == "list":
                update.message.reply_text(countries)
            else:
                update.message.reply_text(instructions)

def data(country):
    i = 0
    page = requests.get("https://www.worldometers.info/coronavirus/")
    soup = BeautifulSoup(page.content, 'html.parser')
    table = soup.find('table')
    table_rows = table.find_all('tr')
    for tr in table_rows:
        td = tr.find_all('td')
        if i &gt; 0:
            if td[0].text.lower() == country.lower():
                return td[0].text.strip() + " has " + td[1].text.strip() + ' total cases, ' + td[2].text.strip() + ' new cases, ' + td[3].text.strip() + ' total deaths, ' + td[4].text.strip() + ' new death(s), ' + td[5].text.strip() + ' total recoverd, ' + td[6].text.strip() + ' active cases, ' + td[7].text.strip() + ' serious critical cases.'
        elif i &gt;= len(table_rows)+1:
            return "Invalid Country"
        i =i+1

def info():
    page = requests.get("https://www.worldometers.info/coronavirus/coronavirus-cases/")
    soup = BeautifulSoup(page.content, 'html.parser')
    i = soup.find_all('p')[0].get_text()
    return i


if __name__ == '__main__':
    main()</code></pre><p>Here's what is does :</p><ul><li><p>Scrape the data from /www.worldometers.info and parse it using beautiful soup.</p></li><li><p>Reply with this data every-time any message is sent to the bot.</p></li><li><p>Its basically a zombie mutation of an echo bot.</p></li></ul><p><s>I am planning to enhance its functionality by giving it access to country-wise data and rates available on worldmeters. </s>UPDATE: Added the country-wise inquiring feature. Check it out <a href="https://github.com/SU1199/COVID19-TelegramBot">here</a>.</p><p>To try this bot use bot id &gt; <a href="https://t.me/corona_chan_bot">@CovidCaseReporter_bot</a> on telegram. Enter 'info' to get summary and 'country &lt;name&gt;' to get specifics.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg 424w, http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg 848w, http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg 1272w, http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg 1456w" sizes="100vw"><img src="http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg" width="351" height="624" data-attrs="{&quot;src&quot;:&quot;http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:624,&quot;width&quot;:351,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg 424w, http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg 848w, http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg 1272w, http://150.136.174.254/wp-content/uploads/2020/03/unnamed-1-576x1024.jpg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Stay Safe !</p>]]></content:encoded></item></channel></rss>