Compare commits

...

4 Commits

Author SHA1 Message Date
adamoutler
e3e20a7b07 Refactoring and linting 2023-02-15 03:26:12 +00:00
adamoutler
2752702d17 add async capabilities to server 2023-02-13 23:33:25 +00:00
adamoutler
a6469184fb Add script for merging dictionaries 2023-02-13 23:33:02 +00:00
adamoutler
4b8e4f9846 Update prompts 2023-02-13 23:32:04 +00:00
19 changed files with 318 additions and 207 deletions

View File

@ -13,10 +13,9 @@
"extensions": [ "extensions": [
"pomdtr.secrets", "pomdtr.secrets",
"ms-python.python", "ms-python.python",
"donjayamanne.python-extension-pack",
"ivory-lab.jenkinsfile-support",
"njpwerner.autodocstring", "njpwerner.autodocstring",
"KevinRose.vsc-python-indent" "NicolasVuillamy.vscode-groovy-lint",
"ms-python.pylint"
] ]
} }
} }

View File

@ -1,5 +1,6 @@
{ {
"recommendations": [ "recommendations": [
"pomdtr.secrets" "pomdtr.secrets",
"nicolasvuillamy.vscode-groovy-lint"
] ]
} }

4
.vscode/launch.json vendored
View File

@ -8,7 +8,7 @@
"name": "Start Server", "name": "Start Server",
"type": "python", "type": "python",
"request": "launch", "request": "launch",
"program": "src/aidgaf/aidgaf-server/server.py", "program": "src/aidgaf/aidgaf_server/server.py",
"console": "integratedTerminal", "console": "integratedTerminal",
"justMyCode": true "justMyCode": true
}, },
@ -16,7 +16,7 @@
"name": "IDGAF", "name": "IDGAF",
"type": "python", "type": "python",
"request": "launch", "request": "launch",
"program": "src/aidgaf/aidgaf-server/idgaf.py", "program": "src/aidgaf/aidgaf_server/idgaf.py",
"console": "integratedTerminal", "console": "integratedTerminal",
"justMyCode": true "justMyCode": true
}, },

View File

@ -1,5 +1,10 @@
{ {
"secrets.enabledFolders": [ "secrets.enabledFolders": [
"aidgaf" "aidgaf"
] ],
"files.associations": {
"[Jj]enkinsfile*": "groovy"
},
"python.linting.pylintPath": "/usr/local/python/current/bin/python"
} }

View File

@ -17,6 +17,6 @@ FROM alpine:latest
RUN apk add python3 py3-pip \ RUN apk add python3 py3-pip \
&& pip3 install openai\ && pip3 install openai\
&& mkdir /app && mkdir /app
COPY src/aidgaf /app COPY src/aidgaf /app/aidgaf
EXPOSE 8087 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
View File

