Compare commits
4 Commits
d6ffa45ee6
...
e3e20a7b07
Author | SHA1 | Date | |
---|---|---|---|
|
e3e20a7b07 | ||
|
2752702d17 | ||
|
a6469184fb | ||
|
4b8e4f9846 |
@ -13,10 +13,9 @@
|
||||
"extensions": [
|
||||
"pomdtr.secrets",
|
||||
"ms-python.python",
|
||||
"donjayamanne.python-extension-pack",
|
||||
"ivory-lab.jenkinsfile-support",
|
||||
"njpwerner.autodocstring",
|
||||
"KevinRose.vsc-python-indent"
|
||||
"NicolasVuillamy.vscode-groovy-lint",
|
||||
"ms-python.pylint"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@ -1,5 +1,6 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"pomdtr.secrets"
|
||||
"pomdtr.secrets",
|
||||
"nicolasvuillamy.vscode-groovy-lint"
|
||||
]
|
||||
}
|
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@ -8,7 +8,7 @@
|
||||
"name": "Start Server",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "src/aidgaf/aidgaf-server/server.py",
|
||||
"program": "src/aidgaf/aidgaf_server/server.py",
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": true
|
||||
},
|
||||
@ -16,7 +16,7 @@
|
||||
"name": "IDGAF",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "src/aidgaf/aidgaf-server/idgaf.py",
|
||||
"program": "src/aidgaf/aidgaf_server/idgaf.py",
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": true
|
||||
},
|
||||
|
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@ -1,5 +1,10 @@
|
||||
{
|
||||
"secrets.enabledFolders": [
|
||||
"aidgaf"
|
||||
]
|
||||
],
|
||||
"files.associations": {
|
||||
"[Jj]enkinsfile*": "groovy"
|
||||
},
|
||||
"python.linting.pylintPath": "/usr/local/python/current/bin/python"
|
||||
|
||||
}
|
@ -17,6 +17,6 @@ FROM alpine:latest
|
||||
RUN apk add python3 py3-pip \
|
||||
&& pip3 install openai\
|
||||
&& mkdir /app
|
||||
COPY src/aidgaf /app
|
||||
COPY src/aidgaf /app/aidgaf
|
||||
EXPOSE 8087
|
||||
ENTRYPOINT ["/usr/bin/python","/app/aidgaf-server/__main__.py",">/dev/stdout"]
|
||||
ENTRYPOINT ["/usr/bin/python","/app/aidgaf/aidgaf_server/__main__.py",">/dev/stdout"]
|
||||
|
50
Jenkinsfile
vendored
50
Jenkinsfile
vendored
@ -1,4 +1,5 @@
|
||||
#! /bin/groovy
|
||||
#!/bin/groovy
|
||||
/* groovylint-disable CompileStatic, DuplicateStringLiteral, LineLength */
|
||||
pipeline {
|
||||
agent {
|
||||
docker {
|
||||
@ -9,18 +10,14 @@ pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
stages {
|
||||
stage('Prepare Environment'){
|
||||
steps{
|
||||
sh "#!/bin/sh \n" +
|
||||
stage('Prepare Environment') {
|
||||
steps {
|
||||
sh '#!/bin/sh \n' +
|
||||
'id; apk add docker openrc git'
|
||||
}
|
||||
}
|
||||
stage('Obtain Source'){
|
||||
stage('Obtain Source') {
|
||||
steps {
|
||||
git branch: 'main', url: 'https://git.adamoutler.com/aoutler/aidgaf-server.git'
|
||||
}
|
||||
@ -28,42 +25,35 @@ pipeline {
|
||||
stage('Build in docker') {
|
||||
steps {
|
||||
// Get some code from a Git repository
|
||||
sh "#!/bin/sh \n" +
|
||||
sh '#!/bin/sh \n' +
|
||||
'docker build -t aidgaf .'
|
||||
}
|
||||
}
|
||||
stage ("setup credentials"){
|
||||
steps{
|
||||
stage('setup credentials') {
|
||||
steps {
|
||||
withCredentials([ sshUserPrivateKey(credentialsId: 'dockeruserOn192.168.1.115', keyFileVariable: 'sshkey', usernameVariable: 'user')]) {
|
||||
sh "#!/bin/sh \n" +
|
||||
sh '#!/bin/sh \n' +
|
||||
'set +e; docker stop aidgaf-server||echo machine stopped; docker rm aidgaf-server||echo machine does not exist; set -e'
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
stage ('export docker container'){
|
||||
stage('export docker container') {
|
||||
steps {
|
||||
|
||||
sh "#!/bin/sh \n" +
|
||||
sh '#!/bin/sh \n' +
|
||||
'set +e; docker stop aidgaf-server||echo machine stopped; docker rm aidgaf-server||echo machine does not exist; set -e'
|
||||
withCredentials([
|
||||
string(credentialsId: 'OpenAI-API-Token', variable: 'OPEN_AI_TOKEN'),
|
||||
string(credentialsId: 'PapaHashingSecret', variable: 'PAPA_HASH'),
|
||||
sshUserPrivateKey(credentialsId: 'dockeruserOn192.168.1.115', keyFileVariable: 'sshkey', usernameVariable: 'user')
|
||||
string(credentialsId: 'PapaAsyncUrl', variable: 'ASYNC_URL'),
|
||||
sshUserPrivateKey(credentialsId: 'dockeruserOn192.168.1.115', keyFileVariable: 'sshkey')
|
||||
]) {
|
||||
sh "#!/bin/sh \n" +
|
||||
'mkdir -p ~/.ssh; cp "${sshkey}" ~/.ssh/id_rsa'
|
||||
sh "#!/bin/sh \n" +
|
||||
'docker run --name=aidgaf-server -eSERVERPORT=8087 -eHOSTNAME=0.0.0.0 -eHASHKEY="${PAPA_HASH}" -eAPIKEY="${OPEN_AI_TOKEN}" -p8087:8087 -d --restart=always aidgaf'
|
||||
}
|
||||
sh '#!/bin/sh \n' +
|
||||
'mkdir -p ~/.ssh; cp "$sshkey" ~/.ssh/id_rsa'
|
||||
sh '#!/bin/sh \n' +
|
||||
/* groovylint-disable-next-line GStringExpressionWithinString */
|
||||
'docker run --name=aidgaf-server -eSERVERPORT=8087 -eHOSTNAME=0.0.0.0 -eHASHKEY="${PAPA_HASH}" -eAPIKEY="${OPEN_AI_TOKEN}" -eASYNC_METHOD="PATCH" -eASYNC_URL="${} -p8087:8087 -d --restart=always aidgaf'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// To run Maven on a Windows agent, use
|
||||
// bat "mvn -Dmaven.test.failure.ignore=true clean package"
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
""" aidgaf-server. """
|
||||
|
||||
""" The name of the package"""
|
||||
name = 'aidgaf'
|
||||
|
||||
""" The version of the package"""
|
||||
version='0.1.0'
|
@ -1,5 +0,0 @@
|
||||
""" aidgaf-server entry point. """
|
||||
import server
|
||||
|
||||
""" The main entry point for the aidgaf-server package."""
|
||||
server.main()
|
@ -1,4 +0,0 @@
|
||||
"""Constants for the aidgaf-server package."""
|
||||
|
||||
""" The encoding to use for strings. """
|
||||
UTF8="utf-8"
|
@ -1,109 +0,0 @@
|
||||
""" aidgaf-server - A simple server to handle requests from the aidgaf client.
|
||||
This server will communicate with OpenAI to generate responses to the client."""
|
||||
import json
|
||||
import random
|
||||
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
import idgaf
|
||||
import settings
|
||||
import security
|
||||
from const import UTF8
|
||||
|
||||
default_request_body = b'{"message":{"command":"aidgaf","data":{"username":"AdamOutler"}}}'
|
||||
|
||||
|
||||
class IDGAFServer(BaseHTTPRequestHandler):
|
||||
""" This class handles the requests from the client. """
|
||||
|
||||
def do_GET(self):
|
||||
""" This function handles GET requests. """
|
||||
self.send_response(418)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.end_headers()
|
||||
self.wfile.write(bytes("", UTF8))
|
||||
|
||||
def do_PATCH(self):
|
||||
""" This function handles PATCH requests. """
|
||||
body = self.get_body().decode(UTF8)
|
||||
if not perform_sanity_checks(body):
|
||||
self.send_response(403)
|
||||
return
|
||||
command = json.loads(body)
|
||||
self.do_request_handling(command)
|
||||
|
||||
def do_request_handling(self, command):
|
||||
""" This function handles the request.
|
||||
Parameters:
|
||||
command: The command object received from the client. """
|
||||
print(command)
|
||||
if command['message']['command'] == 'aidgaf':
|
||||
[responseCode, json_response] = idgaf.parse_idgaf_request(command)
|
||||
json_response['hash'] = security.get_message_hash(json.dumps(command))
|
||||
response_body = json.dumps(json_response)
|
||||
self.handle_response(responseCode, response_body)
|
||||
|
||||
def get_body(self)->bytes:
|
||||
""" This function returns the body of the request.
|
||||
Returns:
|
||||
The body of the request.
|
||||
"""
|
||||
header_length = self.headers.get('Content-Length')
|
||||
request_body = default_request_body
|
||||
if header_length != None and self.headers.get('Content-Length') != None:
|
||||
request_body = self.rfile.read(
|
||||
int(self.headers.get('Content-Length')))
|
||||
str_request = str(request_body, UTF8)
|
||||
print(request_body)
|
||||
return request_body
|
||||
|
||||
|
||||
def handle_response(self, code, body):
|
||||
""" This function handles the response to the client.
|
||||
Parameters:
|
||||
code: The HTTP response code.
|
||||
body: The body of the response. """
|
||||
self.send_response(code)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.end_headers()
|
||||
print("sending:"+body)
|
||||
self.wfile.write(bytes(body, UTF8))
|
||||
|
||||
def perform_sanity_checks(str_request)->bool:
|
||||
""" Performs a hash check on the message, and verifies the timestamp is valid.
|
||||
If either check fails, return False. Otherwise, return True.
|
||||
Parameters:
|
||||
str_request: The request body as a string.
|
||||
Returns:
|
||||
True if the message is valid, False otherwise. """
|
||||
if settings.HASHKEY is not None:
|
||||
hash = security.get_message_hash(str_request)
|
||||
if hash not in str_request:
|
||||
print("Error: hash not match")
|
||||
return False
|
||||
if not security.verify_message_time(str_request):
|
||||
print("Error: timestamp expired")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
""" This function starts the server. """
|
||||
webServer = HTTPServer(
|
||||
(settings.HOSTNAME, settings.SERVERPORT), IDGAFServer)
|
||||
print("Server started http://%s:%s" %
|
||||
(settings.HOSTNAME, settings.SERVERPORT))
|
||||
|
||||
try:
|
||||
webServer.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
webServer.server_close()
|
||||
print("Server stopped.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
""" This function starts the main method. """
|
||||
main()
|
7
src/aidgaf/aidgaf_server/__init__.py
Normal file
7
src/aidgaf/aidgaf_server/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
""" aidgaf-server. """
|
||||
|
||||
# The name of the package
|
||||
name = 'aidgaf_server' # pylint: disable=C0103
|
||||
|
||||
# The version of the package
|
||||
version = '0.1.0' # pylint: disable=C0103
|
5
src/aidgaf/aidgaf_server/__main__.py
Normal file
5
src/aidgaf/aidgaf_server/__main__.py
Normal file
@ -0,0 +1,5 @@
|
||||
""" aidgaf-server entry point. """
|
||||
import server
|
||||
|
||||
# The main entry point for the aidgaf-server package.
|
||||
server.main()
|
10
src/aidgaf/aidgaf_server/const.py
Normal file
10
src/aidgaf/aidgaf_server/const.py
Normal file
@ -0,0 +1,10 @@
|
||||
"""Constants for the aidgaf-server package."""
|
||||
|
||||
UTF8="utf-8"
|
||||
""" The encoding to use for strings. """
|
||||
|
||||
OPENAI_TIMEOUT=30
|
||||
""" The timeout for OpenAI requests. """
|
||||
|
||||
REPORTING_TIMEOUT=10
|
||||
""" The timeout for async reporting requests. """
|
@ -1,6 +1,8 @@
|
||||
""" This module contains the function to calculate the hash of a value and a secret."""
|
||||
import hashlib
|
||||
|
||||
def calculate_hash(value:bytes, secret:bytes)->str:
|
||||
|
||||
def calculate_hash(value: bytes, secret: bytes) -> str:
|
||||
""" This function calculates the hash of a value and a secret.
|
||||
It is used to verify that the message is from the server. The hash
|
||||
is calculated using the SHA512 algorithm. The hash is returned as a
|
||||
@ -13,6 +15,6 @@ def calculate_hash(value:bytes, secret:bytes)->str:
|
||||
returns:
|
||||
The hash of the value and secret. This is a hex string.
|
||||
"""
|
||||
m = hashlib.sha512()
|
||||
m.update(b"".join([value,secret]))
|
||||
return m.hexdigest()
|
||||
sha512 = hashlib.sha512()
|
||||
sha512.update(b"".join([value, secret]))
|
||||
return sha512.hexdigest()
|
@ -1,61 +1,61 @@
|
||||
""" This file contains the logic for the IDGAF server. It can be used to make a stand-alone
|
||||
IDGAF server, or it can be used as a module in a larger application.
|
||||
"""
|
||||
from datetime import datetime
|
||||
import json
|
||||
import random
|
||||
import security
|
||||
import re
|
||||
import requests
|
||||
from time import time
|
||||
from datetime import datetime
|
||||
import settings
|
||||
from const import OPENAI_TIMEOUT
|
||||
|
||||
""" The URL for the OpenAI API. """
|
||||
URL = "https://api.openai.com/v1/completions"
|
||||
""" The URL for the OpenAI API. """
|
||||
|
||||
""" The data to send to OpenAI. """
|
||||
DATA = {"model": settings.OPEN_AI_COMPLETION_MODEL,
|
||||
"prompt": settings.PROMPTS[0],
|
||||
"temperature": settings.TEMPERATURE,
|
||||
"max_tokens": settings.OPEN_AI_MAX_TOKENS
|
||||
}
|
||||
""" The data to send to OpenAI. """
|
||||
|
||||
""" The headers to send to OpenAI. """
|
||||
request_headers = {"Authorization": "Bearer " +
|
||||
settings.APIKEY, "Content-Type": "application/json"}
|
||||
""" The headers to send to OpenAI. """
|
||||
|
||||
def get_response_base_object(text:str) -> dict:
|
||||
|
||||
def get_response_base_object(text: str) -> dict:
|
||||
""" This is used to create the response object for the server.
|
||||
Parameters:
|
||||
text: The text to return to the client.
|
||||
Returns:
|
||||
A dictionary containing the response object.
|
||||
"""
|
||||
resultObject = {}
|
||||
resultObject["message"] = {}
|
||||
resultObject["service"] = "AIDGAF Server"
|
||||
resultObject["message"]["data"] = {}
|
||||
resultObject["message"]["data"]["resultObject"] = text
|
||||
resultObject["timestamp"] = datetime.utcnow().timestamp()
|
||||
return resultObject
|
||||
"""
|
||||
result_object = {}
|
||||
result_object["message"] = {}
|
||||
result_object["service"] = "AIDGAF Server"
|
||||
result_object["message"]["data"] = {}
|
||||
result_object["message"]["data"]["resultObject"] = text
|
||||
result_object["timestamp"] = datetime.utcnow().timestamp()
|
||||
return result_object
|
||||
|
||||
|
||||
def parse_idgaf_request(command)->[int, dict]:
|
||||
def parse_idgaf_request(idgaf_command) -> [int, dict]:
|
||||
""" This function handles the IDGAF command. It will return a response object.
|
||||
Parameters:
|
||||
command: The command object received from the client.
|
||||
Returns:
|
||||
A tuple containing the status code and the response object.
|
||||
"""
|
||||
the_data = get_prompt(command)
|
||||
the_data = get_prompt(idgaf_command)
|
||||
response = get_gpt_response(the_data)
|
||||
try:
|
||||
response_text = response.json()['choices'][0]['text'].strip()
|
||||
except (KeyError):
|
||||
response_text = gpt_response.text
|
||||
except KeyError:
|
||||
response_text = response.text
|
||||
obj = get_response_base_object(response_text)
|
||||
return [response.status_code, obj]
|
||||
|
||||
|
||||
def get_gpt_response(data) -> requests.Response:
|
||||
""" This function communicates with OpenAI and returns a response object.
|
||||
Parameters:
|
||||
@ -63,11 +63,14 @@ def get_gpt_response(data) -> requests.Response:
|
||||
Returns:
|
||||
The response object from OpenAI.
|
||||
"""
|
||||
gpt_response = requests.post(URL, json=data, headers=request_headers)
|
||||
gpt_response = requests.post(
|
||||
url=URL, json=data, headers=request_headers, timeout=OPENAI_TIMEOUT)
|
||||
return gpt_response
|
||||
|
||||
def get_prompt(command)->dict:
|
||||
""" Selects a prompt from the PROMPTS list and replaces the USERNAME placeholder with the username.
|
||||
|
||||
def get_prompt(command) -> dict:
|
||||
""" Selects a prompt from the PROMPTS list and replaces the USERNAME placeholder
|
||||
with the username.
|
||||
Parameters:
|
||||
command: The command object received from the client.
|
||||
Returns:
|
||||
@ -83,9 +86,14 @@ def get_prompt(command)->dict:
|
||||
return the_data
|
||||
|
||||
|
||||
# This function is for testing the IDGAF capabilities without a server.
|
||||
if __name__ == "__main__":
|
||||
""" This function is for testing the IDGAF capabilities without a server. """
|
||||
value = '{"service":"papa","message":{"command":"aidgaf","data":{"username":"AdamOutler"},"timestamp":1675725191},"hash":"1bc73914478835d03f9ebdfb46328321d2bb656647e2876d6f162cc1860607fcfca8d825c48e390a6a254ee0835c8a4fe5f9a25795a3a0880ae5a23e9c132cf2"}'
|
||||
command = json.loads(value)
|
||||
[code, result] = parse_idgaf_request(command)
|
||||
INPUT = '''{"service":"papa","message":
|
||||
{"command":"aidgaf","data":{"username":"AdamOutler"},
|
||||
"timestamp":1675725191},
|
||||
"hash":"1bc73914478835d03f9ebdfb46328321d2bb656647e28
|
||||
76d6f162cc1860607fcfca8d825c48e390a6a254ee0835c8a4fe5f
|
||||
9a25795a3a0880ae5a23e9c132cf2"}'''
|
||||
test_command = json.loads(INPUT)
|
||||
[code, result] = parse_idgaf_request(test_command)
|
||||
print(result)
|
31
src/aidgaf/aidgaf_server/merge.py
Normal file
31
src/aidgaf/aidgaf_server/merge.py
Normal file
@ -0,0 +1,31 @@
|
||||
"""This module contains the merge_dict function."""
|
||||
|
||||
|
||||
def merge_dict_no_overwrite(base_dictionary, other_dictionary, location=None)->dict:
|
||||
""" This function merges two dictionaries. If the same key exists in both dictionaries,
|
||||
the value from the other_dictionary will be used. This function will recurse into nested
|
||||
dictionaries. If the same key exists in both dictionaries, and the value is a dictionary,
|
||||
the function will recurse into the nested dictionary. If the same key exists in both
|
||||
dictionaries, and the value is not a dictionary, the value from the base_dictionary will
|
||||
be used.
|
||||
|
||||
Parameters:
|
||||
base_dictionary: The dictionary to merge the other_dictionary into.
|
||||
other_dictionary: The dictionary to merge keys from. if the same key exists in both
|
||||
dictionaries, the value from the base_dictionary will be used.
|
||||
location: leave blank. This is used to track the location of the key in the dictionary.
|
||||
Returns:
|
||||
The merged dictionary.
|
||||
|
||||
"""
|
||||
if location is None:
|
||||
location=[]
|
||||
for key in other_dictionary:
|
||||
if key in base_dictionary:
|
||||
if isinstance(base_dictionary[key], dict) and isinstance(other_dictionary[key], dict):
|
||||
merge_dict_no_overwrite(base_dictionary[key], other_dictionary[key],[str(key)])
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
base_dictionary[key] = other_dictionary[key]
|
||||
return base_dictionary
|
@ -13,9 +13,9 @@ def perform_hash_checks(str_request)->bool:
|
||||
str_request: The request body, as a string.
|
||||
Returns:
|
||||
True if the message is valid, False otherwise."""
|
||||
hash = get_message_hash(str_request)
|
||||
my_hash = get_message_hash(str_request)
|
||||
|
||||
if hash not in str_request:
|
||||
if my_hash not in str_request:
|
||||
print("Error: hash not match")
|
||||
return False
|
||||
if not verify_message_time(str_request):
|
||||
@ -30,14 +30,14 @@ def get_message_hash(json_command) -> str:
|
||||
json_command: The JSON command to hash.
|
||||
Returns:
|
||||
The hash of the message, as a string. """
|
||||
|
||||
|
||||
strip1 = re.sub(".*\"message\":", "", json_command, 1)
|
||||
if ("\"hash\":" in strip1):
|
||||
if "\"hash\":" in strip1:
|
||||
strip2 = re.sub(',\"hash\":.*', '', strip1)
|
||||
else:
|
||||
strip2 = strip1[:-1]
|
||||
json_value = bytes(strip2, UTF8)
|
||||
if (settings.HASHKEY is not None):
|
||||
if settings.HASHKEY is not None:
|
||||
hash_value = hash_calculator.calculate_hash(
|
||||
json_value, settings.HASHKEY)
|
||||
return hash_value
|
169
src/aidgaf/aidgaf_server/server.py
Normal file
169
src/aidgaf/aidgaf_server/server.py
Normal file
@ -0,0 +1,169 @@
|
||||
""" aidgaf-server - A simple server to handle requests from the aidgaf client.
|
||||
This server will communicate with OpenAI to generate responses to the client."""
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
import json
|
||||
import threading
|
||||
import requests
|
||||
|
||||
import merge
|
||||
import idgaf
|
||||
import settings
|
||||
import security
|
||||
from const import UTF8, REPORTING_TIMEOUT
|
||||
|
||||
default_request_body = b'{"message":{"command":"aidgaf","data":{"username":"AdamOutler"}}}'
|
||||
request_headers = {}
|
||||
|
||||
class IDGAFServer(BaseHTTPRequestHandler):
|
||||
""" This class handles the requests from the client. """
|
||||
|
||||
def do_GET(self):
|
||||
""" This function handles GET requests. """
|
||||
self.send_response(418)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.end_headers()
|
||||
self.wfile.write(bytes("HTTP 408\nI'm a teapot", UTF8))
|
||||
self.close_connection
|
||||
|
||||
def do_PATCH(self):
|
||||
""" This function handles PATCH requests. """
|
||||
body = self.get_body().decode(UTF8)
|
||||
check_result=perform_sanity_checks(body)
|
||||
if check_result:
|
||||
self.send_response(403)
|
||||
self.end_headers()
|
||||
self.wfile.write(bytes(check_result, UTF8))
|
||||
self.close_connection
|
||||
return
|
||||
command = json.loads(body)
|
||||
self.do_request_handling(command)
|
||||
|
||||
def do_request_handling(self, command):
|
||||
""" This function handles the request.
|
||||
Parameters:
|
||||
command: The command object received from the client. """
|
||||
print(command)
|
||||
if command['message']['command'] == 'aidgaf':
|
||||
self.idgaf_command_handler(command)
|
||||
|
||||
def idgaf_command_handler(self, command):
|
||||
""" This function handles the idgaf command. It will generate a
|
||||
response and send it to the client.
|
||||
Parameters:
|
||||
command: The command object received from the client. """
|
||||
if not settings.ASYNC_URL:
|
||||
[code,body]=self.getGPTResponse(command)
|
||||
self.handle_response(code,body)
|
||||
return
|
||||
|
||||
thread = threading.Thread(target=self.send_async_request, args=(command,))
|
||||
thread.start()
|
||||
self.handle_response(200,json.dumps(command))
|
||||
|
||||
def send_async_request(self,command):
|
||||
""" This function sends the request to the async URL. It will generate a
|
||||
response and send it to the client. This function is called in a separate
|
||||
thread. It will not block the main thread.
|
||||
|
||||
Parameters:
|
||||
command: The command object received from the client. """
|
||||
[code,body] = self.getGPTResponse(command)
|
||||
merged=merge.merge_dict_no_overwrite(json.loads(body),command)
|
||||
merged['hash']=security.get_message_hash(json.dumps(merged))
|
||||
merged['service']='JavaShark'
|
||||
data=json.dumps(merged)
|
||||
print(str(code)+": "+data)
|
||||
|
||||
if (code != 200):
|
||||
return
|
||||
if (settings.ASYNC_METHOD == "POST"):
|
||||
requests.post(settings.ASYNC_URL, data=data, headers=request_headers,
|
||||
timeout=REPORTING_TIMEOUT)
|
||||
elif (settings.ASYNC_METHOD == "PUT"):
|
||||
requests.put(settings.ASYNC_URL, data=data, headers=request_headers,
|
||||
timeout=REPORTING_TIMEOUT)
|
||||
elif (settings.ASYNC_METHOD == "PATCH"):
|
||||
resp=requests.patch(settings.ASYNC_URL, data=data, headers=request_headers,
|
||||
timeout=REPORTING_TIMEOUT)
|
||||
print(str(resp)+resp.text)
|
||||
|
||||
|
||||
|
||||
# gpt_response = requests.post(URL, json=data, headers=request_headers)
|
||||
|
||||
def getGPTResponse(self, command) -> [int, str]:
|
||||
""" This function generates a response using OpenAI. It will return
|
||||
the response code and the response body.
|
||||
Parameters:
|
||||
command: The command object received from the client.
|
||||
Returns:
|
||||
The response code and the response body. """
|
||||
[responseCode, json_response] = idgaf.parse_idgaf_request(command)
|
||||
json_response['hash'] = security.get_message_hash(json.dumps(command))
|
||||
response_body = json.dumps(json_response)
|
||||
return [responseCode, response_body]
|
||||
|
||||
def get_body(self) -> bytes:
|
||||
""" This function returns the body of the request.
|
||||
Returns:
|
||||
The body of the request.
|
||||
"""
|
||||
header_length = self.headers.get('Content-Length')
|
||||
request_body = default_request_body
|
||||
if header_length != None and self.headers.get('Content-Length') != None:
|
||||
request_body = self.rfile.read(
|
||||
int(self.headers.get('Content-Length')))
|
||||
str_request = str(request_body, UTF8)
|
||||
print(request_body)
|
||||
return request_body
|
||||
|
||||
def handle_response(self, code, body):
|
||||
""" This function handles the response to the client.
|
||||
Parameters:
|
||||
code: The HTTP response code.
|
||||
body: The body of the response. """
|
||||
self.send_response(code)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.end_headers()
|
||||
print("sending:"+body)
|
||||
self.wfile.write(bytes(body, UTF8))
|
||||
self.close_connection
|
||||
|
||||
|
||||
def perform_sanity_checks(str_request) -> str:
|
||||
""" Performs a hash check on the message, and verifies the timestamp is valid.
|
||||
If either check fails, return False. Otherwise, return True.
|
||||
Parameters:
|
||||
str_request: The request body as a string.
|
||||
Returns:
|
||||
True if the message is valid, False otherwise. """
|
||||
if settings.HASHKEY is not None:
|
||||
hash = security.get_message_hash(str_request)
|
||||
if settings.HASHKEY and hash not in str_request:
|
||||
print("Error: hash not match")
|
||||
return "Error: hash not match"
|
||||
if settings.HASHKEY and not security.verify_message_time(str_request):
|
||||
print("Error: timestamp expired")
|
||||
return "Error: timestamp expired"
|
||||
return ""
|
||||
|
||||
|
||||
def main():
|
||||
""" This function starts the server. """
|
||||
webServer = HTTPServer(
|
||||
(settings.HOSTNAME, settings.SERVERPORT), IDGAFServer)
|
||||
print("Server started http://%s:%s" %
|
||||
(settings.HOSTNAME, settings.SERVERPORT))
|
||||
|
||||
try:
|
||||
webServer.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
webServer.server_close()
|
||||
print("Server stopped.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
""" This function starts the main method. """
|
||||
main()
|
@ -6,21 +6,29 @@ from const import UTF8
|
||||
""" The hostname of the server. """
|
||||
HOSTNAME: str = os.getenv('HOSTNAME') # localhost or some name
|
||||
|
||||
""" The port to broadcast the server """
|
||||
# 8087 or the port you want to run on. pass in with docker -e command.
|
||||
SERVERPORT: int = 8087
|
||||
|
||||
""" The API key for OpenAI"""
|
||||
APIKEY: str = os.getenv('APIKEY') # secret key from OpenAPI website
|
||||
if APIKEY is None:
|
||||
raise Exception("APIKEY Environmental Variable must be set")
|
||||
""" The port to broadcast the server """
|
||||
|
||||
"""The URL to send async requests to"""
|
||||
ASYNC_URL: str=os.getenv('ASYNC_URL')
|
||||
|
||||
""" The method to use for async requests. """
|
||||
ASYNC_METHOD: str=os.getenv('ASYNC_METHOD')
|
||||
|
||||
|
||||
"""8087 or the port you want to run on. pass in with docker -e command."""
|
||||
SERVERPORT: int = 8087
|
||||
|
||||
|
||||
""" The prompts used for OpenAI. When the server receives a request, it will
|
||||
randomly select one of these prompts to use."""
|
||||
PROMPTS = [
|
||||
"Say \"USERNAME does not give a fuck\" as a haiku and mention that it is a haiku.",
|
||||
"Say \"USERNAME does not give a fuck\" in a Dr Suess poem.",
|
||||
"Tell me a story about how \"USERNAME does not give a fuck\" using an outrageous situation where someone should care but they do not and thats fine.",
|
||||
"Tell me a funny, impossible, story about USERNAME. Make USERNAME seem relatable at the end. Make up an outrageous situation where the moral of the story is: \"USERNAME does not give a fuck\" to this very day."
|
||||
"Say \"USERNAME is completely apethetic and does not give a fuck\" in a verbose manner, using your most colorful words and one metaphor."
|
||||
]
|
||||
|
||||
@ -34,7 +42,8 @@ OPEN_AI_COMPLETION_MODEL = "text-davinci-003"
|
||||
TEMPERATURE = 0.7
|
||||
|
||||
""" The hash key for the server. Leave this blank if you don't want to use it. """
|
||||
HASHKEY = bytes(os.getenv('HASHKEY'),
|
||||
UTF8) # shared secret for hmac of message
|
||||
HASHKEY = bytes(os.getenv('HASHKEY') or "",UTF8) # shared secret for hmac of message
|
||||
if (HASHKEY == ""):
|
||||
HASHKEY=None
|
||||
""" The maximum age of a message in seconds. Only used if HASHKEY is set."""
|
||||
MAX_MESSAGE_AGE = 600
|
Loading…
x
Reference in New Issue
Block a user