diff --git a/README.md b/README.md new file mode 100644 index 0000000..245be4a --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Node-Com-Handler +Internal API for getting status on all connected nodes on network + +## Setup + +## Other things to do when you fill in this document diff --git a/app.py b/app.py index 5bbd367..32f60a5 100755 --- a/app.py +++ b/app.py @@ -12,10 +12,11 @@ from werkzeug.security import generate_password_hash, \ from status.diskusage import diskUsage from status.uptime import timeSinceBoot +from status.load import load from status.cpuTemp import getCpuTemp -from plex.tmdb import tmdbSearch -from plex.plexMovies import getSpecificMovieInfo +from plex.tmdb import tmdbSearch +from plex.plexSearch import plexSearch app = Flask(__name__, static_url_path = "") auth = HTTPBasicAuth() @@ -51,7 +52,7 @@ def get_pw(username): # to not match. @auth.error_handler def unauthorized(): - return make_response(jsonify({'error': 'Unauthorized access'}), 401) + return make_response(jsonify({'errors': 'Unauthorized access'}), 401) # This would be replaced with a database, but single process and thread # can use local data like this for simplicity. @@ -60,39 +61,31 @@ def unauthorized(): # Want all return data to be JSON so create custom error response @app.errorhandler(404) def not_found(error): - return make_response(jsonify({'error': 'Not found'}), 404) + return make_response(jsonify({'errors': 'Not found'}), 404) @app.errorhandler(400) def bad_request(error): - return make_response(jsonify({'error': 'Bad request'}), 400) + return make_response(jsonify({'errors': 'Bad request'}), 400) # --- Apollo Activity --- # +@app.route('/api/v1/load', methods=['GET']) +def get_load(): + return jsonify(load()) + @app.route('/api/v1/disks', methods=['GET']) -@auth.login_required def get_diskUsage(): - returningDiskUsage = diskUsage(request.args.get('dir')) - if returningDiskUsage != None: - return jsonify(returningDiskUsage) - else: - abort(404) + return jsonify(diskUsage(request.args.get('dir'))) @app.route('/api/v1/uptimes', methods=['GET']) -@auth.login_required def get_uptimes(): - try: - return jsonify({ 'uptime': timeSinceBoot() }) - except: - abort(404) + return jsonify({ 'uptime': timeSinceBoot() }) @app.route('/api/v1/temps', methods=['GET']) def get_temps(): - cpuTemp = getCpuTemp() - if cpuTemp != None: - return jsonify( {"Avg cpu temp": cpuTemp} ) - else: - return jsonify( {"Error":"Temp reading not supported for host machine."} ) + return jsonify(getCpuTemp()) + # TODO PLEX # Search, watching, +photo @@ -103,15 +96,15 @@ def get_movieRequest(): # TODO if list is empty return jsonify(tmdbSearch(query)) - else: return jsonify({ "Error": "Query not defined." }) + else: return jsonify({ "errors": "Query not defined." }) @app.route('/api/v1/plex/movies', methods=['GET']) -@auth.login_required def getPlexMovies(): title = request.args.get('title') - movieInfo = getSpecificMovieInfo(title) + movieInfo = plexSearch(title) if movieInfo != None: + print(movieInfo) return jsonify(movieInfo) abort(500) @@ -127,24 +120,6 @@ def getPlexWatchings(): return jsonify(movieInfo) -@app.route('/api/v1/uptimes/duration', methods=['GET']) -@auth.login_required -def get_uptimesDuration(): - up = uptime.uptime() - return jsonify( {'Duration': up.duration} ) - -@app.route('/api/v1/uptimes/users', methods=['GET']) -@auth.login_required -def get_uptimesUsers(): - up = uptime.uptime() - return jsonify( {'Users': up.users} ) - -@app.route('/api/v1/uptimes/load', methods=['GET']) -@auth.login_required -def get_uptimesLoad(): - up = uptime.uptime() - return jsonify( {'Load': up.load} ) - if __name__ == '__main__': app.run(host="0.0.0.0",port=63590, debug=True) diff --git a/plex/plexSearch.py b/plex/plexSearch.py index 3ff407f..8d15fcf 100755 --- a/plex/plexSearch.py +++ b/plex/plexSearch.py @@ -3,9 +3,10 @@ # @Author: KevinMidboe # @Date: 2017-02-08 14:00:04 # @Last Modified by: KevinMidboe -# @Last Modified time: 2017-02-10 01:31:43 +# @Last Modified time: 2017-02-18 11:37:08 -from requests import get +import requests +from pprint import pprint plexBaseURL = "http://10.0.0.41:32400/" @@ -42,21 +43,36 @@ def getShowInfo(item): return {"title":title, "year":year, "seasons":seasons, "episodes":episodes, "rating":rating, "art":art, "thumb":thumb} + + +def plexSearch(query): + payload = {"query":query, "type":"1,2"} + header = {'Accept': 'application/json'} + r = requests.get(plexBaseURL+"search",params=payload, headers=header) + + rObject = r.json()["MediaContainer"] + if (r.status_code != requests.codes.ok or rObject["size"] == 0): + return {"errors": "Nothing found for query: " + query} + + return rObject["Metadata"] + + ## MAJOR TODO # Seems to be a change in the return obj. # This looks way more like json. Need to re-write all this. # IDEA: Send the size and resolution for comaprison # No this is for a admin page. OR maybe a github project for # people wanting to update movies. MAJOR IDEA HERE NOW! :D -def plexSearch(query): +def plexXMLSearch(query): + print(query) requestType = "search?" requestQuery = "query=" + str(query) header = {'Accept': 'application/json'} url = plexBaseURL + requestType + requestQuery - response = get(url, headers=header) - print(response.json()) + response = requests.get(url, headers=header) + pprint(response.json()) if response.status_code == 200: resContent = response.json() media = [] @@ -74,7 +90,4 @@ def plexSearch(query): if __name__ == "__main__": # print(plexSearch("star+wars")) - tiss = plexSearch("star+wars") - for al in tiss: - if (al['year']==2015): - print('thishsihis') \ No newline at end of file + pprint(plexSearch("star")) diff --git a/plex/tmdb.py b/plex/tmdb.py index 0ce0db2..e0ba33d 100755 --- a/plex/tmdb.py +++ b/plex/tmdb.py @@ -3,77 +3,48 @@ # @Author: KevinMidboe # @Date: 2017-02-08 14:00:04 # @Last Modified by: KevinMidboe -# @Last Modified time: 2017-02-08 23:19:53 +# @Last Modified time: 2017-02-16 17:08:08 -from requests import get +import requests +from pprint import pprint try: from plexSearch import plexSearch except ImportError: from plex.plexSearch import plexSearch -tmdbBaseURL = "https://api.themoviedb.org/3/" - -def checkPlexExistance(tmdb, plex): - # THIS IS ONLY COMPARED ON YEAR - yearList = [movie["year"] for movie in plex] - print(yearList) - - for movie in tmdb["movies"]: - print(movie["year"]) - movie["exists"] = movie["year"] in str(yearList) - - return tmdb - -def createTMDBResultList(resContent): - movies = [] - tvshows = [] - - for res in resContent["results"]: - if res["media_type"] == "movie": - id = res["id"] - title = res["original_title"] - year = res["release_date"][:4] - poster_path = res["poster_path"] - - movies.append({"id": id, "title": title, "year": year, "poster_path": poster_path}) - - elif res["media_type"] == "tv": - id = res["id"] - name = res["original_name"] - year = res["first_air_date"][:4] - poster_path = res["poster_path"] - - tvshows.append({"id": id, "title": name, "year": year, "poster_path": poster_path}) - - return { "movies": movies, "tvshows": tvshows } +apiKey = "9fa154f5355c37a1b9b57ac06e7d6712" def tmdbSearch(query, page=1): - requestType = "search/multi?" - requestAPI = "api_key=" + "9fa154f5355c37a1b9b57ac06e7d6712" - requestQuery = "&query=" + str(query) - requestLanguage = "&language=en.US" - requestPage = "&page="+str(page) + payload = {"api_key":apiKey, "query":str(query), "language":"en.US", "page":str(page), } + header = {'Accept': 'application/json'} - url = tmdbBaseURL + requestType + requestAPI + requestQuery + requestLanguage + requestPage - print(url) + try: + r = requests.get("https://api.themoviedb.org/3/search/multi", params=payload, headers=header) + except requests.exceptions.ConnectionError: + return {"errors": "Could not connecting to: tmdb.com"} + except requests.exceptions.Timeout: + return {"errors": "Request timed out."} + except requests.exceptions.TooManyRedirects: + return {"errors": "Too many redirects, do you full network access?"} - response = get(url) - if response.status_code == 200: - resContent = response.json() + if r.status_code == 401: + return {"errors": "api key is not valid."} + elif r.status_code == 404: + return {"errors": "Please check url. (404)"} + elif r.status_code == requests.codes.ok and r.json()['total_results'] == 0: + return {"errors": "No results found."} + - plexSearchRes = plexSearch(query) - tmdbSearchRes = createTMDBResultList(resContent) - - return checkPlexExistance(tmdbSearchRes, plexSearchRes) + return r.json() if __name__ == "__main__": import sys print(sys.argv) if len(sys.argv) > 2: - print(tmdbSearch(sys.argv[1], int(sys.argv[2]))) + pprint(tmdbSearch(sys.argv[1], int(sys.argv[2]))) elif len(sys.argv) > 1: - print(tmdbSearch(sys.argv[1])) + pprint(tmdbSearch(sys.argv[1])) else: - print(tmdbSearch("star+wars",1)) \ No newline at end of file + pprint(tmdbSearch("star+wars",1)) \ No newline at end of file diff --git a/status/cpuTemp.py b/status/cpuTemp.py index d2fcb82..8c75829 100755 --- a/status/cpuTemp.py +++ b/status/cpuTemp.py @@ -1,16 +1,22 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +# @Author: KevinMidboe +# @Date: 2017-02-15 23:37:36 +# @Last Modified by: KevinMidboe +# @Last Modified time: 2017-02-15 23:49:18 + import psutil +from platform import system + +# TODO: Add cpu reading for macOS def getCpuTemp(): - # Check if sensors_temperatures exists - try: - # Define cpu as function of sensors_temperatures - cpu = psutil.sensors_temperatures() - except AttributeError: - error = "'sensors_temperatures' is not supported in this verison of psutil or your OS." - print(error) - return None + sysName = system() + if sysName != 'Linux': + return {"Error": "Running OS does not support cpu temp reads."} + + # Define cpu as function of sensors_temperatures + cpu = psutil.sensors_temperatures() # Array for temps for each core. curCpuTemps = [] @@ -19,17 +25,10 @@ def getCpuTemp(): curCpuTemps.append(temp[1]) # Append to list print(temp[0]+': '+str(temp[1])) # Print output - # Check if len of curCpuTemps is something so not to - # calculate on a empty list - if len(curCpuTemps) > 0: - # Compute avg of curCpuTemps - avgCpuTemps = sum(curCpuTemps)/len(curCpuTemps) - return avgCpuTemps - print("Avg: " + str(avgCpuTemps)) - else: - print("Couldn't get cpu temp. (division by zero)") - return None - + avgCpuTemps = sum(curCpuTemps)/len(curCpuTemps) + return {"Avg cpu temp": avgCpuTemps, "Max cpu temp": max(curCpuTemps), + "Min cpu temp": min(curCpuTemps)} + if __name__ == "__main__": print(getCpuTemp()) \ No newline at end of file diff --git a/status/diskusage.py b/status/diskusage.py index b790b63..2c219d7 100755 --- a/status/diskusage.py +++ b/status/diskusage.py @@ -3,15 +3,17 @@ # @Author: KevinMidboe # @Date: 2017-01-28 10:54:06 # @Last Modified by: KevinMidboe -# @Last Modified time: 2017-01-31 22:29:43 +# @Last Modified time: 2017-02-18 11:40:34 # f_avail = free blocks avail to non sudo # frsize = fundamental file sys byte size # f_blocks = total number of blocks in the filesystem -from os import statvfs +from os import statvfs, path from re import sub +# TODO: Add multiple dirs. + def sizeof(num, suffix='B'): for unit in ['','K','M','G','T','P','E','Z']: if abs(num) < 1024.0: @@ -20,24 +22,17 @@ def sizeof(num, suffix='B'): return "%.1f%s%s" % (num, 'Y', suffix) # diskUsage uses statvfs to calculate disk size and availability for given disk -def diskUsage(optionalPath=None): - path = '/' - if optionalPath != None: - path += sub('\+', '/', optionalPath) +def diskUsage(rootPath=None): + if rootPath == None: rootPath = '/' + + if not path.isdir(rootPath): + return {"errors": "Directory does not exist."} - try: - s = statvfs(path) - byteLeft = s.f_bavail * s.f_frsize - byteTotal = s.f_blocks * s.f_frsize - byteUsed = byteTotal-byteLeft - - return { 'left':sizeof(byteLeft), 'used':sizeof(byteUsed), 'total':sizeof(byteTotal) } - - except FileNotFoundError: - return None - except TypeError: - return None + s = statvfs(rootPath) + byteLeft = s.f_bavail * s.f_frsize + byteTotal = s.f_blocks * s.f_frsize + byteUsed = byteTotal-byteLeft + return { 'left': sizeof(byteLeft), 'used': sizeof(byteUsed), 'total': sizeof(byteTotal) } if __name__=="__main__": - n = diskUsage('/media/hdd1') - print(n) + print(diskUsage()) diff --git a/status/linuxcpureader.py b/status/linuxcpureader.py deleted file mode 100644 index 72943c4..0000000 --- a/status/linuxcpureader.py +++ /dev/null @@ -1,48 +0,0 @@ - -from functools import partial -from os import path - - -class LinuxCpuTemperatureReader(): - files = [ - '/sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01/thermal_zone/temp', - '/sys/bus/acpi/devices/LNXTHERM:00/thermal_zone/temp', - '/proc/acpi/thermal_zone/THM0/temperature', - '/proc/acpi/thermal_zone/THRM/temperature', - '/proc/acpi/thermal_zone/THR1/temperature' - ] - - @classmethod - def get_reader(cls): - readers = { - cls.files[0]: cls.reader1, - cls.files[1]: cls.reader1, - cls.files[2]: cls.reader2, - cls.files[3]: cls.reader2, - cls.files[4]: cls.reader2 - } - for file in cls.files: - if path.exists(file): - reader = readers.get(file) - if reader: - print(reader(file)) - return reader(file) - - @classmethod - def reader1(cls, file): - def reader(file): - temperature = open(file).read().strip() - temperature = int(temperature) // 1000 - return temperature - return partial(reader, file) - - @classmethod - def reader2(cls, file): - def reader(file): - temperature = open(file).read().strip() - temperature = temperature.lstrip('temperature :').rstrip(' C') - return int(temperature) - return partial(reader, file) - - -__all__ = ['LinuxCpuTemperatureReader'] diff --git a/status/load.py b/status/load.py new file mode 100755 index 0000000..55e23f9 --- /dev/null +++ b/status/load.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# @Author: KevinMidboe +# @Date: 2017-02-15 23:45:16 +# @Last Modified by: KevinMidboe +# @Last Modified time: 2017-02-18 11:42:42 + +from subprocess import check_output +from re import findall +from platform import system + +def load(): + sysName = system() # Get system name + if sysName == 'Linux': + arpOutput = check_output("cat /proc/loadavg", shell=True) + elif sysName == 'Darwin': # macOS + arpOutput = check_output("uptime", shell=True) + else: + return {"errors": "Running OS does not supported load."} + + arpOutput = arpOutput.decode() + return {"loads": findall('[0-9]{1,2}[\.][0-9]{2}', arpOutput)} + +if __name__ == '__main__': + print(load()) diff --git a/status/uptime.py b/status/uptime.py index 5ab8e3e..c277e5d 100755 --- a/status/uptime.py +++ b/status/uptime.py @@ -3,7 +3,7 @@ # @Author: KevinMidboe # @Date: 2017-01-27 19:48:42 # @Last Modified by: KevinMidboe -# @Last Modified time: 2017-02-03 12:33:51 +# @Last Modified time: 2017-02-18 11:49:30 # TODO add better error handling to return statements @@ -14,8 +14,7 @@ def secToDay(seconds): days = int(seconds/86400) if days is 1: return str(days)+' day' - else: - return str(days)+' days' + return str(days)+' days' def secToHour(seconds): hours = (seconds)//3600 @@ -28,16 +27,15 @@ def timeSinceBoot(): currTime = time() # Use 'time()' to get seconds currently deltaSeconds = int(currTime-bootTime) - # Return in day format - if deltaSeconds >= 86400: - return secToDay(deltaSeconds) + if deltaSeconds >= 86400: # Return in day format + uptime = secToDay(deltaSeconds) - # Return in hour format elif deltaSeconds < 86400 and deltaSeconds >= 0: - return secToHour(deltaSeconds) + uptime = secToHour(deltaSeconds) else: - # TODO Throw error - return None + return {"errors": "Uptime not found"} + + return {"uptime": uptime} if __name__=="__main__": print(timeSinceBoot()) \ No newline at end of file