Basic contact page

This commit is contained in:
2025-01-08 22:12:10 +00:00
parent 856528fbc4
commit 66c8b16018
6 changed files with 102 additions and 9 deletions

View File

@@ -2,16 +2,61 @@
from index import app
from os import environ
from flask import request, redirect, render_template
from flask import request, render_template
from requests import post, get
from uuid import uuid4
from textwrap import dedent
def validate_turnstile(response: str, ip: str) -> bool:
turnstile_secret = environ['TURNSTILE_SECRET']
cf_response = post(
url='https://challenges.cloudflare.com/turnstile/v0/siteverify',
data={
'secret': turnstile_secret,
'response': response,
'remoteip': ip,
'idempotency_key': uuid4()
}
).json()
return cf_response.get('success', False)
def send_to_discord(form: dict) -> bool:
try:
discord_hook = environ['DISCORD_WEBHOOK']
except:
return False
discord_msg = dedent(
f'''
__**New Contact Form Response**__
**From:** {form.get('name')} <{form.get('email')}>
''')
if form.get("message") == '':
discord_msg += '*No Message*'
else:
discord_msg += f'>>> {form.get("message")}'
discord_response = post(
url=discord_hook,
data={
'username': form.get('name'),
'content': discord_msg
}
).status_code
if discord_response == 204:
return True
return False
@app.route('/contact/', methods=('GET', 'POST'))
def contact():
if request.method == 'POST':
discord_hook = environ['DISCORD_WEBHOOK']
print(discord_hook)
print(request.form)
return redirect('/contact/')
if not validate_turnstile(request.form['cf-turnstile-response'], request.remote_addr):
return render_template('contact.html', error=True, user_message='You appear to be a robot.')
send_result = send_to_discord(request.form)
if send_result:
return render_template('contact.html', user_message='Your message has been sent!')
return render_template('contact.html', error=True, user_message='An error occurred.')
else:
return render_template('contact.html')

View File

@@ -3,3 +3,4 @@ flask-markdown>=0.3
markdown>=3.4.1
beautifulsoup4>=4.11.1
python-frontmatter>=1.1.0
requests>=2.32.3

View File

@@ -54,4 +54,9 @@
width: fit-content;
padding-right: 20px;
}
#logo-container{
position: absolute;
height: 25vh;
}
}

View File

@@ -30,6 +30,7 @@ footer{
width: 100%;
justify-content: center;
display: flex;
align-items: center;
}
#logo{
@@ -167,4 +168,39 @@ a{
.article-category:hover{
text-decoration: underline;
}
#contact-main{
padding: 20px 10px 0 10px;
min-height: 65vh;
}
#contact-main>h2 {
margin-top: 0;
}
input, textarea{
display: block;
padding: 10px;
margin-bottom: 20px;
background-color: #4c4c4c;
border-radius: 10px;
border:none;
color: white;
width: 100%;
}
label{
line-height: 2rem;
}
.cf-turnstile{
width: fit-content;
padding: 10px 0 10px 0;
margin-left: auto;
margin-right: auto;
}
#contact-error{
color: red;
}

View File

@@ -1,16 +1,20 @@
{% include 'header.html' %}
<main>
<main id="contact-main">
<h2>Contact Me</h2>
<p>Got a question or want to talk about something on this site? Drop me a message below:</p>
<form action="#" method="post">
<label for="name">Name:</label>
<input type="text" name="name">
<input type="text" name="name" required>
<label for="email">Email Address:</label>
<input type="email" name="email">
<input type="email" name="email" required>
<label for="message">Message:</label>
<textarea name="message"></textarea>
<textarea name="message" rows="10"></textarea>
<div class="cf-turnstile" data-sitekey="0x4AAAAAAA45FeR26JuvqKy7"></div>
<input type="submit" name="submit" value="Submit">
</form>
{% if user_message is not none %}
<p id="{{ 'contact-error' if error else 'contact-message' }}">{{ user_message }}</p>
{% endif %}
</main>
{% include 'footer.html' %}

View File

@@ -12,12 +12,14 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<script src="/static/js/filter_projects.js"></script>
<script src="/static/js/update_copyright.js"></script>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
</head>
<body>
<header>
<nav id="top-nav">
<a href="/">About</a>
<a href="/projects/">Projects</a>
<a href="/contact/">Contact</a>
</nav>
<div id="logo-container">
<div id="logo">