syntax highlighting in html

12/07/24

Words: 693 (and a bunch of html you don’t need to read)

premise

syntax highlighting is really cool. vscode does a really great job of visually communicating what every piece of code is, but a lot of this information is lost when you copy and paste the code into markdown or html. i want to make my code look pretty in my blog posts.

idea(s)

i have a few potential ideas for how i can make this work out:

  1. find a tool that will do it all for me
  2. do it all manually by hand

i would obviously prefer to avoid the latter, so i’ll look for tools first.

attempted solutions

00 - pandoc

in attempts to find something to export my markdown file (what i am writing this in) into html that i can put on my website, i came across pandoc, a neat document converter. it even has a handy vscode plugin that can do it all from a command in the editor.

this is wonderful and all, but it crucially doesn’t generate the colors for you, and… honestly does a pretty terrible job of labelling the code. most of it is left unlabelled and some are even labelled incorrectly.


<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="at">@app_commands.allowed_contexts</span>(guilds<span class="op">=</span><span class="va">True</span>, dms<span class="op">=</span><span class="va">True</span>, private_channels<span class="op">=</span><span class="va">True</span>)</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="at">@tree.context_menu</span>(name<span class="op">=</span><span class="st">&quot;fixfiles&quot;</span>)</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="cf">async</span> <span class="kw">def</span> fixfiles(interaction: discord.Interaction, message: discord.Message):</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a> <span class="cf">await</span> interaction.response.defer()</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a> images <span class="op">=</span> []</span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a> hardware <span class="op">=</span> path.exists(<span class="st">&quot;/dev/dri/renderD128&quot;</span>)</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a> params <span class="op">=</span> [<span class="st">&quot;-vaapi_device&quot;</span>, <span class="st">&quot;/dev/dri/renderD128&quot;</span>, <span class="st">&quot;-vf&quot;</span>, <span class="st">&quot;hwupload,scale_vaapi=w=-2:h=&#39;min(720,iw)&#39;:format=nv12&quot;</span>, <span class="st">&quot;-c:v&quot;</span>, <span class="st">&quot;h264_vaapi&quot;</span>, <span class="st">&quot;-b:v&quot;</span>, <span class="st">&quot;1M&quot;</span>] <span class="cf">if</span> hardware <span class="cf">else</span> [<span class="st">&quot;-c:v&quot;</span>, <span class="st">&quot;h264&quot;</span>, <span class="st">&quot;-vf&quot;</span>, <span class="st">&quot;scale=-2:&#39;min(720,iw)&#39;&quot;</span>]</span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> attachment <span class="kw">in</span> message.attachments:</span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a> extension <span class="op">=</span> <span class="st">&quot;&quot;</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a> attachment_data <span class="op">=</span> <span class="cf">await</span> attachment.read()</span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a> mime <span class="op">=</span> magic.from_buffer(attachment_data, mime <span class="op">=</span> <span class="va">True</span>).split(<span class="st">&quot;/&quot;</span>)</span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a> contentType <span class="op">=</span> mime[<span class="dv">0</span>]</span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a> contentExtension <span class="op">=</span> mime[<span class="dv">1</span>]</span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a> <span class="cf">match</span> contentType:</span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a> <span class="cf">case</span> <span class="st">&quot;image&quot;</span>:</span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> contentExtension <span class="op">==</span> <span class="st">&quot;gif&quot;</span>:</span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a> <span class="cf">continue</span></span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a> command <span class="op">=</span> [<span class="st">&quot;ffmpeg&quot;</span>, <span class="st">&quot;-i&quot;</span>, <span class="st">&quot;pipe:0&quot;</span>, <span class="st">&quot;-f&quot;</span>, <span class="st">&quot;image2&quot;</span>, <span class="st">&quot;pipe:1&quot;</span>]</span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a> extension <span class="op">=</span> <span class="st">&quot;jpg&quot;</span></span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a> <span class="cf">case</span> <span class="st">&quot;video&quot;</span>:</span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a> command <span class="op">=</span> [<span class="st">&quot;ffmpeg&quot;</span>, <span class="st">&quot;-i&quot;</span>, <span class="st">&quot;pipe:0&quot;</span>, <span class="op">*</span>params, <span class="st">&quot;-c:a&quot;</span>, <span class="st">&quot;aac&quot;</span>, <span class="st">&quot;-pix_fmt&quot;</span>, <span class="st">&quot;yuv420p&quot;</span>, <span class="st">&quot;-movflags&quot;</span>, <span class="st">&quot;frag_keyframe+empty_moov+faststart&quot;</span>, <span class="st">&quot;-f&quot;</span>, <span class="st">&quot;mp4&quot;</span>, <span class="st">&quot;pipe:1&quot;</span>]</span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a> extension <span class="op">=</span> <span class="st">&quot;mp4&quot;</span></span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true" tabindex="-1"></a> <span class="cf">case</span> <span class="st">&quot;audio&quot;</span>:</span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a> command <span class="op">=</span> [<span class="st">&quot;ffmpeg&quot;</span>, <span class="st">&quot;-i&quot;</span>, <span class="st">&quot;pipe:0&quot;</span>, <span class="st">&quot;-loop&quot;</span>, <span class="st">&quot;1&quot;</span>, <span class="st">&quot;-r&quot;</span>, <span class="st">&quot;10&quot;</span>, <span class="st">&quot;-i&quot;</span>, <span class="st">&quot;assets/sus.webp&quot;</span>, <span class="st">&quot;-shortest&quot;</span>, <span class="op">*</span>params, <span class="st">&quot;-c:a&quot;</span>, <span class="st">&quot;aac&quot;</span>, <span class="st">&quot;-pix_fmt&quot;</span>, <span class="st">&quot;yuv420p&quot;</span>, <span class="st">&quot;-movflags&quot;</span>, <span class="st">&quot;frag_keyframe+empty_moov+faststart&quot;</span>, <span class="st">&quot;-f&quot;</span>, <span class="st">&quot;mp4&quot;</span>, <span class="st">&quot;pipe:1&quot;</span>]</span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a> extension <span class="op">=</span> <span class="st">&quot;mp4&quot;</span></span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true" tabindex="-1"></a> <span class="cf">case</span> _:</span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true" tabindex="-1"></a> <span class="cf">continue</span></span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-31"><a href="#cb12-31" aria-hidden="true" tabindex="-1"></a> process <span class="op">=</span> run(command, <span class="bu">input</span> <span class="op">=</span> attachment_data, stdout <span class="op">=</span> PIPE)</span>
<span id="cb12-32"><a href="#cb12-32" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> process.returncode <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb12-33"><a href="#cb12-33" aria-hidden="true" tabindex="-1"></a> discord_file <span class="op">=</span> discord.File(fp <span class="op">=</span> BytesIO(process.stdout), filename <span class="op">=</span> <span class="ss">f&quot;</span><span class="sc">{</span>attachment<span class="sc">.</span>filename<span class="sc">.</span>split(<span class="st">&quot;.&quot;</span>)[<span class="dv">0</span>]<span class="sc">}</span><span class="ss">.</span><span class="sc">{</span>extension<span class="sc">}</span><span class="ss">&quot;</span>)</span>
<span id="cb12-34"><a href="#cb12-34" aria-hidden="true" tabindex="-1"></a> images.append(discord_file)</span>
<span id="cb12-35"><a href="#cb12-35" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="bu">len</span>(images) <span class="op">&gt;</span> <span class="dv">0</span>:</span>
<span id="cb12-36"><a href="#cb12-36" aria-hidden="true" tabindex="-1"></a> <span class="cf">await</span> interaction.followup.send(files <span class="op">=</span> images)</span>
<span id="cb12-37"><a href="#cb12-37" aria-hidden="true" tabindex="-1"></a> <span class="cf">else</span>:</span>
<span id="cb12-38"><a href="#cb12-38" aria-hidden="true" tabindex="-1"></a> <span class="cf">await</span> interaction.followup.send(<span class="st">&quot;No files to fix&quot;</span>)</span></code></pre></div>

the amount of code that this left unlabelled or not labelled properly was… frustrating to say the least. i wanted to find another solution, one that had better coverage in the highlighting and that didn’t require me to choose the colors myself.

01 - prism.js

while troubleshooting this, annie recommended trying prism.js. after about 15 minutes of tinkering, i got it running in node, and tried using its output in the same way the pandoc code would be used.


<span class="token decorator annotation punctuation">@app_commands<span class="token punctuation">.</span>allowed_installs</span><span class="token punctuation">(</span>guilds<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">,</span> users<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">)</span>
<span class="token decorator annotation punctuation">@app_commands<span class="token punctuation">.</span>allowed_contexts</span><span class="token punctuation">(</span>guilds<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">,</span> dms<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">,</span> private_channels<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">)</span>
<span class="token decorator annotation punctuation">@tree<span class="token punctuation">.</span>context_menu</span><span class="token punctuation">(</span>name<span class="token operator">=</span><span class="token string">"fixfiles"</span><span class="token punctuation">)</span>
<span class="token keyword">async</span> <span class="token keyword">def</span> <span class="token function">fixfiles</span><span class="token punctuation">(</span>interaction<span class="token punctuation">:</span> discord<span class="token punctuation">.</span>Interaction<span class="token punctuation">,</span> message<span class="token punctuation">:</span> discord<span class="token punctuation">.</span>Message<span class="token punctuation">)</span><span class="token punctuation">:</span>
<span class="token keyword">await</span> interaction<span class="token punctuation">.</span>response<span class="token punctuation">.</span>defer<span class="token punctuation">(</span><span class="token punctuation">)</span>
images <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
hardware <span class="token operator">=</span> path<span class="token punctuation">.</span>exists<span class="token punctuation">(</span><span class="token string">"/dev/dri/renderD128"</span><span class="token punctuation">)</span>
params <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"-vaapi_device"</span><span class="token punctuation">,</span> <span class="token string">"/dev/dri/renderD128"</span><span class="token punctuation">,</span> <span class="token string">"-vf"</span><span class="token punctuation">,</span> <span class="token string">"hwupload,scale_vaapi=w=-2:h='min(720,iw)':format=nv12"</span><span class="token punctuation">,</span> <span class="token string">"-c:v"</span><span class="token punctuation">,</span> <span class="token string">"h264_vaapi"</span><span class="token punctuation">,</span> <span class="token string">"-b:v"</span><span class="token punctuation">,</span> <span class="token string">"1M"</span><span class="token punctuation">]</span> <span class="token keyword">if</span> hardware <span class="token keyword">else</span> <span class="token punctuation">[</span><span class="token string">"-c:v"</span><span class="token punctuation">,</span> <span class="token string">"h264"</span><span class="token punctuation">,</span> <span class="token string">"-vf"</span><span class="token punctuation">,</span> <span class="token string">"scale=-2:'min(720,iw)'"</span><span class="token punctuation">]</span>

<span class="token keyword">for</span> attachment <span class="token keyword">in</span> message<span class="token punctuation">.</span>attachments<span class="token punctuation">:</span>
extension <span class="token operator">=</span> <span class="token string">""</span>
attachment_data <span class="token operator">=</span> <span class="token keyword">await</span> attachment<span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span>
mime <span class="token operator">=</span> magic<span class="token punctuation">.</span>from_buffer<span class="token punctuation">(</span>attachment_data<span class="token punctuation">,</span> mime <span class="token operator">=</span> <span class="token boolean">True</span><span class="token punctuation">)</span><span class="token punctuation">.</span>split<span class="token punctuation">(</span><span class="token string">"/"</span><span class="token punctuation">)</span>
contentType <span class="token operator">=</span> mime<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>
contentExtension <span class="token operator">=</span> mime<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span>
<span class="token keyword">match</span> contentType<span class="token punctuation">:</span>
<span class="token keyword">case</span> <span class="token string">"image"</span><span class="token punctuation">:</span>
<span class="token keyword">if</span> contentExtension <span class="token operator">==</span> <span class="token string">"gif"</span><span class="token punctuation">:</span>
<span class="token keyword">continue</span>
command <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"ffmpeg"</span><span class="token punctuation">,</span> <span class="token string">"-i"</span><span class="token punctuation">,</span> <span class="token string">"pipe:0"</span><span class="token punctuation">,</span> <span class="token string">"-f"</span><span class="token punctuation">,</span> <span class="token string">"image2"</span><span class="token punctuation">,</span> <span class="token string">"pipe:1"</span><span class="token punctuation">]</span>
extension <span class="token operator">=</span> <span class="token string">"jpg"</span>
<span class="token keyword">case</span> <span class="token string">"video"</span><span class="token punctuation">:</span>
command <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"ffmpeg"</span><span class="token punctuation">,</span> <span class="token string">"-i"</span><span class="token punctuation">,</span> <span class="token string">"pipe:0"</span><span class="token punctuation">,</span> <span class="token operator">*</span>params<span class="token punctuation">,</span> <span class="token string">"-c:a"</span><span class="token punctuation">,</span> <span class="token string">"aac"</span><span class="token punctuation">,</span> <span class="token string">"-pix_fmt"</span><span class="token punctuation">,</span> <span class="token string">"yuv420p"</span><span class="token punctuation">,</span> <span class="token string">"-movflags"</span><span class="token punctuation">,</span> <span class="token string">"frag_keyframe+empty_moov+faststart"</span><span class="token punctuation">,</span> <span class="token string">"-f"</span><span class="token punctuation">,</span> <span class="token string">"mp4"</span><span class="token punctuation">,</span> <span class="token string">"pipe:1"</span><span class="token punctuation">]</span>
extension <span class="token operator">=</span> <span class="token string">"mp4"</span>
<span class="token keyword">case</span> <span class="token string">"audio"</span><span class="token punctuation">:</span>
command <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"ffmpeg"</span><span class="token punctuation">,</span> <span class="token string">"-i"</span><span class="token punctuation">,</span> <span class="token string">"pipe:0"</span><span class="token punctuation">,</span> <span class="token string">"-loop"</span><span class="token punctuation">,</span> <span class="token string">"1"</span><span class="token punctuation">,</span> <span class="token string">"-r"</span><span class="token punctuation">,</span> <span class="token string">"10"</span><span class="token punctuation">,</span> <span class="token string">"-i"</span><span class="token punctuation">,</span> <span class="token string">"assets/sus.webp"</span><span class="token punctuation">,</span> <span class="token string">"-shortest"</span><span class="token punctuation">,</span> <span class="token operator">*</span>params<span class="token punctuation">,</span> <span class="token string">"-c:a"</span><span class="token punctuation">,</span> <span class="token string">"aac"</span><span class="token punctuation">,</span> <span class="token string">"-pix_fmt"</span><span class="token punctuation">,</span> <span class="token string">"yuv420p"</span><span class="token punctuation">,</span> <span class="token string">"-movflags"</span><span class="token punctuation">,</span> <span class="token string">"frag_keyframe+empty_moov+faststart"</span><span class="token punctuation">,</span> <span class="token string">"-f"</span><span class="token punctuation">,</span> <span class="token string">"mp4"</span><span class="token punctuation">,</span> <span class="token string">"pipe:1"</span><span class="token punctuation">]</span>
extension <span class="token operator">=</span> <span class="token string">"mp4"</span>
<span class="token keyword">case</span> <span class="token keyword">_</span><span class="token punctuation">:</span>
<span class="token keyword">continue</span>

process <span class="token operator">=</span> run<span class="token punctuation">(</span>command<span class="token punctuation">,</span> <span class="token builtin">input</span> <span class="token operator">=</span> attachment_data<span class="token punctuation">,</span> stdout <span class="token operator">=</span> PIPE<span class="token punctuation">)</span>
<span class="token keyword">if</span> process<span class="token punctuation">.</span>returncode <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">:</span>
discord_file <span class="token operator">=</span> discord<span class="token punctuation">.</span>File<span class="token punctuation">(</span>fp <span class="token operator">=</span> BytesIO<span class="token punctuation">(</span>process<span class="token punctuation">.</span>stdout<span class="token punctuation">)</span><span class="token punctuation">,</span> filename <span class="token operator">=</span> <span class="token string-interpolation"><span class="token string">f"{attachment.filename.split("</span></span><span class="token punctuation">.</span><span class="token string">")[0]}.{extension}"</span><span class="token punctuation">)</span>
images<span class="token punctuation">.</span>append<span class="token punctuation">(</span>discord_file<span class="token punctuation">)</span>
<span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>images<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">:</span>
<span class="token keyword">await</span> interaction<span class="token punctuation">.</span>followup<span class="token punctuation">.</span>send<span class="token punctuation">(</span>files <span class="token operator">=</span> images<span class="token punctuation">)</span>
<span class="token keyword">else</span><span class="token punctuation">:</span>
<span class="token keyword">await</span> interaction<span class="token punctuation">.</span>followup<span class="token punctuation">.</span>send<span class="token punctuation">(</span><span class="token string">"No files to fix"</span><span class="token punctuation">)</span>

