mirror of
https://github.com/KevinMidboe/Node-Com-Handler.git
synced 2025-10-29 09:40:27 +00:00
6
README.md
Normal file
6
README.md
Normal 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
|
||||
57
app.py
57
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)
|
||||
|
||||
@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)
|
||||
|
||||
@@ -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"))
|
||||
|
||||
77
plex/tmdb.py
77
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))
|
||||
pprint(tmdbSearch("star+wars",1))
|
||||
@@ -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:
|
||||
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()
|
||||
except AttributeError:
|
||||
error = "'sensors_temperatures' is not supported in this verison of psutil or your OS."
|
||||
print(error)
|
||||
return None
|
||||
|
||||
# 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
|
||||
return {"Avg cpu temp": avgCpuTemps, "Max cpu temp": max(curCpuTemps),
|
||||
"Min cpu temp": min(curCpuTemps)}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -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)
|
||||
if not path.isdir(rootPath):
|
||||
return {"errors": "Directory does not exist."}
|
||||
|
||||
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) }
|
||||
|
||||
except FileNotFoundError:
|
||||
return None
|
||||
except TypeError:
|
||||
return None
|
||||
|
||||
if __name__=="__main__":
|
||||
n = diskUsage('/media/hdd1')
|
||||
print(n)
|
||||
print(diskUsage())
|
||||
|
||||
@@ -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
25
status/load.py
Executable 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())
|
||||
@@ -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,7 +14,6 @@ def secToDay(seconds):
|
||||
days = int(seconds/86400)
|
||||
if days is 1:
|
||||
return str(days)+' day'
|
||||
else:
|
||||
return str(days)+' days'
|
||||
|
||||
def secToHour(seconds):
|
||||
@@ -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())
|
||||
Reference in New Issue
Block a user