Beta launch

This commit is contained in:
Caretaker0699 2023-06-29 16:32:46 -07:00
commit 4d238c2972
11 changed files with 651 additions and 0 deletions

Binary file not shown.

108
app.py Normal file
View File

@ -0,0 +1,108 @@
from flask import Flask, render_template, request, jsonify
import xml.etree.ElementTree as ET
import logging
app = Flask(__name__)
# Configure logging
logging.basicConfig(level=logging.ERROR)
# Parse the XML file and extract data
def parse_xml(file_path):
try:
tree = ET.parse(file_path)
root = tree.getroot()
items = []
run_time_element = root.find("run_time")
if run_time_element is not None:
run_time = run_time_element.text
else:
run_time = 'N/A'
for item in root.findall('.//item'):
title_element = item.attrib.get('title')
title = title_element if title_element is not None else 'N/A'
link_element = item.attrib.get('link')
link = link_element if link_element is not None else '#'
description_element = item.attrib.get('description')
description = description_element if description_element is not None else 'N/A'
source_element = item.attrib.get('source')
source = source_element if source_element is not None else 'N/A'
guid_element = item.attrib.get('guid')
guid = guid_element if guid_element is not None else 'N/A'
pub_date_element = item.attrib.get('pubDate')
pub_date = pub_date_element if pub_date_element is not None else 'N/A'
georss_point_element = item.attrib.get('{http://www.georss.org/georss}point')
georss_point = georss_point_element if georss_point_element is not None else 'N/A'
items.append({
'title': title,
'link': link,
'description': description,
'source': source,
'guid': guid,
'pub_date': pub_date,
'georss_point': georss_point
})
return items, run_time # Return the extracted items and run time value
except FileNotFoundError:
app.logger.error('XML file not found.')
return [], ''
def write_to_xml(file_path, items):
root = ET.Element("root")
for item in items:
new_element = ET.SubElement(root, "item")
new_element.set("title", item['title'])
new_element.set("link", item['link'])
tree = ET.ElementTree(root)
tree.write(file_path, encoding="utf-8", xml_declaration=True)
@app.route('/')
def index():
items, run_time = parse_xml('./indeed_output.xml') # Retrieve the items and run time
return render_template('index.html', items=items, run_time=run_time) # Pass the run time to the template
@app.route('/search')
def search():
query = request.args.get('query')
items, run_time = parse_xml('./indeed_output.xml') # Retrieve the items and run time
# Filter the items based on the search query
filtered_items = []
for item in items:
if query.lower() in item['title'].lower() or query.lower() in item['description'].lower():
filtered_items.append(item)
return render_template('index.html', items=filtered_items, run_time=run_time) # Pass the run time to the template
@app.route('/report', methods=['POST'])
def report():
title = request.form.get('title')
link = request.form.get('link')
reported_items = list(parse_xml('./reported.xml'))
reported_items[0].append({'title': title, 'link': link}) # Append the item to the first element of the tuple
write_to_xml('./reported.xml', reported_items[0]) # Pass the first element of the tuple to write_to_xml
response = {
'message': 'Item reported successfully! Our team will review this listing to see if it is in line with our Statement of Faith. Appropriate filtering will be applied.'
}
return jsonify(response)
if __name__ == '__main__':
app.run()

108
app_backup.py Normal file
View File

@ -0,0 +1,108 @@
from flask import Flask, render_template, request, jsonify
import xml.etree.ElementTree as ET
import logging
app = Flask(__name__)
# Configure logging
logging.basicConfig(level=logging.ERROR)
# Parse the XML file and extract data
def parse_xml(file_path):
try:
tree = ET.parse(file_path)
root = tree.getroot()
items = []
run_time_element = root.find("run_time")
if run_time_element is not None:
run_time = run_time_element.text
else:
run_time = 'N/A'
for item in root.findall('.//item'):
title_element = item.attrib.get('title')
title = title_element if title_element is not None else 'N/A'
link_element = item.attrib.get('link')
link = link_element if link_element is not None else '#'
description_element = item.attrib.get('description')
description = description_element if description_element is not None else 'N/A'
source_element = item.attrib.get('source')
source = source_element if source_element is not None else 'N/A'
guid_element = item.attrib.get('guid')
guid = guid_element if guid_element is not None else 'N/A'
pub_date_element = item.attrib.get('pubDate')
pub_date = pub_date_element if pub_date_element is not None else 'N/A'
georss_point_element = item.attrib.get('{http://www.georss.org/georss}point')
georss_point = georss_point_element if georss_point_element is not None else 'N/A'
items.append({
'title': title,
'link': link,
'description': description,
'source': source,
'guid': guid,
'pub_date': pub_date,
'georss_point': georss_point
})
return items, run_time # Return the extracted items and run time value
except FileNotFoundError:
app.logger.error('XML file not found.')
return [], ''
def write_to_xml(file_path, items):
root = ET.Element("root")
for item in items:
new_element = ET.SubElement(root, "item")
new_element.set("title", item['title'])
new_element.set("link", item['link'])
tree = ET.ElementTree(root)
tree.write(file_path, encoding="utf-8", xml_declaration=True)
@app.route('/')
def index():
items, run_time = parse_xml('./indeed_output.xml') # Retrieve the items and run time
return render_template('index.html', items=items, run_time=run_time) # Pass the run time to the template
@app.route('/search')
def search():
query = request.args.get('query')
items, run_time = parse_xml('./indeed_output.xml') # Retrieve the items and run time
# Filter the items based on the search query
filtered_items = []
for item in items:
if query.lower() in item['title'].lower() or query.lower() in item['description'].lower():
filtered_items.append(item)
return render_template('index.html', items=filtered_items, run_time=run_time) # Pass the run time to the template
@app.route('/report', methods=['POST'])
def report():
title = request.form.get('title')
link = request.form.get('link')
reported_items = parse_xml('./reported.xml')
reported_items.append({'title': title, 'link': link})
write_to_xml('./reported.xml', reported_items)
response = {
'message': 'Item reported successfully! Our team will review this listing to see if it is in line with our Statement of Faith. Appropriate filtering will be applied.'
}
return jsonify(response)
if __name__ == '__main__':
app.run()

