femslash-city/views/contact.erb
Agnes 596fd85f2f
Some checks failed
CI / test (push) Has been cancelled
accidentally leaked secrets so had to nuke shit fuck
2026-08-19 17:29:54 -04:00

376 lines
19 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<div class="header-Outro">
<div class="row content single-Col">
<h1>Contact Us</h1>
</div>
</div>
<div class="content single-Col misc-page">
<% if !@errors.nil? && !@errors.empty? %>
<div class="alert alert-block alert-error">
<% @errors.each do |error| %>
<p><%= error%></p>
<% end %>
</div>
<% end %>
<div class="faq-assist" id="faq-assist">
<label for="faq_query">What issue are you having?</label>
<input
type="search"
id="faq_query"
name="faq_query"
form="contact-form"
class="col-75"
placeholder="e.g. password reset email, file upload not updating, bandwidth questions"
autocomplete="off"
minlength="8"
required
value="<%= params[:faq_query] %>">
<div id="faq-suggestions" class="faq-suggestions" aria-live="polite" aria-label="FAQ suggestions">
<p class="muted">Start typing to see answers from our knowledge base.</p>
</div>
<p class="contact-trigger">
<button type="button" class="btn-Action" id="show-contact-button" disabled>
Still need help? Contact us
</button>
</p>
</div>
<% contact_visible = @show_contact_form || (!@errors.nil? && !@errors.empty?) || params[:faq_check] == 'yes' %>
<div class="contact-form-block <%= contact_visible ? '' : 'is-hidden' %>" id="contact-form-container" data-show="<%= contact_visible ? 'true' : 'false' %>">
<form action="/contact" method="POST" class="content" id="contact-form">
<input name="csrf_token" type="hidden" value="<%= csrf_token %>">
<input type="hidden" name="show_contact_form" id="show_contact_form" value="<%= contact_visible ? 'yes' : 'no' %>">
<input type="hidden" name="faq_check" id="faq_check" value="<%= params[:faq_check] || 'no' %>">
<fieldset>
<label for="your_email">Email address</label>
<input type="email" id="your_email" name="email" placeholder="me@example.com" class="col-50" value="<%= params[:email] %>">
<label for="confirm_your_email">Confirm email address</label>
<input type="email" id="confirm_your_email" name="confirm_email" placeholder="me@example.com" class="col-50" value="<%= params[:confirm_email] %>">
<label for="email_subject">Subject</label>
<input type="text" id="email_subject" name="subject" placeholder="Subject" class="col-50" value="<%= params[:subject] %>">
<label for="your_comments">Message</label>
<small>Being simple but descriptive is helpful. For example, provide the site name, domain, or file path that is causing the issues in question.</small>
<textarea name="body" id="your_comments" class="col-75" rows="10"><%= params[:body] %></textarea>
<label>Fill out the captcha so we know youre not a robot:</label>
<%== hcaptcha_input %>
<input class="btn-Action" type="submit" value="Send">
</fieldset>
</form>
<noscript>
<style>
#contact-form-container.contact-form-block.is-hidden { display: block; }
</style>
<div class="alert alert-block alert-info">
JavaScript is disabled. Please read the FAQ above before sending us a message.
</div>
</noscript>
</div>
<script>
$(function() {
var $search = $('#faq_query');
var $suggestions = $('#faq-suggestions');
var $showContactButton = $('#show-contact-button');
var $contactTrigger = $('.contact-trigger');
var $contactContainer = $('#contact-form-container');
var $showContactField = $('#show_contact_form');
var $faqCheck = $('#faq_check');
var MIN_QUERY_LENGTH = 8;
var escapeElement = document.createElement('div');
function escapeHtml(str) {
escapeElement.textContent = str || '';
return escapeElement.innerHTML;
}
var knowledgeBase = [
{
id: 'emailresetnotfound',
question: "I didn't receive my password reset email",
answer: `<p>Confirm youre checking the inbox and spam folder for the email address you used to create the site. If you used a different address, try the reset with that one.</p>
<p>To avoid lockouts in the future, consider using a password manager (e.g., <a href="https://bitwarden.com/">Bitwarden</a>, <a href="https://1password.com/">1Password</a>) to keep credentials organized.</p>`
},
{
id: 'lostemail',
question: 'I no longer have access to my email; can you reset my password?',
answer: `<p>For security, we cant reset access if you dont control the original email address. Please create a new site. If you expected a reset email, check spam and any alternate inboxes first.</p>`
},
{
id: 'csp',
question: 'Content-Security-Policy blocked loading a resource',
answer: `<p>Free plans cannot send JavaScript requests to external servers after page load. Content must be loaded at page load or hosted on Neocities. To enable outbound requests, upgrade to a <a href="/supporter">supporter</a> plan.</p>
<p>Best practice: host the assets you need directly on your site to improve reliability and performance.</p>`
},
{
id: 'reload',
question: 'My site is not updating after I publish changes',
answer: `<p>Browsers often cache pages. Perform a hard reload (Ctrl+Shift+R on Windows/Linux, Command+Shift+R on macOS) or clear cache and retry. If that doesn't work, try making a small change to the page and saving and see if it resolves it.</p>`
},
{
id: 'editor',
question: 'The editor is behaving unexpectedly or redirecting',
answer: `<p>Browser extensions (ad blockers, privacy tools) can interfere with saves. Temporarily disable them for Neocities and try again.</p>`
},
{
id: 'ads',
question: 'Can I run ads or use my site for business?',
answer: `<p>Yes. You may place ads or run a business site as long as the site isnt purely advertising (ad-only sites are treated as spam). Neocities itself will not place ads on your pages.</p>`
},
{
id: 'backend',
question: 'Do you support PHP or other server-side languages?',
answer: `<p>Neocities is intentionally static hosting (HTML, CSS, JS only). We dont run server-side code for security, cost, and longevity reasons. Front-end JavaScript is fully supported.</p>`
},
{
id: 'ftp',
question: 'Do you support FTP?',
answer: `<p>We do not support FTP. Use the web editor, <a href="/api">API</a>, or <a href="/site_files/mount_info">WebDAV</a> (supporter feature) to upload content.</p>`
},
{
id: 'embeds',
question: 'Do you provide hit counters, webrings, guest books, etc.?',
answer: `<p>We dont provide embeddable widgets because we want sites to remain portable and independent. You can, however, link to your Neocities profile or integrate third-party widgets at your discretion.</p>`
},
{
id: 'filetypes',
question: 'Do you allow WASM / MP3 / MP4 / ZIP on free sites?',
answer: `<p>These formats are limited on free plans due to abuse and bandwidth concerns. For media, consider embedding from platforms like YouTube or upgrading to supporter if you need broader file support. Keep in mind that audio/video piracy is not allowed on Neocities and will result in a ban.</p>`
},
{
id: 'bigfiles',
question: 'I hit a file size upload limit. Can I upload very large files?',
answer: `<p>Very large files are restricted because our CDN is optimized for many small web assets and to mitigate abuse. For large downloads or video distribution, use specialized platforms (e.g., YouTube, Vimeo, BitTorrent).</p>`
},
{
id: 'htaccess',
question: 'Do you support .htaccess?',
answer: `<p>No. .htaccess is Apache-specific and we dont run Apache. We avoid backend-specific features so sites remain portable and secure.</p>`
},
{
id: 'sitecreation',
question: '"Site creation is not currently available from your location"',
answer: `<p>Your IP or session was flagged for potential abuse. If youre on a VPN, disable it and try again. Running an anti-virus scan is also recommended.</p>`
},
{
id: 'hitsviews',
question: 'Whats the difference between hits and views?',
answer: `<p>Hits count every file request. Views count one unique IP per hour for any content on your site. Views better approximate audience size, while hits include all asset requests. Search engine bot traffic is filtered from views where possible.</p>`
},
{
id: 'delete',
question: 'Can you delete my site for me?',
answer: `<p>For security, only the site owner can delete a site, we cannot do it manually. Sign in, go to Settings, and delete the site there. If you have multiple sites, delete each child site before removing the parent account.</p>`
},
{
id: 'backup',
question: 'My site backup download is failing',
answer: `<p>Most backup issues are network-related. Try a wired connection, a different browser, or another network. If problems persist, retry later or use a third-party tool like <a href="https://melonking.net/free/software/neocities-downloader">SAve MY nEOCiTy!</a>.</p>`
},
{
id: 'sitename',
question: 'Can I take over an inactive site name?',
answer: `<p>We dont transfer inactive site names. Ownership stays with the original creator even if the site appears unused. We can't make exceptions at this time.</p>`
},
{
id: 'tags',
question: 'Why cant I add more tags to my profile?',
answer: `<p>Each site can have up to <%= Site::MAXIMUM_TAGS.to_s %> tags. Remove an existing tag to add a new one.</p>`
},
{
id: 'invoices',
question: 'Where can I download supporter invoices?',
answer: `<p>Invoices are available as PDFs at <a href="/settings/invoices">Settings → Invoices</a> if using a credit card. If using a PayPal, invoices need to be downloaded directly from PayPal.</p>`
},
{
id: 'oldbrowsers',
question: 'How do I view Neocities sites on very old browsers?',
answer: `<p>Use an “old browser” proxy like <a href="https://github.com/atauenis/webone">WebOne</a> or <a href="https://github.com/tenox7/wrp">WRP</a>, which translate modern pages for legacy browsers.</p>`
},
{
id: 'dmca',
question: 'How do I file a DMCA takedown notice?',
answer: `<p>Submit requests through our <a href="/dmca">DMCA page</a> to ensure theyre properly tracked and reviewed.</p>`
},
{
id: 'takedown',
question: 'How do I request removal of a site?',
answer: `<p>We remove content only when it violates our <a href="/terms">Terms of Service</a> or applicable law. Review our <a href="/legal">legal guide</a> for details on our policies.</p>`
},
{
id: 'lawsuit',
question: 'I have legal concerns about hosted content',
answer: `<p>Please review our <a href="/legal">legal guide</a> for how we handle complaints, safe harbor, and escalation paths.</p>`
},
{
id: 'domain-dns',
question: 'How do I point my custom domain to Neocities?',
answer: `<p>At your domain registrar, create a CNAME for <code>www</code> (and other subdomains) to <code>neocities.org</code>. For apex/root, add A records to our published IPs. After DNS propagates, add the domain in Settings → Domains; SSL will provision automatically. You will find a full set of instructions in the site settings for custom domains.</p>`
},
{
id: 'domain-ssl',
question: 'How do I set up HTTPS/SSL on my custom domain?',
answer: `<p>Once your domains DNS points to Neocities, we automatically issue certificates. No CSR or key upload is needed. There is sometimes a short delay until the certificate is issued and the domain starts working.</p>`
},
{
id: 'asset-404',
question: 'Why are my images or assets returning 404?',
answer: `<p>Paths on Neocities are case-sensitive. Verify the filename and path match exactly, and confirm the file is uploaded. If you replaced a file, hard reload to bypass cache. Update any links if you renamed or moved the file.</p>`
},
{
id: 'css-cache',
question: 'Why arent my CSS or JS changes showing?',
answer: `<p>Browser cache is the usual culprit. Perform a hard reload (Ctrl+Shift+R or Command+Shift+R). Ensure the linked filename matches the uploaded file.</p>`
},
{
id: 'access-control',
question: 'How do I password protect or restrict access to my site?',
answer: `<p>Neocities hosts public static sites and does not provide built-in authentication. For private access, it is better to host restricted content elsewhere.</p>`
},
{
id: 'binaries',
question: 'Can I upload executables or binary files?',
answer: `<p>Executables and certain binaries are blocked for security and abuse prevention. Keep uploads to web assets (HTML, CSS, JS, images). For distributing software or installers, use a dedicated file host or repository.</p>`
},
{
id: 'storage',
question: 'Whats the storage limit and how do I check it?',
answer: `<p>Free and supporter plans have different space limits. View your usage and remaining quota in your dashboard. Uploads may be rejected if they exceed your quota.</p>`
},
{
id: 'recover-delete',
question: 'How do I recover a deleted site?',
answer: `<p>You can restore a deleted site by logging in with the previous credentials. A prompt will ask if you would like to restore the site.</p>`
},
{
id: 'migrate',
question: 'How do I migrate from another host to Neocities?',
answer: `<p>Export your static files from the old host, then upload via the web editor, drag-and-drop, API, or WebDAV (supporter). After upload, verify links and paths—case differences commonly cause 404s.</p>`
},
{
id: 'rate-limit',
question: 'Why is my IP address rate-limited or blocked?',
answer: `<p>Rate limits trigger on suspicious or abusive patterns (bursty traffic, scraping, abuse reports). Reduce aggressive site or API calls, and retry after the block ends. Contact us with details about what triggered it if you believe its an error.</p>`
},
{
id: 'redirects',
question: 'Do you support server-side redirects or rewrites?',
answer: `<p>Server-side rewrites (e.g., .htaccess) arent supported.</p>`
},
{
id: 'abuse',
question: 'How do I report abuse or illegal content?',
answer: `<p>Report with the site URL, a brief description, and relevant evidence. We review against our <a href="/terms">Terms of Service</a> and applicable law. Not all disliked content is removable.</p>`
},
{
id: 'media-hosting',
question: 'Can I host video or audio directly?',
answer: `<p>Large media is limited on free plans. For best performance, upload to a streaming platform (e.g., YouTube, Vimeo) and embed. Supporters have more flexibility, but specialized media hosts are preferred for heavy content.</p>`
},
{
id: 'performance',
question: 'How can I improve my sites performance?',
answer: `<p>Compress and resize images, minify CSS/JS, avoid oversized single-page payloads, and reduce external dependencies. Use consistent casing and clean paths to prevent 404s and extra requests.</p>`
},
{
id: 'backups',
question: 'I accidentally deleted a file or overwrote it, is there a way to restore a lost file from a backup?',
answer: '<p>Unfortunately there is no way to do this at this moment, we cannot restore deleted files.</p>'
}
];
function renderSuggestions(query) {
var clean = $.trim(query || '');
if (!clean) {
$suggestions.html('<p class="muted">Start typing to see answers from our FAQ.</p>');
$showContactButton.prop('disabled', true);
$contactTrigger.hide();
return;
}
var lower = clean.toLowerCase();
var terms = lower.split(/\s+/).filter(function(term) { return term.length; });
var matches = knowledgeBase.map(function(entry) {
var question = entry.question.toLowerCase();
var answer = entry.answer.toLowerCase();
var score = 0;
terms.forEach(function(term) {
if (question.indexOf(term) !== -1) { score += 5; }
if (answer.indexOf(term) !== -1) { score += 1; }
});
if (question.indexOf(lower) !== -1) {
score += 3;
}
if (score > 0) {
return { entry: entry, score: score };
}
}).filter(Boolean).sort(function(a, b) {
return b.score - a.score;
}).slice(0, 5);
if (!matches.length) {
$suggestions.html('<p class="muted">No matches yet. Try different keywords.</p>');
} else {
var html = matches.map(function(match) {
return '' +
'<div class="faq-suggestion" data-target="' + match.entry.id + '">' +
'<h4>' + escapeHtml(match.entry.question) + '</h4>' +
'<div class="answer">' + match.entry.answer + '</div>' +
'</div>';
}).join('');
$suggestions.html(html);
}
if (clean.length >= MIN_QUERY_LENGTH) {
$contactTrigger.show();
$showContactButton.prop('disabled', false);
} else {
$contactTrigger.hide();
$showContactButton.prop('disabled', true);
}
}
function showContactForm() {
$contactContainer.removeClass('is-hidden');
$showContactField.val('yes');
$faqCheck.val('yes');
$('html, body').animate({scrollTop: $contactContainer.offset().top - 10}, 250);
}
$search.on('input', function() {
renderSuggestions($(this).val());
}).on('keypress', function(e) {
if (e.which === 13) {
e.preventDefault();
}
});
$showContactButton.on('click', function() {
showContactForm();
});
if ($contactContainer.data('show') === true || $contactContainer.data('show') === 'true') {
$contactContainer.removeClass('is-hidden');
$contactTrigger.show();
}
renderSuggestions($search.val());
});
</script>
</div>