diff --git a/data/favicon_requests.json b/data/favicon_requests.json index 5204355..3dbb7f7 100644 --- a/data/favicon_requests.json +++ b/data/favicon_requests.json @@ -31,5 +31,33 @@ 1650090012.933084, 1650090481.4744847, 1650090521.486587, - 1650090584.648241 + 1650090584.648241, + 1650095974.4940188, + 1650097447.4327528, + 1650100147.3385897, + 1650100566.5777473, + 1650102075.2005043, + 1650103439.1721528, + 1650103628.453873, + 1650103669.108851, + 1650103715.6338923, + 1650103792.0688775, + 1650103848.74207, + 1650103929.5856616, + 1650104068.4825075, + 1650104211.148559, + 1650104242.4403458, + 1650104410.298269, + 1650104561.913953, + 1650104761.2695749, + 1650104807.013614, + 1650104867.3241987, + 1650105102.2744603, + 1650105197.1579733, + 1650105202.8585582, + 1650105210.2589703, + 1650105235.6373727, + 1650105264.9144416, + 1650105289.841991, + 1650105298.780408 ] \ No newline at end of file diff --git a/default.css b/default.css index fc03270..9be6230 100644 --- a/default.css +++ b/default.css @@ -137,6 +137,11 @@ p { } .side_found { margin-top: 100} + +/* +If a screen is at least 1024 pixels wide, we do some more things. +*/ + @media screen and (min-width: 1024px) { .recomendations { margin-left: 40%;} @@ -151,4 +156,15 @@ p { top:100; left:5%;} } +/* prgoress bar theme */ + +.back_progress {background-color: #543ba3; + width: 100%; + height: 7} +.back_progress:hover { + background-color: #CC35F0; +} +.front_progress {background-color: #96bbe8; + height: 7} + } diff --git a/faq.html b/faq.html index 8470ddb..27c2acc 100644 --- a/faq.html +++ b/faq.html @@ -1,17 +1,4 @@ - -
Some test text
- +

Frequently Asked Questions:

@@ -73,6 +60,30 @@

+
+ Does this website uses JavaScript? +

+ + No. We do not use a single line of JavaScript. Now, you are probably wondering how we make so many cool things with the website. Like progress bars and graphs? Well, we are using CSS for it. And CSS is really all you need to render pretty websites. JavaScript is really unnecessary. You can right-click and see sources of the pages. They have comments. + +

+
+ +
+ Does this website uses cookies or other trackers? +

+ + We do not use cookies. We respect the privacy of every person. Furthermore this website is designed to work over Tor. If you are connecting via .onion domain, we do not even see what Tor node is connecting. For the server, it seems like it's connecting to itself. So, if you using .onion site, we don't have anyway to even tell whether you connected to it before. Or how many times you connected to it. At a non .onion instance, your IP address will be visible to the website operator. The software is not configured to record them. But you have to trust the website operator. So we are advising to still use .onion version, or simply connect over Tor or VPN ( to anything ).

+ +

We do however see what is being searched. What pages are requested to be served and how often they are requested. For example, if you are requesting to see the Free Competitors for let's say WhatsApp it will request the server to render and send back the WhatsApp page. We can see when the server does it and what page is requested.

+ +

This fact lets us generate truly anonymous analytics. For example, we can detect what software is being searched, but not yet added into our database. So to create a list for us on what to work on.

+ +

One more thing that we can use it for. Is to get a general usage analytics. Without counties and people's names. Just the amounts and times people used the site. For example, each time you load the web-site for the first time ( on each session of your browser ) it will request the favicon. A little logo to put in the corner of the tab. It does it only once per session ( usually ). So we can record the times when the favicon was requested to get a general idea of how many users use the site. Without knowing who they are, or anything about them. + +

+
+
How does it find Competitors?

@@ -134,3 +145,5 @@

Now search for something and get a list of Free Competitors for it. + diff --git a/modules/missing.py b/modules/missing.py index a53cf85..0aa1f4f 100644 --- a/modules/missing.py +++ b/modules/missing.py @@ -161,3 +161,51 @@ def List(): else: s = s + " | |" print(s) + + +def List_html(): + + # This function will list missing in html format + + try: + with open("data/missing.json") as json_file: + missing = json.load(json_file) + + # Reverse the old file + if type(missing) == dict: + missing = [] + + except: + missing = [] + + page = """ + +

Known Missing Software

+ +

This list is auto-generated by the server software when the software + cannot find a '.json' for for the searched query. It may or may not + be know to the developers, or even to the server operators. So please report + the software into + the Missing Software Page in our source code repository.

+ + """ + + + for i in missing: + i = sorted(i.items(), key=lambda x:x[1]) + i = dict(i) + + if len(i) > 1: + page = page + "
"+list(i.keys())[0]+"" + for b in i: + if b == list(i.keys())[0]: + continue + if b == list(i.keys())[-1]: + comma = "" + page = page + "    " + b + "
" + page = page + "
" + else: + page = page + list(i.keys())[0]+"
" + page = page + "\n\n" + + return page diff --git a/modules/render.py b/modules/render.py index d176237..6afd15b 100644 --- a/modules/render.py +++ b/modules/render.py @@ -7,7 +7,9 @@ # your ability to set it up and running. import os +import time from modules import search +from modules import missing def html(page, json): @@ -318,7 +320,11 @@ def source_code_link(page): - + + + @@ -337,6 +343,10 @@ def source_code_link(page): + +
+ +
+
+
@@ -358,19 +368,11 @@ def progress(page, frac, text=""): page = page + """ - - - - - +
@@ -379,3 +381,62 @@ def progress(page, frac, text=""):   """+str(text)+""" """ return page + +def stats(page, mis=False, data=[]): + + + # Graph will require some math to work. + # We are going to use CSS and HTML5 to + # draw it / interact with it. + + spd = 60*60*24 # Seconds in each day + span = max(data) - min(data) # Time of seconds between first and last entry + days = span / spd # Time in days between first and last entry + + # making sure there is at least something to show + if days < 20: + data.append(min(data)-(spd*20)) + spd = 60*60*24 + span = max(data) - min(data) + days = span / spd + + + + widthfrac = 100 / days # the % to use for the width of each div + + # Count how much hits happen per each day + biggest = 0 + day_counts = [] + print(days) + for d in range(int(round(days))): + count = 0 + for i in data: + day = min(data) + (d*spd) + if int(i) in range(int(day), int(day+spd)): + count += 1 + if count > biggest: + biggest = count + day_counts.append(count) + + # Render them + page = page +"
" + for n, d in enumerate(day_counts): + if n == 0: + d -= 1 + + dayis = min(data)+(n*spd) + dayis = time.strftime("%Y/%m/%d", time.gmtime( dayis) ) + + page = page + '
\n' + frac = 100-(d/biggest*100) + page = page + '
\n\n' + + page = page + '\n
\n\n
' + # If to render missing software + + if mis: + page = page + missing.List_html() + + + page = source_code_link(page) + return page diff --git a/server.py b/server.py index 1eaaf02..828c06e 100644 --- a/server.py +++ b/server.py @@ -92,6 +92,12 @@ class handler(BaseHTTPRequestHandler): 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 = '' @@ -99,7 +105,9 @@ class handler(BaseHTTPRequestHandler): text = text + "\n" text = text + ''+csstext+'\n\n' text = text + "\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' @@ -145,9 +153,9 @@ class handler(BaseHTTPRequestHandler): # The css file - cssfile = open("default.css") + cssfile = open("default.css", "rb") cssfile = cssfile.read() - self.send(cssfile) + self.wfile.write(cssfile) elif self.path == "/font": @@ -155,7 +163,7 @@ class handler(BaseHTTPRequestHandler): fontfile = open("OpenSans-ExtraBold.ttf", "rb") fontfile = fontfile.read() - self.send(fontfile) + self.wfile.write(fontfile) elif self.path in ["/faq", "/faq?"]: @@ -194,6 +202,20 @@ class handler(BaseHTTPRequestHandler): 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: