connpy/connpy/api.py

187 lines
5.1 KiB
Python
Executable File

from flask import Flask, request, jsonify
from connpy import configfile, node, nodes, hooks
from connpy.ai import ai as myai
from waitress import serve
import os
import signal
app = Flask(__name__)
conf = configfile()
PID_FILE1 = "/run/connpy.pid"
PID_FILE2 = "/tmp/connpy.pid"
@app.route("/")
def root():
return jsonify({
'message': 'Welcome to Connpy api',
'version': '1.0',
'documentation': 'https://fluzzi.github.io/connpy/'
})
@app.route("/list_nodes", methods=["POST"])
def list_nodes():
conf = app.custom_config
case = conf.config["case"]
try:
data = request.get_json()
filter = data["filter"]
if not case:
if isinstance(filter, list):
filter = [item.lower() for item in filter]
else:
filter = filter.lower()
output = conf._getallnodes(filter)
except:
output = conf._getallnodes()
return jsonify(output)
@app.route("/get_nodes", methods=["POST"])
def get_nodes():
conf = app.custom_config
case = conf.config["case"]
try:
data = request.get_json()
filter = data["filter"]
if not case:
if isinstance(filter, list):
filter = [item.lower() for item in filter]
else:
filter = filter.lower()
output = conf._getallnodesfull(filter)
except:
output = conf._getallnodesfull()
return jsonify(output)
@app.route("/ask_ai", methods=["POST"])
def ask_ai():
conf = app.custom_config
data = request.get_json()
input = data["input"]
if "dryrun" in data:
dryrun = data["dryrun"]
else:
dryrun = False
if "chat_history" in data:
chat_history = data["chat_history"]
else:
chat_history = None
ai = myai(conf)
return ai.ask(input, dryrun, chat_history)
@app.route("/confirm", methods=["POST"])
def confirm():
conf = app.custom_config
data = request.get_json()
input = data["input"]
ai = myai(conf)
return str(ai.confirm(input))
@app.route("/run_commands", methods=["POST"])
def run_commands():
conf = app.custom_config
data = request.get_json()
case = conf.config["case"]
mynodes = {}
args = {}
try:
action = data["action"]
nodelist = data["nodes"]
args["commands"] = data["commands"]
if action == "test":
args["expected"] = data["expected"]
except KeyError as e:
error = "'{}' is mandatory".format(e.args[0])
return({"DataError": error})
if isinstance(nodelist, list):
mynodes = conf.getitems(nodelist)
else:
if not case:
nodelist = nodelist.lower()
if nodelist.startswith("@"):
mynodes = conf.getitem(nodelist)
else:
mynodes[nodelist] = conf.getitem(nodelist)
mynodes = nodes(mynodes, config=conf)
try:
args["vars"] = data["vars"]
except:
pass
try:
options = data["options"]
thisoptions = {k: v for k, v in options.items() if k in ["prompt", "parallel", "timeout"]}
args.update(thisoptions)
except:
options = None
if action == "run":
output = mynodes.run(**args)
elif action == "test":
output = {}
output["result"] = mynodes.test(**args)
output["output"] = mynodes.output
else:
error = "Wrong action '{}'".format(action)
return({"DataError": error})
return output
@hooks.MethodHook
def stop_api():
# Read the process ID (pid) from the file
try:
with open(PID_FILE1, "r") as f:
pid = int(f.readline().strip())
port = int(f.readline().strip())
PID_FILE=PID_FILE1
except:
try:
with open(PID_FILE2, "r") as f:
pid = int(f.readline().strip())
port = int(f.readline().strip())
PID_FILE=PID_FILE2
except:
print("Connpy api server is not running.")
return
# Send a SIGTERM signal to the process
try:
os.kill(pid, signal.SIGTERM)
except:
pass
# Delete the PID file
os.remove(PID_FILE)
print(f"Server with process ID {pid} stopped.")
return port
@hooks.MethodHook
def debug_api(port=8048):
app.custom_config = configfile()
app.run(debug=True, port=port)
@hooks.MethodHook
def start_server(port=8048):
app.custom_config = configfile()
serve(app, host='0.0.0.0', port=port)
@hooks.MethodHook
def start_api(port=8048):
if os.path.exists(PID_FILE1) or os.path.exists(PID_FILE2):
print("Connpy server is already running.")
return
pid = os.fork()
if pid == 0:
start_server(port)
else:
try:
with open(PID_FILE1, "w") as f:
f.write(str(pid) + "\n" + str(port))
except:
try:
with open(PID_FILE2, "w") as f:
f.write(str(pid) + "\n" + str(port))
except:
print("Cound't create PID file")
return
print(f'Server is running with process ID {pid} in port {port}')