this yielded much better results, with better coverage in the code, and much less code left behind. additionally, i could use a theme someone else made for prism to mimic the vscode dark+ theme (what i use). however, this still wasn’t good enough for me. it still didn’t look as pretty as i wanted it to, but then i took a shower and had an epiphany

02 - pandocs again (kinda)

while in the shower, i had a big realization. surely there had to be some way to copy the text from vscode including the syntax highlighting, because you can do as such in other places like word and google docs. if i could manage to figure this out, i could do the following: 1. copy with syntax highlighting 2. paste into a doc 3. export as docx 4. use pandoc to convert docx into html 5. insert html into pre>code tags

this was a great plan, and worked great until step 4. pandoc made this harder than it needed to be, and instead i ended up using an online converter instead. this… just sort of worked. it exported the text as a bunch of p tags with spans instead of them. this meant i had to fix these by pulling the spans out of the p tags before inputting them into my code tags, but i did that with a simple python script:


with open("code.html", "r+") as f:
d = f.readlines()
f.seek(0)
for line in d:
if line.startswith("<span"):
f.write(line)
f.truncate()

this fully worked! i got a fully functional perfect paste of my code just as it looked in vscode.


<span style="font-family:'Courier New'; color:#dcdcaa">@</span><span style="font-family:'Courier New'; color:#4ec9b0">app_commands</span><span style="font-family:'Courier New'; color:#dcdcaa">.allowed_installs</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#9cdcfe">guilds</span><span style="font-family:'Courier New'; color:#d4d4d4">=</span><span style="font-family:'Courier New'; color:#4fc1ff">True</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#9cdcfe">users</span><span style="font-family:'Courier New'; color:#d4d4d4">=</span><span style="font-family:'Courier New'; color:#4fc1ff">True</span><span style="font-family:'Courier New'; color:#d4d4d4">)</span>
<span style="font-family:'Courier New'; color:#dcdcaa">@</span><span style="font-family:'Courier New'; color:#4ec9b0">app_commands</span><span style="font-family:'Courier New'; color:#dcdcaa">.allowed_contexts</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#9cdcfe">guilds</span><span style="font-family:'Courier New'; color:#d4d4d4">=</span><span style="font-family:'Courier New'; color:#4fc1ff">True</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#9cdcfe">dms</span><span style="font-family:'Courier New'; color:#d4d4d4">=</span><span style="font-family:'Courier New'; color:#4fc1ff">True</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#9cdcfe">private_channels</span><span style="font-family:'Courier New'; color:#d4d4d4">=</span><span style="font-family:'Courier New'; color:#4fc1ff">True</span><span style="font-family:'Courier New'; color:#d4d4d4">)</span>
<span style="font-family:'Courier New'; color:#dcdcaa">@</span><span style="font-family:'Courier New'; color:#9cdcfe">tree</span><span style="font-family:'Courier New'; color:#dcdcaa">.context_menu</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#9cdcfe">name</span><span style="font-family:'Courier New'; color:#d4d4d4">=</span><span style="font-family:'Courier New'; color:#ce9178">"fixfiles"</span><span style="font-family:'Courier New'; color:#d4d4d4">)</span>
<span style="font-family:'Courier New'; color:#569cd6">async</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#569cd6">def</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#dcdcaa">fixfiles</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#9cdcfe">interaction</span><span style="font-family:'Courier New'; color:#d4d4d4">: </span><span style="font-family:'Courier New'; color:#4ec9b0">discord</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#4ec9b0">Interaction</span><span style="font-family:'Courier New'; color:#d4d4d4">,</span><span style="font-family:'Courier New'; color:#d4d4d4">&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">message</span><span style="font-family:'Courier New'; color:#d4d4d4">: </span><span style="font-family:'Courier New'; color:#4ec9b0">discord</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#4ec9b0">Message</span><span style="font-family:'Courier New'; color:#d4d4d4">):</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">await</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#9cdcfe">interaction</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#9cdcfe">response</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#dcdcaa">defer</span><span style="font-family:'Courier New'; color:#d4d4d4">()</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">images</span><span style="font-family:'Courier New'; color:#d4d4d4"> = []</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">hardware</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#9cdcfe">path</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#dcdcaa">exists</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#ce9178">"/dev/dri/renderD128"</span><span style="font-family:'Courier New'; color:#d4d4d4">)</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">params</span><span style="font-family:'Courier New'; color:#d4d4d4"> = [</span><span style="font-family:'Courier New'; color:#ce9178">"-vaapi_device"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"/dev/dri/renderD128"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-vf"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"hwupload,scale_vaapi=w=-2:h='min(720,iw)':format=nv12"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-c:v"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"h264_vaapi"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-b:v"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"1M"</span><span style="font-family:'Courier New'; color:#d4d4d4">] </span><span style="font-family:'Courier New'; color:#c586c0">if</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#9cdcfe">hardware</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#c586c0">else</span><span style="font-family:'Courier New'; color:#d4d4d4"> [</span><span style="font-family:'Courier New'; color:#ce9178">"-c:v"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"h264"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-vf"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"scale=-2:'min(720,iw)'"</span><span style="font-family:'Courier New'; color:#d4d4d4">]</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">for</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#9cdcfe">attachment</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#c586c0">in</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#9cdcfe">message</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#9cdcfe">attachments</span><span style="font-family:'Courier New'; color:#d4d4d4">:</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">extension</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#ce9178">""</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">attachment_data</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#c586c0">await</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#9cdcfe">attachment</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#dcdcaa">read</span><span style="font-family:'Courier New'; color:#d4d4d4">()</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">mime</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#4ec9b0">magic</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#dcdcaa">from_buffer</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#9cdcfe">attachment_data</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#9cdcfe">mime</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#4fc1ff">True</span><span style="font-family:'Courier New'; color:#d4d4d4">).</span><span style="font-family:'Courier New'; color:#dcdcaa">split</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#ce9178">"/"</span><span style="font-family:'Courier New'; color:#d4d4d4">)</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">contentType</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#9cdcfe">mime</span><span style="font-family:'Courier New'; color:#d4d4d4">[</span><span style="font-family:'Courier New'; color:#b5cea8">0</span><span style="font-family:'Courier New'; color:#d4d4d4">]</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">contentExtension</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#9cdcfe">mime</span><span style="font-family:'Courier New'; color:#d4d4d4">[</span><span style="font-family:'Courier New'; color:#b5cea8">1</span><span style="font-family:'Courier New'; color:#d4d4d4">]</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">match</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#9cdcfe">contentType</span><span style="font-family:'Courier New'; color:#d4d4d4">:</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">case</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#ce9178">"image"</span><span style="font-family:'Courier New'; color:#d4d4d4">:</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">if</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#9cdcfe">contentExtension</span><span style="font-family:'Courier New'; color:#d4d4d4"> == </span><span style="font-family:'Courier New'; color:#ce9178">"gif"</span><span style="font-family:'Courier New'; color:#d4d4d4">:</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">continue</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">command</span><span style="font-family:'Courier New'; color:#d4d4d4"> = [</span><span style="font-family:'Courier New'; color:#ce9178">"ffmpeg"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-i"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"pipe:0"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-f"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"image2"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"pipe:1"</span><span style="font-family:'Courier New'; color:#d4d4d4">]</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">extension</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#ce9178">"jpg"</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">case</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#ce9178">"video"</span><span style="font-family:'Courier New'; color:#d4d4d4">:</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">command</span><span style="font-family:'Courier New'; color:#d4d4d4"> = [</span><span style="font-family:'Courier New'; color:#ce9178">"ffmpeg"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-i"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"pipe:0"</span><span style="font-family:'Courier New'; color:#d4d4d4">, *</span><span style="font-family:'Courier New'; color:#9cdcfe">params</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-c:a"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"aac"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-pix_fmt"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"yuv420p"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-movflags"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"frag_keyframe+empty_moov+faststart"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-f"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"mp4"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"pipe:1"</span><span style="font-family:'Courier New'; color:#d4d4d4">]</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">extension</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#ce9178">"mp4"</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">case</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#ce9178">"audio"</span><span style="font-family:'Courier New'; color:#d4d4d4">:</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">command</span><span style="font-family:'Courier New'; color:#d4d4d4"> = [</span><span style="font-family:'Courier New'; color:#ce9178">"ffmpeg"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-i"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"pipe:0"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-loop"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"1"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-r"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"10"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-i"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"assets/sus.webp"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-shortest"</span><span style="font-family:'Courier New'; color:#d4d4d4">, *</span><span style="font-family:'Courier New'; color:#9cdcfe">params</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-c:a"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"aac"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-pix_fmt"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"yuv420p"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-movflags"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"frag_keyframe+empty_moov+faststart"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"-f"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"mp4"</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#ce9178">"pipe:1"</span><span style="font-family:'Courier New'; color:#d4d4d4">]</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">extension</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#ce9178">"mp4"</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">case</span><span style="font-family:'Courier New'; color:#d4d4d4"> _:</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">continue</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">process</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#dcdcaa">run</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#9cdcfe">command</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#9cdcfe">input</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#9cdcfe">attachment_data</span><span style="font-family:'Courier New'; color:#d4d4d4">, </span><span style="font-family:'Courier New'; color:#9cdcfe">stdout</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#4fc1ff">PIPE</span><span style="font-family:'Courier New'; color:#d4d4d4">)</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">if</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#9cdcfe">process</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#9cdcfe">returncode</span><span style="font-family:'Courier New'; color:#d4d4d4"> == </span><span style="font-family:'Courier New'; color:#b5cea8">0</span><span style="font-family:'Courier New'; color:#d4d4d4">:</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">discord_file</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#4ec9b0">discord</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#4ec9b0">File</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#9cdcfe">fp</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#4ec9b0">BytesIO</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#9cdcfe">process</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#9cdcfe">stdout</span><span style="font-family:'Courier New'; color:#d4d4d4">), </span><span style="font-family:'Courier New'; color:#9cdcfe">filename</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#569cd6">f</span><span style="font-family:'Courier New'; color:#ce9178">"</span><span style="font-family:'Courier New'; color:#569cd6">{</span><span style="font-family:'Courier New'; color:#9cdcfe">attachment</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#9cdcfe">filename</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#dcdcaa">split</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#ce9178">"."</span><span style="font-family:'Courier New'; color:#d4d4d4">)[</span><span style="font-family:'Courier New'; color:#b5cea8">0</span><span style="font-family:'Courier New'; color:#d4d4d4">]</span><span style="font-family:'Courier New'; color:#569cd6">}</span><span style="font-family:'Courier New'; color:#ce9178">.</span><span style="font-family:'Courier New'; color:#569cd6">{</span><span style="font-family:'Courier New'; color:#9cdcfe">extension</span><span style="font-family:'Courier New'; color:#569cd6">}</span><span style="font-family:'Courier New'; color:#ce9178">"</span><span style="font-family:'Courier New'; color:#d4d4d4">)</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#9cdcfe">images</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#dcdcaa">append</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#9cdcfe">discord_file</span><span style="font-family:'Courier New'; color:#d4d4d4">)</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">if</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#dcdcaa">len</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#9cdcfe">images</span><span style="font-family:'Courier New'; color:#d4d4d4">) &gt; </span><span style="font-family:'Courier New'; color:#b5cea8">0</span><span style="font-family:'Courier New'; color:#d4d4d4">:</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">await</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#9cdcfe">interaction</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#9cdcfe">followup</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#dcdcaa">send</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#9cdcfe">files</span><span style="font-family:'Courier New'; color:#d4d4d4"> = </span><span style="font-family:'Courier New'; color:#9cdcfe">images</span><span style="font-family:'Courier New'; color:#d4d4d4">)</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">else</span><span style="font-family:'Courier New'; color:#d4d4d4">:</span>
<span style="font-family:'Courier New'; color:#d4d4d4">&#xa0;&#xa0;&#xa0;&#xa0;&#xa0;&#xa0; </span><span style="font-family:'Courier New'; color:#c586c0">await</span><span style="font-family:'Courier New'; color:#d4d4d4"> </span><span style="font-family:'Courier New'; color:#9cdcfe">interaction</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#9cdcfe">followup</span><span style="font-family:'Courier New'; color:#d4d4d4">.</span><span style="font-family:'Courier New'; color:#dcdcaa">send</span><span style="font-family:'Courier New'; color:#d4d4d4">(</span><span style="font-family:'Courier New'; color:#ce9178">"No files to fix"</span><span style="font-family:'Courier New'; color:#d4d4d4">)</span>