@ -1,4 +1,5 @@
#! /bin/groovy #!/bin/groovy
/* groovylint-disable CompileStatic, DuplicateStringLiteral, LineLength */
pipeline { pipeline {
agent { agent {
docker { docker {
@ -9,18 +10,14 @@ pipeline {
} }
} }
stages { stages {
stage('Prepare Environment'){ stage('Prepare Environment') {
steps{ steps {
sh "#!/bin/sh \n" + sh '#!/bin/sh \n' +
'id; apk add docker openrc git' 'id; apk add docker openrc git'
} }
} }
stage('Obtain Source'){ stage('Obtain Source') {
steps { steps {
git branch: 'main', url: 'https://git.adamoutler.com/aoutler/aidgaf-server.git' git branch: 'main', url: 'https://git.adamoutler.com/aoutler/aidgaf-server.git'
} }
@ -28,42 +25,35 @@ pipeline {
stage('Build in docker') { stage('Build in docker') {
steps { steps {
// Get some code from a Git repository // Get some code from a Git repository
sh "#!/bin/sh \n" + sh '#!/bin/sh \n' +
'docker build -t aidgaf .' 'docker build -t aidgaf .'
} }
} }
stage ("setup credentials"){ stage('setup credentials') {
steps{ steps {
withCredentials([ sshUserPrivateKey(credentialsId: 'dockeruserOn192.168.1.115', keyFileVariable: 'sshkey', usernameVariable: 'user')]) { 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' '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 { 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' 'set +e; docker stop aidgaf-server||echo machine stopped; docker rm aidgaf-server||echo machine does not exist; set -e'
withCredentials([ withCredentials([
string(credentialsId: 'OpenAI-API-Token', variable: 'OPEN_AI_TOKEN'), string(credentialsId: 'OpenAI-API-Token', variable: 'OPEN_AI_TOKEN'),
string(credentialsId: 'PapaHashingSecret', variable: 'PAPA_HASH'), 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" + sh '#!/bin/sh \n' +
'mkdir -p ~/.ssh; cp "${sshkey}" ~/.ssh/id_rsa' 'mkdir -p ~/.ssh; cp "$sshkey" ~/.ssh/id_rsa'
sh "#!/bin/sh \n" + 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' /* 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"
} }
} }

View File

@ -1,7 +0,0 @@
""" aidgaf-server. """
""" The name of the package"""
name = 'aidgaf'
""" The version of the package"""
version='0.1.0'

View File

@ -1,5 +0,0 @@
""" aidgaf-server entry point. """
import server
""" The main entry point for the aidgaf-server package."""
server.main()

View File

@ -1,4 +0,0 @@
"""Constants for the aidgaf-server package."""
""" The encoding to use for strings. """
UTF8="utf-8"

View File

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

View 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

View File

@ -0,0 +1,5 @@
""" aidgaf-server entry point. """
import server
# The main entry point for the aidgaf-server package.
server.main()

View 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. """

View File

@ -1,6 +1,8 @@
""" This module contains the function to calculate the hash of a value and a secret."""
import hashlib 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. """ 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 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 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: returns:
The hash of the value and secret. This is a hex string. The hash of the value and secret. This is a hex string.
""" """
m = hashlib.sha512() sha512 = hashlib.sha512()
m.update(b"".join([value,secret])) sha512.update(b"".join([value, secret]))
return m.hexdigest() return sha512.hexdigest()

View File

@ -1,61 +1,61 @@
""" This file contains the logic for the IDGAF server. It can be used to make a stand-alone """ 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. IDGAF server, or it can be used as a module in a larger application.
""" """
from datetime import datetime
import json import json
import random import random
import security
import re
import requests import requests
from time import time
from datetime import datetime
import settings import settings
from const import OPENAI_TIMEOUT
""" The URL for the OpenAI API. """
URL = "https://api.openai.com/v1/completions" 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, DATA = {"model": settings.OPEN_AI_COMPLETION_MODEL,
"prompt": settings.PROMPTS[0], "prompt": settings.PROMPTS[0],
"temperature": settings.TEMPERATURE, "temperature": settings.TEMPERATURE,
"max_tokens": settings.OPEN_AI_MAX_TOKENS "max_tokens": settings.OPEN_AI_MAX_TOKENS
} }
""" The data to send to OpenAI. """
""" The headers to send to OpenAI. """
request_headers = {"Authorization": "Bearer " + request_headers = {"Authorization": "Bearer " +
settings.APIKEY, "Content-Type": "application/json"} 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. """ This is used to create the response object for the server.
Parameters: Parameters:
text: The text to return to the client. text: The text to return to the client.
Returns: Returns:
A dictionary containing the response object. A dictionary containing the response object.
""" """
resultObject = {} result_object = {}
resultObject["message"] = {} result_object["message"] = {}
resultObject["service"] = "AIDGAF Server" result_object["service"] = "AIDGAF Server"
resultObject["message"]["data"] = {} result_object["message"]["data"] = {}
resultObject["message"]["data"]["resultObject"] = text result_object["message"]["data"]["resultObject"] = text
resultObject["timestamp"] = datetime.utcnow().timestamp() result_object["timestamp"] = datetime.utcnow().timestamp()
return resultObject 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. """ This function handles the IDGAF command. It will return a response object.
Parameters: Parameters:
command: The command object received from the client. command: The command object received from the client.
Returns: Returns:
A tuple containing the status code and the response object. 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) response = get_gpt_response(the_data)
try: try:
response_text = response.json()['choices'][0]['text'].strip() response_text = response.json()['choices'][0]['text'].strip()
except (KeyError): except KeyError:
response_text = gpt_response.text response_text = response.text
obj = get_response_base_object(response_text) obj = get_response_base_object(response_text)
return [response.status_code, obj] return [response.status_code, obj]
def get_gpt_response(data) -> requests.Response: def get_gpt_response(data) -> requests.Response:
""" This function communicates with OpenAI and returns a response object. """ This function communicates with OpenAI and returns a response object.
Parameters: Parameters:
@ -63,11 +63,14 @@ def get_gpt_response(data) -> requests.Response:
Returns: Returns:
The response object from OpenAI. 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 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: Parameters:
command: The command object received from the client. command: The command object received from the client.
Returns: Returns:
@ -83,9 +86,14 @@ def get_prompt(command)->dict:
return the_data return the_data
# This function is for testing the IDGAF capabilities without a server.
if __name__ == "__main__": if __name__ == "__main__":
""" This function is for testing the IDGAF capabilities without a server. """ INPUT = '''{"service":"papa","message":
value = '{"service":"papa","message":{"command":"aidgaf","data":{"username":"AdamOutler"},"timestamp":1675725191},"hash":"1bc73914478835d03f9ebdfb46328321d2bb656647e2876d6f162cc1860607fcfca8d825c48e390a6a254ee0835c8a4fe5f9a25795a3a0880ae5a23e9c132cf2"}' {"command":"aidgaf","data":{"username":"AdamOutler"},
command = json.loads(value) "timestamp":1675725191},
[code, result] = parse_idgaf_request(command) "hash":"1bc73914478835d03f9ebdfb46328321d2bb656647e28
76d6f162cc1860607fcfca8d825c48e390a6a254ee0835c8a4fe5f
9a25795a3a0880ae5a23e9c132cf2"}'''
test_command = json.loads(INPUT)
[code, result] = parse_idgaf_request(test_command)
print(result) print(result)

View 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

View File

@ -13,9 +13,9 @@ def perform_hash_checks(str_request)->bool:
str_request: The request body, as a string. str_request: The request body, as a string.
Returns: Returns:
True if the message is valid, False otherwise.""" 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") print("Error: hash not match")
return False return False
if not verify_message_time(str_request): 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. json_command: The JSON command to hash.
Returns: Returns:
The hash of the message, as a string. """ The hash of the message, as a string. """
strip1 = re.sub(".*\"message\":", "", json_command, 1) strip1 = re.sub(".*\"message\":", "", json_command, 1)
if ("\"hash\":" in strip1): if "\"hash\":" in strip1:
strip2 = re.sub(',\"hash\":.*', '', strip1) strip2 = re.sub(',\"hash\":.*', '', strip1)
else: else:
strip2 = strip1[:-1] strip2 = strip1[:-1]
json_value = bytes(strip2, UTF8) json_value = bytes(strip2, UTF8)
if (settings.HASHKEY is not None): if settings.HASHKEY is not None:
hash_value = hash_calculator.calculate_hash( hash_value = hash_calculator.calculate_hash(
json_value, settings.HASHKEY) json_value, settings.HASHKEY)
return hash_value return hash_value

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

View File

@ -6,21 +6,29 @@ from const import UTF8
""" The hostname of the server. """ """ The hostname of the server. """
HOSTNAME: str = os.getenv('HOSTNAME') # localhost or some name 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""" """ The API key for OpenAI"""
APIKEY: str = os.getenv('APIKEY') # secret key from OpenAPI website APIKEY: str = os.getenv('APIKEY') # secret key from OpenAPI website
if APIKEY is None: if APIKEY is None:
raise Exception("APIKEY Environmental Variable must be set") 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 """ The prompts used for OpenAI. When the server receives a request, it will
randomly select one of these prompts to use.""" randomly select one of these prompts to use."""
PROMPTS = [ 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\" as a haiku and mention that it is a haiku.",
"Say \"USERNAME does not give a fuck\" in a Dr Suess poem.", "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." "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 TEMPERATURE = 0.7
""" The hash key for the server. Leave this blank if you don't want to use it. """ """ The hash key for the server. Leave this blank if you don't want to use it. """
HASHKEY = bytes(os.getenv('HASHKEY'), HASHKEY = bytes(os.getenv('HASHKEY') or "",UTF8) # shared secret for hmac of message
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.""" """ The maximum age of a message in seconds. Only used if HASHKEY is set."""
MAX_MESSAGE_AGE = 600 MAX_MESSAGE_AGE = 600