Merge pull request #7 from KevinMidboe/status

Status
This commit is contained in:
2017-03-05 00:36:26 +01:00
committed by GitHub
9 changed files with 136 additions and 202 deletions

6
README.md Normal file
View File

@@ -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

59
app.py
View File

@@ -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)

View File

@@ -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')
pprint(plexSearch("star"))

View File

@@ -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))
pprint(tmdbSearch("star+wars",1))

View File

@@ -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,16 +25,9 @@ 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__":

View File

@@ -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 = '/'
try:
s = statvfs(path)
byteLeft = s.f_bavail * s.f_frsize
byteTotal = s.f_blocks * s.f_frsize
byteUsed = byteTotal-byteLeft
if not path.isdir(rootPath):
return {"errors": "Directory does not exist."}
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())

View File

@@ -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']

25
status/load.py Executable file
View File

@@ -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())

View File

@@ -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())