1
0
mirror of https://github.com/fHDHR/fHDHR_NextPVR.git synced 2025-12-06 06:56:57 -05:00

Merge pull request #41 from deathbybandaid/dev

Dev
This commit is contained in:
Deathbybandaid 2020-10-28 13:51:19 -04:00 committed by GitHub
commit eadb5e5385
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 498 additions and 81 deletions

8
data/www/style.css Normal file
View File

@ -0,0 +1,8 @@
.pull-right { float: right; }
.pull-lef { float: left; }
.center {
margin-left: auto;
margin-right: auto;
}

View File

@ -1,2 +1,2 @@
# coding=utf-8
fHDHR_VERSION = "v0.2.2-beta"
fHDHR_VERSION = "v0.2.9-beta"

View File

@ -15,6 +15,19 @@ class HDHR_HTTP_Server():
base_url = request.headers["host"]
return fhdhrhub.get_index_html(base_url)
@app.route('/guide')
def channel_guide_html():
return fhdhrhub.get_channel_guide_html()
@app.route('/origin')
def origin_html():
base_url = request.headers["host"]
return fhdhrhub.get_origin_html(base_url)
@app.route('/style.css', methods=['GET'])
def style_css():
return send_from_directory(fhdhrhub.config.dict["filedir"]["www_dir"], 'style.css')
@app.route('/favicon.ico', methods=['GET'])
def favicon():
return send_from_directory(fhdhrhub.config.dict["filedir"]["www_dir"],
@ -79,6 +92,16 @@ class HDHR_HTTP_Server():
mimetype='application/xml')
return "not subscribed"
@app.route('/diagnostics', methods=['GET'])
def debug_html():
base_url = request.headers["host"]
return fhdhrhub.get_diagnostics_html(base_url)
@app.route('/version', methods=['GET'])
def version_html():
base_url = request.headers["host"]
return fhdhrhub.get_version_html(base_url)
@app.route('/debug.json', methods=['GET'])
def debug_json():
base_url = request.headers["host"]
@ -96,6 +119,14 @@ class HDHR_HTTP_Server():
response=channels_m3u,
mimetype='text/plain')
@app.route('/<channel>.m3u', methods=['GET'])
def channel_m3u(channel):
base_url = request.headers["host"]
channel_m3u = fhdhrhub.get_channel_m3u(base_url, channel)
return Response(status=200,
response=channel_m3u,
mimetype='text/plain')
@app.route('/images', methods=['GET'])
def images():
image, imagetype = fhdhrhub.get_image(request.args)

View File

@ -11,10 +11,10 @@ class fHDHR_Hub():
self.origin = origin
self.pages = pages.fHDHR_Pages(settings)
self.device = device.fHDHR_Device(settings, origin)
self.pages = pages.fHDHR_Pages(settings, self.device)
self.files = files.fHDHR_Files(settings, self.device)
def get_xmltv(self, base_url):
@ -50,6 +50,9 @@ class fHDHR_Hub():
def get_channels_m3u(self, base_url):
return self.files.m3u.get_channels_m3u(base_url)
def get_channel_m3u(self, base_url, channel_number):
return self.files.m3u.get_channel_m3u(base_url, channel_number)
def get_stream_info(self, stream_args):
return self.device.watch.get_stream_info(stream_args)
@ -58,3 +61,15 @@ class fHDHR_Hub():
def get_index_html(self, base_url):
return self.pages.index.get_index_html(base_url)
def get_channel_guide_html(self):
return self.pages.channel_guide.get_channel_guide_html()
def get_diagnostics_html(self, base_url):
return self.pages.diagnostics.get_diagnostics_html(base_url)
def get_version_html(self, base_url):
return self.pages.version.get_version_html(base_url)
def get_origin_html(self, base_url):
return self.pages.origin.get_origin_html(base_url)

View File

@ -14,7 +14,7 @@ class fHDHR_Device():
self.epg = epg.EPG(settings, self.channels)
self.tuners = Tuners(settings)
self.tuners = Tuners(settings, self.epg)
self.watch = WatchStream(settings, self.channels, self.tuners)

View File