3
gunicorn_config.py Normal file
View File

@ -0,0 +1,3 @@
workers = 4
bind = '0.0.0.0:8000'
module = 'app:app'

1
indeed_input.xml Normal file

File diff suppressed because one or more lines are too long

2
indeed_output.xml Normal file

File diff suppressed because one or more lines are too long

2
reported.xml Normal file
View File

@ -0,0 +1,2 @@
<?xml version='1.0' encoding='utf-8'?>
<root></root>

BIN
static/heartily1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

229
static/style.css Normal file
View File

@ -0,0 +1,229 @@
body {
background-color: #272822;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #272822;
}
h1 {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
color: #f8f8f2;
}
ul {
list-style: none;
padding: 0;
}
li {
margin-bottom: 20px;
}
h2 {
font-size: 20px;
font-weight: bold;
color: #a9dc76;
}
p {
color: #999999;
}
a {
color: #78dce8;
text-decoration: none;
}
a:hover {
color: #e6a96b;
}
header {
display: flex;
justify-content: center;
align-items: center;
}
.logo {
flex-direction: row;
}
.logo-img {
width: 50px;
max-width: 100%;
margin-right: 10px;
}
.logo p {
font-size: 24px;
color: #f8f8f2;
margin: 10px;
}
.logo-name {
font-size: 24px;
font-weight: bold;
color: #f8f8f2;
margin: 10px;
}
.logo-link {
display: inline-flex;
align-items: center;
text-decoration: none; /* Add this line to remove underline */
}
.search-form {
display: flex;
align-items: center;
justify-content: center;
}
.search-input {
padding: 10px;
border: none;
border-radius: 4px;
font-size: 16px;
background-color: #F9F5DD;
color: #75715e;
}
.search-input::placeholder {
color: #75715e;
}
.search-button {
padding: 10px 20px;
border: none;
border-radius: 4px;
font-size: 16px;
background-color: #fd971f;
color: #f8f8f2;
cursor: pointer;
margin:10px;
}
.search-button:hover {
background-color: #f4bf75;
}
.notification-overlay {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background-color: #ff5795c7;
color: #f8f8f2;
border: 1px solid #272822;
padding: 10px 20px;
border-radius: 4px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
animation: fadeIn 0.5s, fadeOut 0.5s 5s forwards;
display: none;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
.report-button {
position: relative;
display: flex;
text-decoration: none;
padding: 10px 20px;
border-radius: 4px;
color: #FF5794;
border:none;
background-color: transparent;
margin: 5px;
}
.wrapper {
position: relative;
display: inline-block;
text-decoration: none;
color: #f8f8f2;
background-color: #fd971f;
padding: 10px 20px;
border: none;
border-radius: 4px;
margin: 5px;
}
.wrapper .button-text {
display: inline-block;
transition: opacity 0.3s ease;
}
.wrapper .button-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #ffffff;
font-size: 24px;
opacity: 0;
transition: opacity 0.3s ease;
}
.wrapper:hover {
background-color: #f4bf75;
}
.wrapper:hover .button-text {
opacity: 0;
}
.wrapper:hover .button-icon {
opacity: 1;
font-size: 20px;
}
.report-button .button-text {
display: inline-block;
transition: opacity 0.3s ease;
opacity: 0;
}
.report-button .button-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 24px;
transition: opacity 0.3s ease;
font-size: 20px;
opacity: 1;
}
.report-button:hover .button-text {
opacity: 1;
}
.report-button:hover .button-icon {
opacity: 0;
}
.list-container {
display: flex;
align-items: center;
}

125
templates/index.html Normal file
View File

