summaryrefslogtreecommitdiffstats
path: root/micro.pinapelz.moe/posts/2025-12-04-procon2-hid-tool/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'micro.pinapelz.moe/posts/2025-12-04-procon2-hid-tool/index.html')
-rw-r--r--micro.pinapelz.moe/posts/2025-12-04-procon2-hid-tool/index.html634
1 files changed, 634 insertions, 0 deletions
diff --git a/micro.pinapelz.moe/posts/2025-12-04-procon2-hid-tool/index.html b/micro.pinapelz.moe/posts/2025-12-04-procon2-hid-tool/index.html
new file mode 100644
index 0000000..137cf9a
--- /dev/null
+++ b/micro.pinapelz.moe/posts/2025-12-04-procon2-hid-tool/index.html
@@ -0,0 +1,634 @@
+<!DOCTYPE html>
+<html lang="en-us">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <style type=text/css>body{font-family:monospace;}</style>
+ <title>Enable HID Mode on Nintendo Pro Controller 2 | micro.pinapelz.moe</title>
+
+ <meta name="author" content="map[avatar:https://files.catbox.moe/5r1pue.jpg banner:https://files.pinapelz.com/pso2ngs-2232-collab.png bio:yo! and he&#39;s more than a cover he&#39;s a quilt&lt;br/&gt;
+ General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)&lt;br/&gt;
+ Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)&lt;br/&gt;
+ I Watch only slice of life (and Bandori)&lt;br/&gt;
+ Arch Linux &#43; Hyprland user (btw)&lt;br/&gt;
+ Hi from the &lt;a href=&#34;https://indieweb.org/&#34;&gt;indieweb&lt;/a&gt;, if you are seeing me bridged elsewhere! email:yukais@pinapelz.com name:Pinapelz]">
+ <link rel="stylesheet" href="/css/style.css">
+
+
+
+ <link rel="me" href="https://github.com/pinapelz" />
+ <link rel="me" href="mailto:yukais@pinapelz.com" />
+ <link rel="me" href="https://sakurajima.social/@pinapelz" />
+ <link rel="me" href="https://bsky.app/profile/pinapelz.moe" /><link rel="pgpkey" href="https://pinapelz.com/Yukai_Shan.asc">
+ <link
+ rel="authorization_endpoint"
+ href="https://indieauth.com/auth"
+ />
+ <link
+ rel="token_endpoint"
+ href="https://tokens.indieauth.com/token"
+ />
+ <link rel="webmention" href="https://webmention.io/micro.pinapelz.moe/webmention" />
+
+
+
+</head>
+<body>
+ <header>
+ <div style="display:flex;flex-flow:row wrap;justify-content:space-between">
+ <div style="align-self:flex-start;">
+ ==============<br>
+ == <a href="https://micro.pinapelz.moe/">Pinapelz</a> ==<br>
+ ==============
+ </div>
+ <div style="align-self:center;">check it out. I&#39;m in the house like carpet</div>
+ </div>
+ <nav style="margin: 1rem auto;">
+
+
+ <a href="/posts/"><b>Posts</b></a>.
+
+ <a href="/categories/"><b>Categories</b></a>.
+
+ <a href="/tags/"><b>Tags</b></a>.
+
+
+ </nav>
+</header>
+
+
+
+ <main>
+ <article class="h-entry">
+ <a class="u-bridgy-fed" href="https://fed.brid.gy/" hidden="from-humans"></a>
+ <h1 class="p-name">Enable HID Mode on Nintendo Pro Controller 2</h1>
+ <div hidden><div class="h-card p-author bio-card" style="text-align:center;">
+
+ <div class="banner" style="margin-bottom: 1rem; position: relative;">
+ <img class="u-featured" src="https://files.pinapelz.com/pso2ngs-2232-collab.png" alt="Banner" style="width: 100%; max-width: 400px; height: auto; border-radius: 8px; opacity: 0.6;">
+ <img class="u-photo avatar" src="https://files.catbox.moe/5r1pue.jpg" alt="Pinapelz's avatar" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);">
+ </div>
+
+ <div class="bio">
+ <p class="p-note">yo! and he's more than a cover he's a quilt<br/>
+ General arcade rhythm game enjoyer (SDVX, IIDX, CHUNITHM)<br/>
+ Mostly play MMOs (FFXIV, OSRS), JRPGs, and VNs (anything with a good story)<br/>
+ I Watch only slice of life (and Bandori)<br/>
+ Arch Linux + Hyprland user (btw)<br/>
+ Hi from the <a href="https://indieweb.org/">indieweb</a>, if you are seeing me bridged elsewhere!</p>
+ </div>
+ <p class="bio-name"><a href="https://micro.pinapelz.moe/" rel="me" class="p-nickname p-name u-url">Pinapelz</a></p>
+</div>
+<hr/>
+</div>
+
+
+ <div><b>
+ <time class="dt-published" datetime="2025-12-04T23:19:29-08:00">
+ Thursday, December 4, 2025
+ </time>
+ - <a href="https://micro.pinapelz.moe/posts/2025-12-04-procon2-hid-tool/" class="u-url u-uid" >Permalink</a>
+ </b></div>
+ <div class="article-meta"><span class="categories">
+ Categories:
+
+ <a href="/categories/tools">tools</a>
+
+ </span>--<span class="tags">
+ Tags:
+
+ #<a href="/tags/code" class="p-category">code</a>
+
+ #<a href="/tags/nintendo" class="p-category">nintendo</a>
+
+ </span></div><div class="e-content">
+ <p>Switch 2 Pro Controller is very comfy in my hands, but unfortunately it didn&rsquo;t work out of box on PC (Linux) for me like it&rsquo;s predacessor. Until there&rsquo;s actual better driver support for this thing in the kernel (or Valve does something), here&rsquo;s a hacky Python script to initialize HID-mode on the controller</p>
+<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># I only tested this script on Linux w/ Steam but in theory it shoud work on Windows?</span>
+</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> usb.core <span style="color:#75715e"># install pyusb first: pip install pyusb</span>
+</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> usb.util
+</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> time
+</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sys
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span>VENDOR_ID <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x057E</span>
+</span></span><span style="display:flex;"><span>PRODUCT_IDS <span style="color:#f92672">=</span> {
+</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2066</span>: <span style="color:#e6db74">&#34;Joy-Con (L)&#34;</span>,
+</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2067</span>: <span style="color:#e6db74">&#34;Joy-Con (R)&#34;</span>,
+</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2069</span>: <span style="color:#e6db74">&#34;Pro Controller&#34;</span>,
+</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x2073</span>: <span style="color:#e6db74">&#34;GCN Controller&#34;</span>
+</span></span><span style="display:flex;"><span>}
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span>USB_INTERFACE_NUMBER <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span>INIT_COMMAND_0x03 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0d</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>])
+</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x07 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x07</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x16 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x16</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>REQUEST_CONTROLLER_MAC <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x15</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0e</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>])
+</span></span><span style="display:flex;"><span>LTK_REQUEST <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x15</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x11</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>, <span style="color:#ae81ff">0xFF</span>])
+</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x15_ARG_0x03 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x15</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x09 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x09</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x07</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>IMU_COMMAND_0x02 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0c</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x27</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x11 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x11</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>UNKNOWN_COMMAND_0x0A <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0a</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x14</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0xff</span>, <span style="color:#ae81ff">0x35</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x46</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>IMU_COMMAND_0x04 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0c</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x27</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>ENABLE_HAPTICS <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0a</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x09</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x10 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x10</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x01 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x0c</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x03 <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x01</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>OUT_UNKNOWN_COMMAND_0x0A_ALT <span style="color:#f92672">=</span> bytes([<span style="color:#ae81ff">0x0a</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x02</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x04</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x03</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>])
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">send_usb_data</span>(ep_out, ep_in, data, description<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span>):
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
+</span></span><span style="display:flex;"><span> ep_out<span style="color:#f92672">.</span>write(data)
+</span></span><span style="display:flex;"><span> time<span style="color:#f92672">.</span>sleep(<span style="color:#ae81ff">0.01</span>)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
+</span></span><span style="display:flex;"><span> response <span style="color:#f92672">=</span> ep_in<span style="color:#f92672">.</span>read(<span style="color:#ae81ff">32</span>, timeout<span style="color:#f92672">=</span><span style="color:#ae81ff">100</span>)
+</span></span><span style="display:flex;"><span> hex_resp <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34; &#34;</span><span style="color:#f92672">.</span>join([<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">{</span>x<span style="color:#e6db74">:</span><span style="color:#e6db74">02x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span> <span style="color:#66d9ef">for</span> x <span style="color:#f92672">in</span> response])
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] Response: </span><span style="color:#e6db74">{</span>hex_resp<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e:
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> e<span style="color:#f92672">.</span>errno <span style="color:#f92672">==</span> <span style="color:#ae81ff">110</span>:
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] No response (Timeout)&#34;</span>)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">else</span>:
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] Read Error: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e:
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;[</span><span style="color:#e6db74">{</span>description<span style="color:#e6db74">}</span><span style="color:#e6db74">] Write Error: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">raise</span>
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">set_player_leds</span>(ep_out, ep_in, led_mask):
+</span></span><span style="display:flex;"><span> command <span style="color:#f92672">=</span> [
+</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x09</span>, <span style="color:#ae81ff">0x91</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x07</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x08</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>,
+</span></span><span style="display:flex;"><span> led_mask,
+</span></span><span style="display:flex;"><span> <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>, <span style="color:#ae81ff">0x00</span>
+</span></span><span style="display:flex;"><span> ]
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, bytes(command), <span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Set LED Mask: 0x</span><span style="color:#e6db74">{</span>led_mask<span style="color:#e6db74">:</span><span style="color:#e6db74">02x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">connect_usb</span>():
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">&#34;Searching for Nintendo Switch Controllers...&#34;</span>)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">match_device</span>(dev):
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">return</span> dev<span style="color:#f92672">.</span>idVendor <span style="color:#f92672">==</span> VENDOR_ID <span style="color:#f92672">and</span> dev<span style="color:#f92672">.</span>idProduct <span style="color:#f92672">in</span> PRODUCT_IDS
+</span></span><span style="display:flex;"><span> dev <span style="color:#f92672">=</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>find(custom_match<span style="color:#f92672">=</span>match_device)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> dev <span style="color:#f92672">is</span> <span style="color:#66d9ef">None</span>:
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">raise</span> <span style="color:#a6e22e">ValueError</span>(<span style="color:#e6db74">&#34;Device not found&#34;</span>)
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span> product_name <span style="color:#f92672">=</span> PRODUCT_IDS<span style="color:#f92672">.</span>get(dev<span style="color:#f92672">.</span>idProduct, <span style="color:#e6db74">&#34;Unknown Device&#34;</span>)
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Found </span><span style="color:#e6db74">{</span>product_name<span style="color:#e6db74">}</span><span style="color:#e6db74"> (ID: </span><span style="color:#e6db74">{</span>dev<span style="color:#f92672">.</span>idProduct<span style="color:#e6db74">:</span><span style="color:#e6db74">04x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">)&#34;</span>)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> dev<span style="color:#f92672">.</span>is_kernel_driver_active(USB_INTERFACE_NUMBER):
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">&#34;Detaching kernel driver...&#34;</span>)
+</span></span><span style="display:flex;"><span> dev<span style="color:#f92672">.</span>detach_kernel_driver(USB_INTERFACE_NUMBER)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e:
+</span></span><span style="display:flex;"><span> sys<span style="color:#f92672">.</span>exit(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Could not detach kernel driver: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
+</span></span><span style="display:flex;"><span> dev<span style="color:#f92672">.</span>set_configuration()
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">&#34;Configuration set.&#34;</span>)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e:
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Error setting configuration: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
+</span></span><span style="display:flex;"><span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>claim_interface(dev, USB_INTERFACE_NUMBER)
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Interface </span><span style="color:#e6db74">{</span>USB_INTERFACE_NUMBER<span style="color:#e6db74">}</span><span style="color:#e6db74"> claimed.&#34;</span>)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> usb<span style="color:#f92672">.</span>core<span style="color:#f92672">.</span>USBError <span style="color:#66d9ef">as</span> e:
+</span></span><span style="display:flex;"><span> sys<span style="color:#f92672">.</span>exit(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Could not claim interface: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
+</span></span><span style="display:flex;"><span> cfg <span style="color:#f92672">=</span> dev<span style="color:#f92672">.</span>get_active_configuration()
+</span></span><span style="display:flex;"><span> intf <span style="color:#f92672">=</span> cfg[(USB_INTERFACE_NUMBER,<span style="color:#ae81ff">0</span>)]
+</span></span><span style="display:flex;"><span> ep_out <span style="color:#f92672">=</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>find_descriptor(
+</span></span><span style="display:flex;"><span> intf,
+</span></span><span style="display:flex;"><span> custom_match <span style="color:#f92672">=</span> <span style="color:#66d9ef">lambda</span> e: usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>endpoint_direction(e<span style="color:#f92672">.</span>bEndpointAddress) <span style="color:#f92672">==</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>ENDPOINT_OUT)
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span> ep_in <span style="color:#f92672">=</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>find_descriptor(
+</span></span><span style="display:flex;"><span> intf,
+</span></span><span style="display:flex;"><span> custom_match <span style="color:#f92672">=</span>
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">lambda</span> e: usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>endpoint_direction(e<span style="color:#f92672">.</span>bEndpointAddress) <span style="color:#f92672">==</span> usb<span style="color:#f92672">.</span>util<span style="color:#f92672">.</span>ENDPOINT_IN
+</span></span><span style="display:flex;"><span> )
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> ep_out:
+</span></span><span style="display:flex;"><span> sys<span style="color:#f92672">.</span>exit(<span style="color:#e6db74">&#34;Could not find OUT endpoint&#34;</span>)
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Found Endpoint OUT: 0x</span><span style="color:#e6db74">{</span>ep_out<span style="color:#f92672">.</span>bEndpointAddress<span style="color:#e6db74">:</span><span style="color:#e6db74">02x</span><span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">&#34;Starting Initialization Sequence...&#34;</span>)
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, INIT_COMMAND_0x03, <span style="color:#e6db74">&#34;Init 0x03&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x07, <span style="color:#e6db74">&#34;Unknown 0x07&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x16, <span style="color:#e6db74">&#34;Unknown 0x16&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, REQUEST_CONTROLLER_MAC, <span style="color:#e6db74">&#34;Req MAC&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, LTK_REQUEST, <span style="color:#e6db74">&#34;Req LTK&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x15_ARG_0x03, <span style="color:#e6db74">&#34;Unknown 0x15&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x09, <span style="color:#e6db74">&#34;Unknown 0x09&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, IMU_COMMAND_0x02, <span style="color:#e6db74">&#34;IMU 0x02&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x11, <span style="color:#e6db74">&#34;OUT Unknown 0x11&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, UNKNOWN_COMMAND_0x0A, <span style="color:#e6db74">&#34;Unknown 0x0A&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, IMU_COMMAND_0x04, <span style="color:#e6db74">&#34;IMU 0x04&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, ENABLE_HAPTICS, <span style="color:#e6db74">&#34;Enable Haptics&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x10, <span style="color:#e6db74">&#34;OUT Unknown 0x10&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x01, <span style="color:#e6db74">&#34;OUT Unknown 0x01&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x03, <span style="color:#e6db74">&#34;OUT Unknown 0x03&#34;</span>)
+</span></span><span style="display:flex;"><span> send_usb_data(ep_out, ep_in, OUT_UNKNOWN_COMMAND_0x0A_ALT, <span style="color:#e6db74">&#34;OUT Unknown 0x0A Alt&#34;</span>)
+</span></span><span style="display:flex;"><span> set_player_leds(ep_out, ep_in, <span style="color:#ae81ff">0x0F</span>)
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">&#34;Controller initialization sequence complete! All LEDs should be on.&#34;</span>)
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">Exception</span> <span style="color:#66d9ef">as</span> e:
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Error during sequence: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
+</span></span><span style="display:flex;"><span>
+</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;__main__&#34;</span>:
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">try</span>:
+</span></span><span style="display:flex;"><span> connect_usb()
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">ValueError</span> <span style="color:#66d9ef">as</span> e:
+</span></span><span style="display:flex;"><span> print(e)
+</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">except</span> <span style="color:#a6e22e">Exception</span> <span style="color:#66d9ef">as</span> e:
+</span></span><span style="display:flex;"><span> print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Unexpected error: </span><span style="color:#e6db74">{</span>e<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)
+</span></span></code></pre></div><p><strong>Steps</strong></p>
+<ol start="0">
+<li>(Optional) First Create a virtual environment</li>
+<li>Install pyusb via <code>pip install pyusb</code></li>
+<li>Plug your Pro Controller 2 in via USB</li>
+<li>Run the script</li>
+</ol>
+<p>If all 4 of the player indicator LEDs light up (the square ones near the charging port), then that means you should be good to go!</p>
+<p>You&rsquo;ll need to re-run this script each time you plug/unplug or restart your machine.</p>
+<p>This is pretty much a copy of the <a href="https://handheldlegend.github.io/procon2tool/">online Procon 2 Enabler Tool</a> but WebHID is dodgy on the Firefox fork I&rsquo;m using, plus its annoying having to open this page each time.</p>
+
+ </div>
+
+
+
+
+
+
+ <section id="comments" class="webmentions">
+ <h2 class="wm-title">Webmentions</h2>
+ <div id="mentions" class="wm-list">Loading…</div>
+</section>
+
+<style>
+.webmentions {
+ margin-top: 2.5rem;
+ padding-top: 1rem;
+ border-top: 2px dashed var(--hrcolor);
+}
+
+.webmentions .wm-title {
+ color: var(--titlecolor);
+ margin-bottom: 1rem;
+}
+
+.wm-list {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+
+.wm-reactions {
+ margin-bottom: 1.5rem;
+}
+
+.wm-reaction-group {
+ margin-bottom: 1rem;
+}
+
+.wm-reaction-title {
+ font-size: 1.1rem;
+ font-weight: 600;
+ color: var(--titlecolor);
+ margin-bottom: 0.5rem;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.wm-avatar-grid {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 4px;
+ align-items: center;
+}
+
+.wm-avatar {
+ position: relative;
+ display: inline-block;
+}
+
+.wm-avatar img {
+ width: 40px;
+ height: 40px;
+ border-radius: 50%;
+ border: 2px solid var(--hrcolor);
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
+}
+
+.wm-avatar:hover img {
+ transform: scale(1.1);
+ box-shadow: 0 4px 12px rgba(255, 140, 200, 0.4);
+}
+
+.wm-avatar-tooltip {
+ position: absolute;
+ bottom: 120%;
+ left: 50%;
+ transform: translateX(-50%);
+ background: var(--blockquotecolor);
+ color: var(--titlecolor);
+ padding: 4px 8px;
+ border-radius: 4px;
+ font-size: 0.8rem;
+ white-space: nowrap;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.2s ease;
+ z-index: 10;
+ border: 1px solid var(--hrcolor);
+}
+
+.wm-avatar:hover .wm-avatar-tooltip {
+ opacity: 1;
+}
+
+
+.wm-comments-header {
+ font-size: 1.1rem;
+ font-weight: 600;
+ color: var(--titlecolor);
+ margin-bottom: 0.5rem;
+ margin-top: 1rem;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+
+.wm-regular {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.wm {
+ display: flex;
+ gap: 0.6rem;
+ padding: 0.6rem 0.75rem;
+ border-radius: 10px;
+ background: var(--alertbgcolor);
+ border: 1px solid var(--hrcolor);
+ box-shadow: 0 0 6px rgba(255, 180, 220, 0.22);
+}
+
+.wm-author img {
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ box-shadow: 0 0 4px rgba(255, 140, 200, 0.35);
+}
+
+.wm-body {
+ flex: 1;
+ font-size: 0.9rem;
+}
+
+.wm-author-name a {
+ font-weight: 600;
+ color: var(--linkcolor);
+}
+
+.wm-type {
+ font-size: 0.8rem;
+ margin-top: 2px;
+ color: var(--titlecolor);
+}
+
+.wm-content {
+ margin-top: 4px;
+ padding: 6px 8px;
+ font-size: 0.9rem;
+ background: var(--blockquotecolor);
+ border-left: 3px solid var(--hrcolor);
+ border-radius: 6px;
+}
+
+.wm-meta {
+ margin-top: 3px;
+ font-size: 0.75rem;
+ opacity: 0.7;
+}
+
+.wm-meta a {
+ color: var(--linkcolor);
+}
+
+
+@media (max-width: 600px) {
+ .wm-avatar img {
+ width: 32px;
+ height: 32px;
+ }
+
+ .wm-avatar-grid {
+ gap: 3px;
+ }
+
+ .wm-reaction-title {
+ font-size: 1rem;
+ }
+
+ .wm-comments-header {
+ font-size: 1rem;
+ }
+}
+</style>
+
+<script>
+const PAGE_URL = "https:\/\/micro.pinapelz.moe\/posts\/2025-12-04-procon2-hid-tool\/";
+
+async function loadMentions() {
+ const url =
+ "https://webmention.io/api/mentions.jf2?domain=micro.pinapelz.moe&token=hdjQAqlZwgJmSuPSiU8h8w";
+
+ const res = await fetch(url);
+ const data = await res.json();
+
+ const container = document.getElementById("mentions");
+ container.innerHTML = "";
+
+
+ const mentions = data.children.filter(m => {
+ const t = m["wm-target"];
+ const inReply = m["in-reply-to"];
+ const likeOf = m["like-of"];
+ const repostOf = m["repost-of"];
+ const mentionOf = m["mention-of"];
+
+ return (
+ t === PAGE_URL ||
+ inReply === PAGE_URL ||
+ likeOf === PAGE_URL ||
+ repostOf === PAGE_URL ||
+ mentionOf === PAGE_URL
+ );
+ });
+
+ if (!mentions.length) {
+ container.innerHTML = "<p>No webmentions yet.</p>";
+ return;
+ }
+
+
+ const likes = mentions.filter(m => m["wm-property"] === "like-of");
+ const reposts = mentions.filter(m => m["wm-property"] === "repost-of");
+ const replies = mentions.filter(m => m["wm-property"] === "in-reply-to");
+ const regularMentions = mentions.filter(m =>
+ !["like-of", "repost-of", "in-reply-to"].includes(m["wm-property"])
+ );
+
+
+ const reactionsDiv = document.createElement("div");
+ reactionsDiv.className = "wm-reactions";
+
+
+ if (reposts.length > 0) {
+ const repostGroup = document.createElement("div");
+ repostGroup.className = "wm-reaction-group";
+
+ const repostTitle = document.createElement("div");
+ repostTitle.className = "wm-reaction-title";
+ repostTitle.textContent = `${reposts.length} Repost${reposts.length !== 1 ? 's' : ''}`;
+
+ const repostGrid = document.createElement("div");
+ repostGrid.className = "wm-avatar-grid";
+
+ reposts.forEach(mention => {
+ const author = mention.author || {};
+ const avatarDiv = document.createElement("div");
+ avatarDiv.className = "wm-avatar";
+
+ avatarDiv.innerHTML = `
+ <a href="${author.url || "#"}" target="_blank">
+ <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" />
+ </a>
+ <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div>
+ `;
+
+ repostGrid.appendChild(avatarDiv);
+ });
+
+ repostGroup.appendChild(repostTitle);
+ repostGroup.appendChild(repostGrid);
+ reactionsDiv.appendChild(repostGroup);
+ }
+
+
+ if (likes.length > 0) {
+ const likeGroup = document.createElement("div");
+ likeGroup.className = "wm-reaction-group";
+
+ const likeTitle = document.createElement("div");
+ likeTitle.className = "wm-reaction-title";
+ likeTitle.textContent = `${likes.length} Like${likes.length !== 1 ? 's' : ''}`;
+
+ const likeGrid = document.createElement("div");
+ likeGrid.className = "wm-avatar-grid";
+
+ likes.forEach(mention => {
+ const author = mention.author || {};
+ const avatarDiv = document.createElement("div");
+ avatarDiv.className = "wm-avatar";
+
+ avatarDiv.innerHTML = `
+ <a href="${author.url || "#"}" target="_blank">
+ <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}" />
+ </a>
+ <div class="wm-avatar-tooltip">${author.name || 'Unknown'}</div>
+ `;
+
+ likeGrid.appendChild(avatarDiv);
+ });
+
+ likeGroup.appendChild(likeTitle);
+ likeGroup.appendChild(likeGrid);
+ reactionsDiv.appendChild(likeGroup);
+ }
+
+
+ if (reactionsDiv.children.length > 0) {
+ container.appendChild(reactionsDiv);
+ }
+
+
+ const regularMentionsToShow = [...replies, ...regularMentions];
+
+ if (regularMentionsToShow.length > 0) {
+
+ const commentsHeader = document.createElement("div");
+ commentsHeader.className = "wm-comments-header";
+ commentsHeader.textContent = "Comments";
+ container.appendChild(commentsHeader);
+
+ const regularDiv = document.createElement("div");
+ regularDiv.className = "wm-regular";
+
+ regularMentionsToShow.forEach(m => {
+ const div = document.createElement("div");
+ div.className = "wm";
+
+ const author = m.author || {};
+ const content = m.content || {};
+ const type =
+ m["wm-property"] === "in-reply-to" ? "replied đź’¬" :
+ "mentioned this";
+
+ div.innerHTML = `
+ <div class="wm-author">
+ <img src="${author.photo || ""}" alt="${author.name || 'Unknown'}">
+ </div>
+
+ <div class="wm-body">
+ <div class="wm-author-name">
+ <a href="${author.url || "#"}" target="_blank">
+ ${author.name || "Unknown"}
+ </a>
+ </div>
+
+ <div class="wm-type">${type}</div>
+
+ ${content.text ? `<div class="wm-content">${content.text}</div>` : ""}
+
+ <div class="wm-meta">
+ <a href="${m.url}" target="_blank">source</a> •
+ ${m["wm-received"]
+ ? new Date(m["wm-received"]).toLocaleString()
+ : ""}
+ </div>
+ </div>
+ `;
+ regularDiv.appendChild(div);
+ });
+
+ container.appendChild(regularDiv);
+ }
+
+
+ if (container.children.length === 0) {
+ container.innerHTML = "<p>No webmentions yet.</p>";
+ }
+}
+
+loadMentions();
+</script>
+
+ </article>
+ </main>
+
+ <hr />
+<footer>
+ <p>
+ <a href="https://github.com/pinapelz"><b>Github</b></a>.
+ <a href="https://pinapelz.moe"><b>pinapelz.moe</b></a>.
+ </p>
+
+
+
+ <p style="text-align: center" class="copyright">
+ &copy; <a href="https://micro.pinapelz.moe/"><b>micro.pinapelz.moe</b></a>.
+ </p>
+</footer>
+
+</body>
+</html>
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage