#!/usr/bin/python3 # 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 import time from modules import search from modules import render # 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. 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. 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 . """) print("Loading config...") if os.path.exists("config.json"): with open("config.json","r") as f: srvConfig = json.load(f) ADDRESS = srvConfig["address"] PORT = srvConfig["port"] CSS = srvConfig["css"] 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: newConfig = open("config.json", "w") newConfig.write("""{ "INFO" : "You would be better off setting address to the full URL of the FreeCompetitors instance.", "address" : "/", "port" : 8080, "css" : "/css" }""") newConfig.close print(bcolors.WARNING + "Please edit the configuration file \"config.json\"." + bcolors.RESET) exit() # 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) if "/json/" in self.path: self.send_header('Content-type', 'application/json') elif self.path == "/css": self.send_header('Content-type', 'text/css') elif self.path == "/ttf": self.send_header('Content-type', 'font/ttf') elif self.path in ["/favicon.png", "/logo"]: self.send_header('Content-type', 'image/png') else: self.send_header('Content-type', 'text/html') self.end_headers() def send(self, textin): software = self.path.replace("/", "").replace("+", " ") if software: software = ": "+software[0].upper()+software[1:].lower() textin = str(textin) csstext = '' text = " \n\n" text = text + "\n" text = text + ''+csstext+'\n\n' text = text + "\n\n" text = text + '\n\n' text = text + "\n\n" text = text + 'Free Competitors'+software+'\n\n' text = text + "\n" text = text + '\n\n'+textin+'\n\n' self.start_page() self.wfile.write(text.encode("utf-8")) def do_GET(self): if self.path.startswith("/json/"): # 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")) elif self.path == "/": # If the user is at the front page, let him get only the search bar page = """



[LOGO]

Free Competitors

""" page = render.search_widget(page, ADDRESS) page = page + "

Please search for any software to which you would like to find a Free Software replacement.

" page = render.source_code_link(page) self.send(page) elif self.path == "/css": # The css file self.send_response(200) self.send_header('Content-type', 'text/css') self.end_headers() cssfile = open("default.css", "rb") cssfile = cssfile.read() self.wfile.write(cssfile) elif self.path == "/font": # The font file fontfile = open("OpenSans-ExtraBold.ttf", "rb") fontfile = fontfile.read() self.wfile.write(fontfile) 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) 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. 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) elif self.path in ["/stats", "/stats?"]: # Analytics / statistics availble for all users of # the website. try: with open("data/favicon_requests.json") as json_file: favicons = json.load(json_file) except: favicons = [] page = render.stats("", True, favicons) self.send(page) 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('') else: # This is when the fun is software = self.path.replace("/", "").replace("+", " ") software_data, match = search.search_app(software) page = "" page = page + '" page = page + '
' page = render.progress(page, match, "Search match: "+ str(int(match*100))+"%") # Let's add the found software to the page page = render.html(page, software_data) page = page + "
" page = page + '
' page = render.suggestions(page, software_data) page = render.source_code_link(page) page = page + "
" self.send(page) serve = HTTPServer(("", PORT), handler) print(bcolors.OK + "⚡Now serving on port "+ str(PORT) +" at "+ ADDRESS +"." + bcolors.RESET) serve.serve_forever()