@ -0,0 +1,125 @@
<!DOCTYPE html>
<html>
<head>
<title>Heartily</title>
<link
rel="stylesheet"
href="{{ url_for('static', filename='style.css') }}"
/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
/>
</head>
<body>
<header>
<div class="logo">
<a href="/" class="logo-link">
<img
src="{{ url_for('static', filename='heartily1.gif') }}"
alt="Heartily Logo"
class="logo-img"
/>
<p class="logo-name">Heartily</p>
<p>Col. 3:23</p>
</a>
</div>
</header>
<div class="container">
<form action="{{ url_for('search') }}" method="GET" class="search-form">
<input
type="text"
name="query"
placeholder="Search..."
class="search-input"
/>
<button type="submit" class="search-button">Search</button>
<a href="/" class="wrapper">
<span class="button-text">Refresh</span>
<span class="button-icon"><i class="far fa-heart"></i></span>
</a>
</form>
<h1>Latest Jobs:</h1>
<p>This list is updated hourly. Last update: {{ run_time }}</p>
<ul>
{% for item in items %}
<li>
<h2>{{ item.title }}</h2>
<p>Source: {{ item.source }}</p>
<p>Post Date: {{ item.pub_date }}</p>
<div class = "list-container">
<a href="{{ item.link }}" target="_blank" class="wrapper">
<span class="button-text">Apply Now</span>
<span class="button-icon"><i class="far fa-heart"></i></span>
</a>
<form
action="{{ url_for('report') }}"
method="POST"
class="report-form"
>
<input type="hidden" name="title" value="{{ item.title }}" />
<input type="hidden" name="link" value="{{ item.link }}" />
<button type="submit" class="report-button">
<span class="button-text">Report</span>
<span class="button-icon">
<i class="fas fa-heart-circle-exclamation"></i>
</span>
</button>
</form>
</div>
</li>
{% endfor %}
</ul>
</div>
<footer>
<p>
&copy; 2023 Heartily. All rights reserved. Version:
<a href="https://githaven.org/Shiloh/heartily" target="_blank">Beta</a>.
Powered by
<a href="https://shilohcode.com" target="_blank">Shiloh</a>.
</p>
</footer>
<!-- Notification overlay -->
<div id="notification-overlay" class="notification-overlay">
<span id="notification-message"></span>
</div>
<script>
// JavaScript code for displaying the notification overlay
function showNotification(message) {
var overlay = document.getElementById("notification-overlay");
var notification = document.getElementById("notification-message");
notification.textContent = message;
overlay.style.display = "block";
setTimeout(function () {
overlay.style.display = "none";
}, 10000); // Display the notification for 10 seconds
}
// JavaScript code for handling the AJAX request and displaying the notification
var reportForms = document.getElementsByClassName("report-form");
Array.prototype.forEach.call(reportForms, function (form) {
form.addEventListener("submit", function (event) {
event.preventDefault(); // Prevent the form from submitting
// Create a new FormData object to send the form data
var formData = new FormData(form);
// Send the AJAX request
var xhr = new XMLHttpRequest();
xhr.open("POST", "/report");
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
showNotification(response.message); // Display the notification
}
};
xhr.send(formData);
});
});
</script>
</body>
</html>

73
xmldownloader.py Normal file
View File

@ -0,0 +1,73 @@
import xml.etree.ElementTree as ET
import urllib.request
import random
import time
from fake_useragent import UserAgent
import requests
import datetime
# Get the current date and time
current_datetime = datetime.datetime.now()
# Format the date and time as a string
run_time = current_datetime.strftime("%Y-%m-%d %H:%M:%S")
# Print the run time
print("Script run time:", run_time)
# Define the URL of the XML file to download
url = "https://rss.indeed.com/rss?q=(it+OR+technology+OR+developer+OR+software)+AND+(bible+OR+christian+OR+jesus+OR+god)+-LDS+-%22Latter-Day+Saints%22.xml"
# Set a custom user agent
ua = UserAgent()
headers = {
'User-Agent': ua.random,
'Referer': 'https://google.com',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
}
# Create a session object to handle cookies
session = requests.Session()
session.headers.update(headers)
# Download the XML file
response = session.get(url)
filename = "/home/gordon/Documents/Code/heartily/indeed_input.xml"
with open(filename, 'wb') as f:
f.write(response.content)
# Introduce a random delay between 2 and 5 seconds
delay = random.uniform(2, 5)
time.sleep(delay)
# Read the downloaded XML file
tree = ET.parse(filename)
root = tree.getroot()
# Define the desired attribute names
attribute_names = ["title", "link", "source", "guid", "pubDate", "description", "{http://www.georss.org/georss}point"]
# Create a new XML root element to store the extracted values
new_root = ET.Element("root")
# Iterate over the "item" elements and extract the desired values
for item in root.findall(".//item"):
new_element = ET.SubElement(new_root, "item")
# Extract the desired attributes from the "item" element
for attribute_name in attribute_names:
value = item.find(attribute_name).text
if value is not None:
new_element.set(attribute_name, value)
# Add a new element for the run time
run_time_element = ET.SubElement(new_root, "run_time")
run_time_element.text = run_time
# Create an ElementTree object and write it to a new XML file
new_tree = ET.ElementTree(new_root)
output_filename = "/home/gordon/Documents/Code/heartily/indeed_output.xml"
new_tree.write(output_filename, encoding="utf-8", xml_declaration=True)