From 9a39e8ec131377f987f6404e833708f6709c5247 Mon Sep 17 00:00:00 2001 From: Zack3D Date: Mon, 6 Oct 2025 15:39:54 -0700 Subject: [PATCH] wee --- frontend-backup/furryplace-sdk.js | 180 ++++++++++++++++++++++++++++++ frontend-backup/index.html | 2 +- src/index.ts | 2 +- 3 files changed, 182 insertions(+), 2 deletions(-) diff --git a/frontend-backup/furryplace-sdk.js b/frontend-backup/furryplace-sdk.js index c6fc698..d28af4c 100644 --- a/frontend-backup/furryplace-sdk.js +++ b/frontend-backup/furryplace-sdk.js @@ -107,6 +107,7 @@ let shopModalObserver = null; const DEFAULT_SOCIAL_ORDER = ['discord', 'twitter', 'bluesky', 'instagram', 'youtube', 'tiktok', 'reddit', 'github']; + const DEFAULT_FOOTER_LINK_ORDER = ['terms', 'privacy', 'refund', 'ban-appeal', 'suggestions', 'bug-report']; // Find the button container in the DOM function findButtonContainer() { @@ -401,6 +402,184 @@ return link; } + function getDefaultFooterOrder(id) { + const index = DEFAULT_FOOTER_LINK_ORDER.indexOf(id); + return index === -1 ? DEFAULT_FOOTER_LINK_ORDER.length + 10 : index; + } + + function ensureFooterEntry(map, id) { + if (!map[id]) { + map[id] = { id, order: getDefaultFooterOrder(id) }; + } + return map[id]; + } + + function formatFooterLabel(id) { + if (!id) return ''; + return id + .split('-') + .map(part => part.charAt(0).toUpperCase() + part.slice(1)) + .join(' '); + } + + function buildFooterEntriesFromContent(content) { + const data = content || {}; + const entries = {}; + + Object.entries(data).forEach(([key, value]) => { + if (!value) return; + const match = key.match(/^modal\.footer\.links\.([^.]+)\.(url|text|order|target)$/); + if (!match) return; + + const [, id, field] = match; + const entry = ensureFooterEntry(entries, id); + + if (field === 'order') { + const numericOrder = Number(value); + if (!Number.isNaN(numericOrder)) { + entry.order = numericOrder; + } + } else { + entry[field] = value; + } + }); + + const legacyFooterLinks = [ + ['terms', 'modal.footer.terms'], + ['privacy', 'modal.footer.privacy'], + ['refund', 'modal.footer.refund'], + ['ban-appeal', 'modal.footer.banAppeal'], + ['suggestions', 'modal.footer.suggestions'], + ['bug-report', 'modal.footer.bugReport'] + ]; + + legacyFooterLinks.forEach(([id, baseKey]) => { + const url = data[`${baseKey}.url`] || data[baseKey]; + if (!url) return; + + const entry = ensureFooterEntry(entries, id); + entry.url = url; + + const textValue = data[`${baseKey}.text`]; + if (!entry.text && textValue) { + entry.text = textValue; + } + + const orderValue = data[`${baseKey}.order`]; + if (orderValue !== undefined) { + const numericOrder = Number(orderValue); + if (!Number.isNaN(numericOrder)) { + entry.order = numericOrder; + } + } + + const targetValue = data[`${baseKey}.target`]; + if (targetValue) { + entry.target = targetValue; + } + }); + + return Object.values(entries) + .filter(entry => entry.url) + .map(entry => { + if (!entry.text) { + entry.text = formatFooterLabel(entry.id); + } + return entry; + }) + .sort((a, b) => { + if (a.order !== b.order) { + return a.order - b.order; + } + return a.id.localeCompare(b.id); + }); + } + + function createFooterLinkElement(entry) { + const link = document.createElement('a'); + link.href = entry.url; + link.className = 'link'; + + if (entry.target) { + link.target = entry.target; + } else if (!entry.url.startsWith('mailto:')) { + link.target = '_blank'; + } + + if (link.target === '_blank') { + link.rel = 'noopener noreferrer'; + } + + link.textContent = entry.text || formatFooterLabel(entry.id); + link.setAttribute('data-footer-id', entry.id); + + return link; + } + + async function rebuildInfoModalFooter(modalBox) { + try { + const footerSection = Array.from(modalBox.querySelectorAll('section')).find(section => + section.classList.contains('text-base-content/80') && section.classList.contains('text-sm') + ); + + if (!footerSection) return; + + const locale = getPreferredLocale(); + if ( + footerSection.dataset.fpFooterLocale === locale && + footerSection.dataset.fpFooterLoaded === 'true' + ) { + return; + } + + const content = await getSiteContent(locale); + if (!content) return; + + const email = content['modal.footer.email']; + const footerEntries = buildFooterEntriesFromContent(content); + + footerSection.innerHTML = ''; + + const items = []; + if (email) { + const emailSpan = document.createElement('span'); + emailSpan.className = 'inline-flex items-center gap-1'; + const emailLink = document.createElement('a'); + emailLink.href = `mailto:${email}`; + emailLink.className = 'link'; + emailLink.textContent = email; + emailSpan.append('Email: ', emailLink); + items.push(emailSpan); + } + + footerEntries.forEach(entry => { + const link = createFooterLinkElement(entry); + items.push(link); + }); + + if (items.length === 0) { + footerSection.dataset.fpFooterLocale = locale; + footerSection.dataset.fpFooterLoaded = 'false'; + return; + } + + items.forEach((node, index) => { + footerSection.appendChild(node); + if (index < items.length - 1) { + const separator = document.createElement('span'); + separator.className = 'mx-1 text-base-content/60'; + separator.textContent = ' ยท '; + footerSection.appendChild(separator); + } + }); + + footerSection.dataset.fpFooterLocale = locale; + footerSection.dataset.fpFooterLoaded = 'true'; + } catch (error) { + console.warn('[FurryPlace SDK] Failed to rebuild info modal footer:', error); + } + } + async function rebuildInfoModalSocialLinks(modalBox) { try { const contentContainer = modalBox.querySelector('div[class*="flex"]'); @@ -511,6 +690,7 @@ }); rebuildInfoModalSocialLinks(modalBox); + rebuildInfoModalFooter(modalBox); } // Watch for info modal opening diff --git a/frontend-backup/index.html b/frontend-backup/index.html index d731b5e..992a717 100644 --- a/frontend-backup/index.html +++ b/frontend-backup/index.html @@ -91,7 +91,7 @@ "@context": "https://schema.org", "@type": "WebApplication", "name": "FurryPlace", - "url": "https://github.com/FurryPlaceteam/FurryPlace" + "url": "https://gitea.goocat.gay/zack3d/my_openplace" } diff --git a/src/index.ts b/src/index.ts index 1992ab3..5d0dd3a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -236,7 +236,7 @@ app.use(async (req, res, next) => { if (ext === ".html") { res.setHeader("Content-Security-Policy", "script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval' https://challenges.cloudflare.com https://js.hcaptcha.com https://*.hcaptcha.com https://www.google.com https://www.gstatic.com blob:; " + - "frame-src 'self' https://challenges.cloudflare.com https://*.hcaptcha.com https://www.google.com https://www.gstatic.com; " + + "frame-src 'self' https://challenges.cloudflare.com https://*.hcaptcha.com https://www.google.com https://www.gstatic.com https://www.youtube.com; " + "style-src 'self' 'unsafe-inline' https://*.hcaptcha.com https://www.gstatic.com; " + "connect-src 'self' https://*.hcaptcha.com https://www.google.com https://www.gstatic.com https://tiles.openfreemap.org;" );