FreeCompetitors/server.py

238 lines
8.2 KiB
Python
Raw Normal View History

2022-04-03 20:04:47 +02:00
#!/usr/bin/python3
2022-03-29 14:43:19 +02:00
# THIS SOFTWARE IS A PART OF FREE COMPETITOR PROJECT
# THE FOLLOWING SOURCE CODE I UNDER THE GNU
# AGPL LICENSE V3 OR ANY LATER VERSION.
# This project is not for simple users, but for
# web-masters and a like, so we are counting on
# your ability to set it up and running.
# Server side
from http.server import BaseHTTPRequestHandler, HTTPServer
from subprocess import *
import json
import os
2022-04-15 19:40:53 +02:00
import time
2022-03-29 14:43:19 +02:00
from modules import search
from modules import render
2022-04-03 20:04:47 +02:00
# Author: https://www.delftstack.com/howto/python/python-print-colored-text/
class bcolors:
OK = '\033[92m' #GREEN
WARNING = '\033[93m' #YELLOW
FAIL = '\033[91m' #RED
RESET = '\033[0m' #RESET COLOR
print("""╔═╗┬─┐┌─┐┌─┐╔═╗┌─┐┌┬┐┌─┐┌─┐┌┬┐┬┌┬┐┌─┐┬─┐┌─┐
Copyright (C) 2022 Jeison Yehuda Amihud and contributors.
2022-04-03 20:04:47 +02:00
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
2022-04-03 19:35:04 +02:00
2022-04-03 20:04:47 +02:00
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
""")
print("Loading config...")
if os.path.exists("config.json"):
2022-04-03 19:35:04 +02:00
with open("config.json","r") as f:
srvConfig = json.load(f)
ADDRESS = srvConfig["address"]
PORT = srvConfig["port"]
CSS = srvConfig["css"]
2022-04-03 20:04:47 +02:00
print(bcolors.OK + "Loaded Configuration: " + bcolors.RESET)
print("Address: "+ ADDRESS)
print("Port: "+ str(PORT)) # Do not think people are smart at syntax
print("CSS: "+ CSS)
try:
PORT = int(PORT)
except:
print(bcolors.FAIL + "ERR: Port should be a number" + bcolors.RESET)
exit()
else:
2022-04-03 18:27:21 +02:00
newConfig = open("config.json", "w")
newConfig.write("""{
"INFO" : "You would be better off setting address to the full URL of the FreeCompetitors instance.",
"address" : "/",
2022-04-03 19:35:04 +02:00
"port" : 8080,
2022-04-04 18:34:28 +02:00
"css" : "/css"
2022-04-03 18:27:21 +02:00
}""")
newConfig.close
2022-04-03 20:04:47 +02:00
print(bcolors.WARNING + "Please edit the configuration file \"config.json\"." + bcolors.RESET)
2022-04-03 18:27:21 +02:00
exit()
2022-04-03 19:35:04 +02:00
2022-03-29 14:43:19 +02:00
# Who fucking made this http.server so I need to use classes?
# I fucking hate who ever thought that it was a good idea...
class handler(BaseHTTPRequestHandler):
def start_page(self):
self.send_response(200)
2022-04-04 18:34:28 +02:00
if "/json/" in self.path:
self.send_header('Content-type', 'application/json')
2022-04-04 18:34:28 +02:00
elif self.path == "/css":
self.send_header('Content-type', 'text/css')
elif self.path == "/ttf":
self.send_header('Content-type', 'font/ttf')
2022-04-15 19:40:53 +02:00
elif self.path in ["/favicon.png", "/logo"]:
self.send_header('Content-type', 'image/png')
2022-04-04 18:34:28 +02:00
else:
self.send_header('Content-type', 'text/html')
2022-03-29 14:43:19 +02:00
self.end_headers()
def send(self, textin):
2022-04-15 19:40:53 +02:00
textin = str(textin)
2022-03-29 14:43:19 +02:00
csstext = '<link media="all" href="'+CSS+'" type="text/css" rel="stylesheet" />'
text = "<!-- Welcome to Free Competitors Page Source!!!--> \n\n"
text = text + "<!-- Let's add some CSS, you can edit 'config.json' to change it. -->\n"
2022-04-15 21:25:42 +02:00
text = text + '<head>'+csstext+'\n\n'
2022-04-15 19:40:53 +02:00
text = text + "<!-- Now we want the favicon to be PNG instead of ICO -->\n\n"
2022-04-15 21:25:42 +02:00
text = text + '<link rel="icon" href="favicon.png"></head>\n\n'
text = text + "<!-- Now the body. The main part of the page, so to speak. -->\n"
text = text + '<body>\n\n'+textin+'\n\n</body>'
2022-03-29 14:43:19 +02:00
self.start_page()
self.wfile.write(text.encode("utf-8"))
def do_GET(self):
2022-03-30 19:52:14 +02:00
if self.path.startswith("/json/"):
2022-03-29 14:43:19 +02:00
# API CALL
term = self.path[6:]
software_data, match = search.search_app(term)
data = {"found":{"data":software_data,"match":match}}
data["suggestions"] = search.suggest(software_data)
text = json.dumps(data, indent = 2)
self.start_page()
self.wfile.write(text.encode("utf-8"))
2022-04-15 19:40:53 +02:00
elif self.path == "/":
2022-03-29 14:43:19 +02:00
# If the user is at the front page, let him get only the search bar
2022-03-30 18:11:55 +02:00
2022-04-15 19:40:53 +02:00
page = """<center>
<br><br><br>
<img src="/logo" alt="[LOGO]" style="height:150px;">
<h1>Free Competitors</h1>"""
2022-04-03 18:27:21 +02:00
page = render.search_widget(page, ADDRESS)
2022-04-01 21:59:32 +02:00
page = page + "<p>Please search for any software to which you would like to find a Free Software replacement.</p></center>"
2022-03-30 18:11:55 +02:00
page = render.source_code_link(page)
self.send(page)
2022-03-29 14:43:19 +02:00
2022-04-04 18:34:28 +02:00
elif self.path == "/css":
# The css file
cssfile = open("default.css")
cssfile = cssfile.read()
self.send(cssfile)
elif self.path == "/font":
# The font file
fontfile = open("OpenSans-ExtraBold.ttf", "rb")
fontfile = fontfile.read()
self.send(fontfile)
2022-04-06 21:03:07 +02:00
elif self.path in ["/faq", "/faq?"]:
# The font file
faqfile = open("faq.html")
faqfile = faqfile.read()
faqfile = render.search_widget(faqfile, ADDRESS)
faqfile = render.source_code_link(faqfile)
self.send(faqfile)
2022-04-04 18:34:28 +02:00
2022-04-15 19:40:53 +02:00
elif "/favicon.png" == self.path:
# I'm recording all the favicons request times to get
# a rough estimate of how many people visit when.
# It seems like the browser is visiting the site for
# the first time ( at least in a given session ) it
# asks for a 'favicon.ico'. So I store each of those
# requests time. As a timestamp.
2022-04-04 18:34:28 +02:00
2022-04-15 19:40:53 +02:00
try:
with open("data/favicon_requests.json") as json_file:
favicons = json.load(json_file)
except:
favicons = []
favicons.append(time.time())
with open("data/favicon_requests.json", 'w') as f:
json.dump(favicons, f, indent=4, sort_keys=True)
icon = open("favicon.png", "rb")
icon = icon.read()
self.wfile.write(icon)
elif "/logo" == self.path:
icon = open("favicon.png", "rb")
icon = icon.read()
self.wfile.write(icon)
2022-04-04 18:34:28 +02:00
2022-03-29 14:43:19 +02:00
elif "/search?item=" in self.path:
# Clearing the url
# instead of it being /search?item=softwarename
# it will be just /softwarename
item = self.path[self.path.find("item=")+5:].lower()
self.send('<meta http-equiv="Refresh" content="0; url=\'/'+item+'\'" />')
else:
# This is when the fun is
software = self.path.replace("/", "").replace("+", " ")
2022-04-01 21:29:15 +02:00
software_data, match = search.search_app(software)
2022-04-15 21:25:42 +02:00
page = ""
page = page + '<div class="searchbar">'
page = page + render.search_widget("", ADDRESS)
page = page + "</div>"
page = page + '<div class="side_found">'
page = render.progress(page, match, "Search match: "+ str(int(match*100))+"%")
2022-03-29 14:43:19 +02:00
# Let's add the found software to the page
page = render.html(page, software_data)
2022-04-15 21:25:42 +02:00
page = page + "</div>"
page = page + '<div class="recomendations">'
2022-03-29 14:43:19 +02:00
page = render.suggestions(page, software_data)
2022-03-30 18:11:55 +02:00
page = render.source_code_link(page)
2022-04-15 21:25:42 +02:00
page = page + "</div>"
2022-03-29 14:43:19 +02:00
self.send(page)
serve = HTTPServer(("", PORT), handler)
2022-04-03 20:04:47 +02:00
print(bcolors.OK + "⚡Now serving on port "+ str(PORT) +" at "+ ADDRESS +"." + bcolors.RESET)
2022-03-29 14:43:19 +02:00
serve.serve_forever()