') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Created Modals for Latex command by JefeThePug · Pull Request #179 · practical-python-org/Eos · GitHub
Skip to content

Created Modals for Latex command - #179

Merged
Xarlos89 merged 3 commits into
masterfrom
Fix/Latex_improvements
Aug 23, 2026
Merged

Created Modals for Latex command#179
Xarlos89 merged 3 commits into
masterfrom
Fix/Latex_improvements

Conversation

@JefeThePug

Copy link
Copy Markdown
Collaborator

Made Latex editable without spamming the channel using Modals

Describe your changes

slash command -> modal -> embed where user can initialize the /latex command with a slash command, edit it as much as they like in the modal, with preview of how it will look, and a "publish" button which sends it to the chat as an embed. All modals and previews are ephemeral to avoid spamming the chat with mistakes.

Added

  • Invalid Equation image to appear during editing when the typed LaTeX equation is not renderable
  • _latex_utilities.py to store the Modal classes for editing Latex equations.

Fixed

  • latex.py to have the slash command open a Modal where the user can edit their LaTeX submission before publicly sending it to the channel.

Changed

Small Concern

  • Looking at my Docker logs, it seems like the logging is not working but nothing in my edited code seems to have anything to do with it and I am never referencing the .id attribute of anything.
2026-08-23 20:24:00 :: 08-23 11:24.00 :: ERROR :: client.py line 582 --- Ignoring exception in on_message_edit
2026-08-23 20:24:00 Traceback (most recent call last):
2026-08-23 20:24:00 File "/bot/.venv/lib/python3.12/site-packages/discord/client.py", line 508, in _run_event
2026-08-23 20:24:00 await coro(*args, **kwargs)
2026-08-23 20:24:00 File "/bot/src/bot/cogs/logging/logging_message_edit.py", line 57, in on_message_edit
2026-08-23 20:24:00 message_before.guild.id != int(os.getenv("MASTER_GUILD"))
2026-08-23 20:24:00 ^^^^^^^^^^^^^^^^^^^^^^^
2026-08-23 20:24:00 AttributeError: 'NoneType' object has no attribute 'id'

Checklist

  • Have your ran pre-commit over your PR?
  • Was this PR branched off from master?
  • Is this PR merging to master?

Made Latex editable without spamming the channel using Modals
Xarlos89
Xarlos89 previously approved these changes Aug 23, 2026

@Xarlos89Xarlos89 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some minor things with defer and potential issues with slow APIs, but if it's not an issue then it's not an issue. Approved from my side.

Comment threadsrc/bot/cogs/features/latex.py
Comment threadsrc/bot/cogs/features/_latex_utilities.py
Comment threadsrc/bot/cogs/features/_latex_utilities.py
Added defer() where requested and adjusted the interaction methods accordingly.
@Xarlos89
Xarlos89 merged commit d53ab05 into masterAug 23, 2026
2 checks passed
@Xarlos89
Xarlos89 deleted the Fix/Latex_improvements branch August 23, 2026 14:47
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@JefeThePug@Xarlos89