victory! well, almost.

03 - clipboard inspection

after i had done all of this process, mary suggested that it could be possible to “make a thing that listens to the paste event and grabs the text/html copy of the clipboard”. in response to this, my girlfriend sent clipboard inspector and clipboard viewer, two tools that did exactly that. these could entirely skip the intermediaries of the doc and the converters, allowing me to simply copy the html out of the clipboard. The only extra effort it required is removing the two divs that the code is inside.

this yielded a much simpler and faster process, and one that gave seemingly much more concise html:


<span style="color: #dcdcaa;">@</span><span style="color: #4ec9b0;">app_commands</span><span style="color: #dcdcaa;">.</span><span style="color: #dcdcaa;">allowed_installs</span><span style="color: #d4d4d4;">(</span><span style="color: #9cdcfe;">guilds</span><span style="color: #d4d4d4;">=</span><span style="color: #4fc1ff;">True</span><span style="color: #d4d4d4;">, </span><span style="color: #9cdcfe;">users</span><span style="color: #d4d4d4;">=</span><span style="color: #4fc1ff;">True</span><span style="color: #d4d4d4;">)</span></div><div><span style="color: #dcdcaa;">@</span><span style="color: #4ec9b0;">app_commands</span><span style="color: #dcdcaa;">.</span><span style="color: #dcdcaa;">allowed_contexts</span><span style="color: #d4d4d4;">(</span><span style="color: #9cdcfe;">guilds</span><span style="color: #d4d4d4;">=</span><span style="color: #4fc1ff;">True</span><span style="color: #d4d4d4;">, </span><span style="color: #9cdcfe;">dms</span><span style="color: #d4d4d4;">=</span><span style="color: #4fc1ff;">True</span><span style="color: #d4d4d4;">, </span><span style="color: #9cdcfe;">private_channels</span><span style="color: #d4d4d4;">=</span><span style="color: #4fc1ff;">True</span><span style="color: #d4d4d4;">)</span></div><div><span style="color: #dcdcaa;">@</span><span style="color: #9cdcfe;">tree</span><span style="color: #dcdcaa;">.</span><span style="color: #dcdcaa;">context_menu</span><span style="color: #d4d4d4;">(</span><span style="color: #9cdcfe;">name</span><span style="color: #d4d4d4;">=</span><span style="color: #ce9178;">"fixfiles"</span><span style="color: #d4d4d4;">)</span></div><div><span style="color: #569cd6;">async</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">def</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">fixfiles</span><span style="color: #d4d4d4;">(</span><span style="color: #9cdcfe;">interaction</span><span style="color: #d4d4d4;">: </span><span style="color: #4ec9b0;">discord</span><span style="color: #d4d4d4;">.</span><span style="color: #4ec9b0;">Interaction</span><span style="color: #d4d4d4;">,  </span><span style="color: #9cdcfe;">message</span><span style="color: #d4d4d4;">: </span><span style="color: #4ec9b0;">discord</span><span style="color: #d4d4d4;">.</span><span style="color: #4ec9b0;">Message</span><span style="color: #d4d4d4;">):</span></div><div><span style="color: #d4d4d4;">    </span><span style="color: #c586c0;">await</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">interaction</span><span style="color: #d4d4d4;">.</span><span style="color: #9cdcfe;">response</span><span style="color: #d4d4d4;">.</span><span style="color: #dcdcaa;">defer</span><span style="color: #d4d4d4;">()</span></div><div><span style="color: #d4d4d4;">    </span><span style="color: #9cdcfe;">images</span><span style="color: #d4d4d4;"> = []</span></div><div><span style="color: #d4d4d4;">    </span><span style="color: #9cdcfe;">hardware</span><span style="color: #d4d4d4;"> = </span><span style="color: #9cdcfe;">path</span><span style="color: #d4d4d4;">.</span><span style="color: #dcdcaa;">exists</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"/dev/dri/renderD128"</span><span style="color: #d4d4d4;">)</span></div><div><span style="color: #d4d4d4;">    </span><span style="color: #9cdcfe;">params</span><span style="color: #d4d4d4;"> = [</span><span style="color: #ce9178;">"-vaapi_device"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"/dev/dri/renderD128"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-vf"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"hwupload,scale_vaapi=w=-2:h='min(720,iw)':format=nv12"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-c:v"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"h264_vaapi"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-b:v"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"1M"</span><span style="color: #d4d4d4;">] </span><span style="color: #c586c0;">if</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">hardware</span><span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">else</span><span style="color: #d4d4d4;"> [</span><span style="color: #ce9178;">"-c:v"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"h264"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-vf"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"scale=-2:'min(720,iw)'"</span><span style="color: #d4d4d4;">]</span></div><br><div><span style="color: #d4d4d4;">    </span><span style="color: #c586c0;">for</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">attachment</span><span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">in</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">message</span><span style="color: #d4d4d4;">.</span><span style="color: #9cdcfe;">attachments</span><span style="color: #d4d4d4;">:</span></div><div><span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">extension</span><span style="color: #d4d4d4;"> = </span><span style="color: #ce9178;">""</span></div><div><span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">attachment_data</span><span style="color: #d4d4d4;"> = </span><span style="color: #c586c0;">await</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">attachment</span><span style="color: #d4d4d4;">.</span><span style="color: #dcdcaa;">read</span><span style="color: #d4d4d4;">()</span></div><div><span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">mime</span><span style="color: #d4d4d4;"> = </span><span style="color: #4ec9b0;">magic</span><span style="color: #d4d4d4;">.</span><span style="color: #dcdcaa;">from_buffer</span><span style="color: #d4d4d4;">(</span><span style="color: #9cdcfe;">attachment_data</span><span style="color: #d4d4d4;">, </span><span style="color: #9cdcfe;">mime</span><span style="color: #d4d4d4;"> = </span><span style="color: #4fc1ff;">True</span><span style="color: #d4d4d4;">).</span><span style="color: #dcdcaa;">split</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"/"</span><span style="color: #d4d4d4;">)</span></div><div><span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">contentType</span><span style="color: #d4d4d4;"> = </span><span style="color: #9cdcfe;">mime</span><span style="color: #d4d4d4;">[</span><span style="color: #b5cea8;">0</span><span style="color: #d4d4d4;">]</span></div><div><span style="color: #d4d4d4;">        </span><span style="color: #9cdcfe;">contentExtension</span><span style="color: #d4d4d4;"> = </span><span style="color: #9cdcfe;">mime</span><span style="color: #d4d4d4;">[</span><span style="color: #b5cea8;">1</span><span style="color: #d4d4d4;">]</span></div><div><span style="color: #d4d4d4;">        </span><span style="color: #c586c0;">match</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">contentType</span><span style="color: #d4d4d4;">:</span></div><div><span style="color: #d4d4d4;">            </span><span style="color: #c586c0;">case</span><span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">"image"</span><span style="color: #d4d4d4;">:</span></div><div><span style="color: #d4d4d4;">                </span><span style="color: #c586c0;">if</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">contentExtension</span><span style="color: #d4d4d4;"> == </span><span style="color: #ce9178;">"gif"</span><span style="color: #d4d4d4;">:</span></div><div><span style="color: #d4d4d4;">                    </span><span style="color: #c586c0;">continue</span></div><div><span style="color: #d4d4d4;">                </span><span style="color: #9cdcfe;">command</span><span style="color: #d4d4d4;"> = [</span><span style="color: #ce9178;">"ffmpeg"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-i"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"pipe:0"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-f"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"image2"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"pipe:1"</span><span style="color: #d4d4d4;">]</span></div><div><span style="color: #d4d4d4;">                </span><span style="color: #9cdcfe;">extension</span><span style="color: #d4d4d4;"> = </span><span style="color: #ce9178;">"jpg"</span></div><div><span style="color: #d4d4d4;">            </span><span style="color: #c586c0;">case</span><span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">"video"</span><span style="color: #d4d4d4;">:</span></div><div><span style="color: #d4d4d4;">                </span><span style="color: #9cdcfe;">command</span><span style="color: #d4d4d4;"> = [</span><span style="color: #ce9178;">"ffmpeg"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-i"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"pipe:0"</span><span style="color: #d4d4d4;">, *</span><span style="color: #9cdcfe;">params</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-c:a"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"aac"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-pix_fmt"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"yuv420p"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-movflags"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"frag_keyframe+empty_moov+faststart"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-f"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"mp4"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"pipe:1"</span><span style="color: #d4d4d4;">]</span></div><div><span style="color: #d4d4d4;">                </span><span style="color: #9cdcfe;">extension</span><span style="color: #d4d4d4;"> = </span><span style="color: #ce9178;">"mp4"</span></div><div><span style="color: #d4d4d4;">            </span><span style="color: #c586c0;">case</span><span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">"audio"</span><span style="color: #d4d4d4;">:</span></div><div><span style="color: #d4d4d4;">                </span><span style="color: #9cdcfe;">command</span><span style="color: #d4d4d4;"> = [</span><span style="color: #ce9178;">"ffmpeg"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-i"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"pipe:0"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-loop"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"1"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-r"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"10"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-i"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"assets/sus.webp"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-shortest"</span><span style="color: #d4d4d4;">, *</span><span style="color: #9cdcfe;">params</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-c:a"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"aac"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-pix_fmt"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"yuv420p"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-movflags"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"frag_keyframe+empty_moov+faststart"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"-f"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"mp4"</span><span style="color: #d4d4d4;">, </span><span style="color: #ce9178;">"pipe:1"</span><span style="color: #d4d4d4;">]</span></div><div><span style="color: #d4d4d4;">                </span><span style="color: #9cdcfe;">extension</span><span style="color: #d4d4d4;"> = </span><span style="color: #ce9178;">"mp4"</span></div><div><span style="color: #d4d4d4;">            </span><span style="color: #c586c0;">case</span><span style="color: #d4d4d4;"> _:</span></div><div><span style="color: #d4d4d4;">                </span><span style="color: #c586c0;">continue</span>```
        

conclusion

this was an… interesting, and while very confusing and very long process, honestly kind of fun. plus my code looks pretty now so it’s WORTH IT!