@ -56,6 +56,12 @@ class Channels():
self.list_update_time = None
self.get_channels()
def get_origin_status(self):
try:
return self.origin.get_status_dict()
except AttributeError:
return {}
def get_channels(self, forceupdate=False):
"""Pull Channels from origin.

View File

@ -1,6 +1,7 @@
import os
import json
import time
import datetime
from collections import OrderedDict
from multiprocessing import Process
@ -16,6 +17,8 @@ class EPG():
self.origin = origin_epg.originEPG(settings, channels)
self.epgdict = None
self.epg_method_selfadd()
self.epg_method = self.config.dict["fhdhr"]["epg_method"]
@ -31,12 +34,31 @@ class EPG():
self.epgscan = Process(target=self.epgServerProcess)
self.epgscan.start()
def whats_on_now(self, channel):
epgdict = self.get_epg()
listings = epgdict[channel]["listing"]
for listing in listings:
nowtime = datetime.datetime.utcnow()
start_time = datetime.datetime.strptime(listing["time_start"], '%Y%m%d%H%M%S +0000')
end_time = datetime.datetime.strptime(listing["time_end"], '%Y%m%d%H%M%S +0000')
if start_time <= nowtime <= end_time:
epgitem = epgdict[channel].copy()
epgitem["listing"] = [listing]
return epgitem
return None
def whats_on_allchans(self):
channel_guide_list = []
for channel in self.channels.get_channels():
channel_guide_list.append(self.whats_on_now(channel["number"]))
return channel_guide_list
def get_epg(self):
epgdict = None
if os.path.isfile(self.epg_cache_file):
with open(self.epg_cache_file, 'r') as epgfile:
epgdict = json.load(epgfile)
return epgdict
if not self.epgdict:
if os.path.isfile(self.epg_cache_file):
with open(self.epg_cache_file, 'r') as epgfile:
self.epgdict = json.load(epgfile)
return self.epgdict
def get_thumbnail(self, itemtype, itemid):
if itemtype == "channel":
@ -86,6 +108,7 @@ class EPG():
with open(self.epg_cache_file, 'w') as epgfile:
epgfile.write(json.dumps(programguide, indent=4))
print("Wrote " + self.epgtypename + " EPG cache file.")
self.epgdict = programguide
def epgServerProcess(self):
print("Starting EPG thread...")

View File

@ -1,11 +1,14 @@
import threading
import datetime
from fHDHR.exceptions import TunerError
from fHDHR.tools import humanized_time
class Tuner():
def __init__(self, inum):
def __init__(self, inum, epg):
self.number = inum
self.epg = epg
self.tuner_lock = threading.Lock()
self.set_off_status()
@ -20,6 +23,7 @@ class Tuner():
"method": stream_args["method"],
"accessed": stream_args["accessed"],
"proxied_url": stream_args["channelUri"],
"time_start": datetime.datetime.utcnow(),
}
def close(self):
@ -28,25 +32,28 @@ class Tuner():
self.tuner_lock.release()
def get_status(self):
return self.status
current_status = self.status.copy()
if current_status["status"] == "Active":
current_status["Play Time"] = str(
humanized_time(
int((datetime.datetime.utcnow() - current_status["time_start"]).total_seconds())))
current_status["time_start"] = str(current_status["time_start"])
current_status["epg"] = self.epg.whats_on_now(current_status["accessed"].split("v")[-1])
return current_status
def set_off_status(self):
self.status = {
"status": "Inactive",
"method": None,
"accessed": None,
"proxied_url": None,
}
self.status = {"status": "Inactive"}
class Tuners():
def __init__(self, settings):
def __init__(self, settings, epg):
self.config = settings
self.epg = epg
self.max_tuners = int(self.config.dict["fhdhr"]["tuner_count"])
for i in range(1, self.max_tuners + 1):
exec("%s = %s" % ("self.tuner_" + str(i), "Tuner(i)"))
exec("%s = %s" % ("self.tuner_" + str(i), "Tuner(i, epg)"))
def tuner_grab(self, stream_args, tunernum=None):
tunerselected = None
@ -81,3 +88,19 @@ class Tuners():
for tunernum in range(1, self.max_tuners + 1):
all_status[tunernum] = eval("self.tuner_" + str(tunernum) + ".get_status()")
return all_status
def available_tuner_count(self):
available_tuners = 0
for tunernum in range(1, self.max_tuners + 1):
tuner_status = eval("self.tuner_" + str(tunernum) + ".get_status()")
if tuner_status["status"] == "Inactive":
available_tuners += 1
return available_tuners
def inuse_tuner_count(self):
inuse_tuners = 0
for tunernum in range(1, self.max_tuners + 1):
tuner_status = eval("self.tuner_" + str(tunernum) + ".get_status()")
if tuner_status["status"] == "Active":
inuse_tuners += 1
return inuse_tuners

View File

@ -6,7 +6,7 @@ from .lineup_json import Lineup_JSON
from .debug_json import Debug_JSON
from .lineup_status_json import Lineup_Status_JSON
from .xmltv_xml import xmlTV_XML
from .channels_m3u import channels_M3U
from .m3u import channels_M3U
class fHDHR_Files():

View File

@ -53,3 +53,50 @@ class channels_M3U():
)
return fakefile.getvalue()
def get_channel_m3u(self, base_url, channel_number):
FORMAT_DESCRIPTOR = "#EXTM3U"
RECORD_MARKER = "#EXTINF"
fakefile = StringIO()
xmltvurl = ('%s%s/xmltv.xml' %
("http://",
base_url))
fakefile.write(
"%s\n" % (
FORMAT_DESCRIPTOR + " " +
"url-tvg=\"" + xmltvurl + "\"" + " " +
"x-tvg-url=\"" + xmltvurl + "\"")
)
channel = self.device.channels.get_channel_dict("number", channel_number)
logourl = ('%s%s/images?source=epg&type=channel&id=%s' %
("http://",
base_url,
str(channel['id'])))
fakefile.write(
"%s\n" % (
RECORD_MARKER + ":0" + " " +
"channelID=\"" + str(channel['id']) + "\" " +
"tvg-chno=\"" + str(channel['number']) + "\" " +
"tvg-name=\"" + str(channel['name']) + "\" " +
"tvg-id=\"" + str(channel['number']) + "\" " +
"tvg-logo=\"" + logourl + "\" " +
"group-title=\"" + self.config.dict["fhdhr"]["friendlyname"] + "," + str(channel['name']))
)
fakefile.write(
"%s\n" % (
('%s%s/auto/v%s' %
("http://",
base_url,
str(channel['number'])))
)
)
return fakefile.getvalue()

View File

@ -1,11 +1,78 @@
# pylama:ignore=W0611
from .index_html import Index_HTML
from io import StringIO
from .htmlerror import HTMLerror
from .index_html import Index_HTML
from .origin_html import Origin_HTML
from .diagnostics_html import Diagnostics_HTML
from .version_html import Version_HTML
from .channel_guide_html import Channel_Guide_HTML
class fHDHR_Pages():
def __init__(self, settings):
def __init__(self, settings, device):
self.config = settings
self.index = Index_HTML(settings)
self.device = device
self.page_elements = {
"top": self.pagetop(),
"end": self.pageend()
}
self.htmlerror = HTMLerror(settings)
self.index = Index_HTML(settings, self.device, self.page_elements)
self.origin = Origin_HTML(settings, self.device, self.page_elements)
self.diagnostics = Diagnostics_HTML(settings, self.device, self.page_elements)
self.version = Version_HTML(settings, self.device, self.page_elements)
self.channel_guide = Channel_Guide_HTML(settings, self.device, self.page_elements)
def pagetop(self):
friendlyname = self.config.dict["fhdhr"]["friendlyname"]
servicename = str(self.config.dict["main"]["servicename"])
return [
"<!DOCTYPE html>",
"<html>",
"<head>",
"<title>%s</title>" % friendlyname,
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">",
"<style>",
"table, th, td {",
"border: 1px solid black;",
"}",
"</style>",
"<link href=\"style.css\" rel=\"stylesheet\">",
"</head>",
"<h1 id=\"mcetoc_1cdobsl3g0\" style=\"text-align: center;\"><span style=\"text-decoration: underline;\"><strong><em>%s</em></strong></span></h1><br>" % friendlyname,
"",
"<h2>"
"<div>",
"<button class=\"pull-left\" onclick=\"OpenLink('%s')\">%s</a></button>" % ("/", "fHDHR"),
"<button class=\"pull-left\" onclick=\"OpenLink('%s')\">%s</a></button>" % ("/origin", servicename),
"<button class=\"pull-left\" onclick=\"OpenLink('%s')\">%s</a></button>" % ("/guide", "Guide"),
"<button class=\"pull-left\" onclick=\"OpenLink('%s')\">%s</a></button>" % ("/version", "Version"),
"<button class=\"pull-left\" onclick=\"OpenLink('%s')\">%s</a></button>" % ("/diagnostics", "Diagnostics"),
"<a class=\"pull-right\" style=\"padding: 5px;\" href=\"%s\">%s</a>" % ("xmltv.xml", "xmltv"),
"<a class=\"pull-right\" style=\"padding: 5px;\" href=\"%s\">%s</a>" % ("channels.m3u", "m3u"),
"</p>",
"</div>"
"<hr align=\"center\" width=\"100%\">"
]
def pageend(self):
return [
"</html>",
"",
"<script>",
"function OpenLink(NewURL) {",
" window.open(NewURL, \"_self\");",
"}",
"</script>"
]

View File

@ -0,0 +1,61 @@
from io import StringIO
import datetime
from fHDHR.tools import humanized_time
class Channel_Guide_HTML():
def __init__(self, settings, device, page_elements):
self.config = settings
self.device = device
self.page_elements = page_elements
def get_channel_guide_html(self, force_update=False):
friendlyname = self.config.dict["fhdhr"]["friendlyname"]
nowtime = datetime.datetime.utcnow()
fakefile = StringIO()
for line in self.page_elements["top"]:
fakefile.write(line + "\n")
fakefile.write("<h4 id=\"mcetoc_1cdobsl3g0\" style=\"text-align: center;\"><span style=\"text-decoration: underline;\"><strong><em>What's On %s</em></strong></span></h4>\n" % friendlyname)
fakefile.write("\n")
fakefile.write("<table style=\"width:100%\">\n")
fakefile.write(" <tr>\n")
fakefile.write(" <th>Play</th>\n")
fakefile.write(" <th>Channel Name</th>\n")
fakefile.write(" <th>Channel Number</th>\n")
fakefile.write(" <th>Channel Thumbnail</th>\n")
fakefile.write(" <th>Content Title</th>\n")
fakefile.write(" <th>Content Thumbnail</th>\n")
fakefile.write(" <th>Content Description</th>\n")
fakefile.write(" <th>Content Remaining Time</th>\n")
fakefile.write(" </tr>\n")
for channel in self.device.epg.whats_on_allchans():
end_time = datetime.datetime.strptime(channel["listing"][0]["time_end"], '%Y%m%d%H%M%S +0000')
remaining_time = humanized_time(int((end_time - nowtime).total_seconds()))
play_url = ("/%s.m3u\n" % (channel["number"]))
fakefile.write(" <tr>\n")
fakefile.write(" <td><a href=\"%s\">%s</a>\n" % (play_url, "Play"))
fakefile.write(" <td>%s</td>\n" % (channel["name"]))
fakefile.write(" <td>%s</td>\n" % (channel["number"]))
fakefile.write(" <td><img src=\"%s\" alt=\"%s\" width=\"100\" height=\"100\">\n" % (channel["thumbnail"], channel["name"]))
fakefile.write(" <td>%s</td>\n" % (channel["listing"][0]["title"]))
fakefile.write(" <td><img src=\"%s\" alt=\"%s\" width=\"100\" height=\"100\">\n" % (channel["listing"][0]["thumbnail"], channel["listing"][0]["title"]))
fakefile.write(" <td>%s</td>\n" % (channel["listing"][0]["description"]))
fakefile.write(" <td>%s</td>\n" % (str(remaining_time)))
fakefile.write(" </tr>\n")
for line in self.page_elements["end"]:
fakefile.write(line + "\n")
channel_guide_html = fakefile.getvalue()
return channel_guide_html

View File

@ -0,0 +1,43 @@
from io import StringIO
class Diagnostics_HTML():
def __init__(self, settings, device, page_elements):
self.config = settings
self.device = device
self.diagnostics_html = None
self.page_elements = page_elements
def get_diagnostics_html(self, base_url, force_update=False):
if not self.diagnostics_html or force_update:
fakefile = StringIO()
for line in self.page_elements["top"]:
fakefile.write(line + "\n")
# a list of 2 part lists containing button information
button_list = [
["Force Channel Update", "chanscan"],
["debug", "debug.json"],
["device.xml", "device.xml"],
["discover.json", "discover.json"],
["lineup.json", "lineup.json"],
["lineup_status.json", "lineup_status.json"]
]
for button_item in button_list:
button_label = button_item[0]
button_path = button_item[1]
fakefile.write("<div style=\"text-align: center;\">\n")
fakefile.write(" <p><button onclick=\"OpenLink('%s')\">%s</a></button></p>\n" % (button_path, button_label))
fakefile.write("</div>\n")
fakefile.write("\n")
for line in self.page_elements["end"]:
fakefile.write(line + "\n")
self.diagnostics_html = fakefile.getvalue()
return self.diagnostics_html

View File

@ -3,74 +3,47 @@ from io import StringIO
class Index_HTML():
def __init__(self, settings):
def __init__(self, settings, device, page_elements):
self.config = settings
self.index_html = None
self.device = device
self.page_elements = page_elements
def get_index_html(self, base_url, force_update=False):
if not self.index_html or force_update:
friendlyname = self.config.dict["fhdhr"]["friendlyname"]
fakefile = StringIO()
fakefile = StringIO()
for line in self.page_elements["top"]:
fakefile.write(line + "\n")
fakefile.write("<!DOCTYPE html>\n")
fakefile.write("<html>\n")
fakefile.write("<h4 style=\"text-align: center;\">fHDHR Status</h4>")
fakefile.write("\n")
fakefile.write("<head>\n")
fakefile.write("<title>%s</title>\n" % friendlyname)
fakefile.write("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n")
fakefile.write("</head>\n")
fakefile.write("<table class=\"center\" style=\"width:50%\">\n")
fakefile.write(" <tr>\n")
fakefile.write(" <th></th>\n")
fakefile.write(" <th></th>\n")
fakefile.write(" </tr>\n")
fakefile.write("<h2 id=\"mcetoc_1cdobsl3g0\" style=\"text-align: center;\"><span style=\"text-decoration: underline;\"><strong><em>%s</em></strong></span></h2>\n" % friendlyname)
fakefile.write("\n")
total_channels = self.device.channels.get_station_total()
fakefile.write("<h4 style=\"text-align: center;\">Primary fHDHR Links</h4>")
fakefile.write("\n")
tuners_in_use = self.device.tuners.inuse_tuner_count()
max_tuners = self.device.tuners.max_tuners
# a list of 2 part lists containing button information
button_list = [
["xmltv", "xmltv.xml"],
["m3u", "channels.m3u"],
["debug", "debug.json"],
["Force Channel Update", "chanscan"]
]
tableguts = [
["Script Directory", str(self.config.dict["filedir"]["script_dir"])],
["Config File", str(self.config.config_file)],
["Cache Path", str(self.config.dict["filedir"]["cache_dir"])],
["Total Channels", str(total_channels)],
["Tuner Usage", "%s/%s" % (str(tuners_in_use), str(max_tuners))]
]
for button_item in button_list:
button_label = button_item[0]
button_path = button_item[1]
fakefile.write("<div style=\"text-align: center;\">\n")
fakefile.write(" <p><button onclick=\"OpenLink('%s')\">%s</a></button></p>\n" % (button_path, button_label))
fakefile.write("</div>\n")
fakefile.write("\n")
for guts in tableguts:
fakefile.write(" <tr>\n")
fakefile.write(" <td>%s</td>\n" % (guts[0]))
fakefile.write(" <td>%s</td>\n" % (guts[1]))
fakefile.write(" </tr>\n")
fakefile.write("<h4 style=\"text-align: center;\">Other fHDHR Links</h4>")
for line in self.page_elements["end"]:
fakefile.write(line + "\n")
# a list of 2 part lists containing button information
button_list = [
["device.xml", "device.xml"],
["discover.json", "discover.json"],
["lineup.json", "lineup.json"],
["lineup_status.json", "lineup_status.json"]
]
for button_item in button_list:
button_label = button_item[0]
button_path = button_item[1]
fakefile.write("<div style=\"text-align: center;\">\n")
fakefile.write(" <p><button onclick=\"OpenLink('%s')\">%s</a></button></p>\n" % (button_path, button_label))
fakefile.write("</div>\n")
fakefile.write("\n")
fakefile.write("</html>\n")
fakefile.write("\n")
fakefile.write("<script>\n")
fakefile.write("function OpenLink(NewURL) {\n")
fakefile.write(" window.open(NewURL, \"_self\");\n")
fakefile.write("}\n")
fakefile.write("</script>")
self.index_html = fakefile.getvalue()
return self.index_html
return fakefile.getvalue()

View File

@ -0,0 +1,39 @@
from io import StringIO
class Origin_HTML():
def __init__(self, settings, device, page_elements):
self.config = settings
self.device = device
self.page_elements = page_elements
def get_origin_html(self, base_url, force_update=False):
servicename = str(self.config.dict["main"]["servicename"])
fakefile = StringIO()
for line in self.page_elements["top"]:
fakefile.write(line + "\n")
fakefile.write("<h4 style=\"text-align: center;\">%s Status</h4>" % (servicename))
fakefile.write("\n")
fakefile.write("<table class=\"center\" style=\"width:50%\">\n")
fakefile.write(" <tr>\n")
fakefile.write(" <th></th>\n")
fakefile.write(" <th></th>\n")
fakefile.write(" </tr>\n")
origin_status_dict = self.device.channels.get_origin_status()
for key in list(origin_status_dict.keys()):
fakefile.write(" <tr>\n")
fakefile.write(" <td>%s</td>\n" % (str(key)))
fakefile.write(" <td>%s</td>\n" % (str(origin_status_dict[key])))
fakefile.write(" </tr>\n")
for line in self.page_elements["end"]:
fakefile.write(line + "\n")
return fakefile.getvalue()

View File

@ -0,0 +1,34 @@
from io import StringIO
from fHDHR import fHDHR_VERSION
class Version_HTML():
def __init__(self, settings, device, page_elements):
self.config = settings
self.device = device
self.page_elements = page_elements
def get_version_html(self, base_url, force_update=False):
fakefile = StringIO()
for line in self.page_elements["top"]:
fakefile.write(line + "\n")
fakefile.write("<table class=\"center\" style=\"width:50%\">\n")
fakefile.write(" <tr>\n")
fakefile.write(" <th></th>\n")
fakefile.write(" <th></th>\n")
fakefile.write(" </tr>\n")
fakefile.write(" <tr>\n")
fakefile.write(" <td>%s</td>\n" % ("fHDHR"))
fakefile.write(" <td>%s</td>\n" % (str(fHDHR_VERSION)))
fakefile.write(" </tr>\n")
for line in self.page_elements["end"]:
fakefile.write(line + "\n")
return fakefile.getvalue()

View File

@ -30,6 +30,7 @@ class Config():
data_dir = pathlib.Path(script_dir).joinpath('data')
www_dir = pathlib.Path(data_dir).joinpath('www')
www_images_dir = pathlib.Path(www_dir).joinpath('images')
self.dict["filedir"] = {
"script_dir": script_dir,
@ -38,6 +39,7 @@ class Config():
"cache_dir": pathlib.Path(data_dir).joinpath('cache'),
"internal_config": pathlib.Path(data_dir).joinpath('internal_config'),
"www_dir": www_dir,
"www_images_dir": www_images_dir,
"font": pathlib.Path(data_dir).joinpath('garamond.ttf'),
"favicon": pathlib.Path(data_dir).joinpath('favicon.ico'),
"epg_cache": {},

View File

@ -59,6 +59,18 @@ class OriginService():
return loginsuccess
def get_status_dict(self):
nextpvr_address = ('%s%s:%s' %
("https://" if self.config.dict["origin"]["ssl"] else "http://",
self.config.dict["origin"]["address"],
str(self.config.dict["origin"]["port"]),
))
ret_status_dict = {
"Login": "Success",
"Address": nextpvr_address,
}
return ret_status_dict
def get_channels(self):
data_url = ('%s%s:%s/service?method=channel.list&sid=%s' %

View File

@ -76,6 +76,39 @@ def hours_between_datetime(first_time, later_time):
return (timebetween.total_seconds() / 60 / 60)
def humanized_time(countdownseconds):
time = float(countdownseconds)
if time == 0:
return "just now"
year = time // (365 * 24 * 3600)
time = time % (365 * 24 * 3600)
day = time // (24 * 3600)
time = time % (24 * 3600)
time = time % (24 * 3600)
hour = time // 3600
time %= 3600
minute = time // 60
time %= 60
second = time
displaymsg = None
timearray = ['year', 'day', 'hour', 'minute', 'second']
for x in timearray:
currenttimevar = eval(x)
if currenttimevar >= 1:
timetype = x
if currenttimevar > 1:
timetype = str(x+"s")
if displaymsg:
displaymsg = str(displaymsg + " " + str(int(currenttimevar)) + " " + timetype)
else:
displaymsg = str(str(int(currenttimevar)) + " " + timetype)
if not displaymsg:
return "just now"
return displaymsg
# just for ignoring a pep error
year, day, hour, minute, second
class WebReq():
def __init__(self):
self.session = requests.Session()