Misc refactoring

This commit is contained in:
adamoutler 2023-02-11 20:21:30 +00:00
parent 5f2abddd89
commit 6d5e90d278
7 changed files with 184 additions and 81 deletions

View File

@ -12,7 +12,8 @@
"vscode": {
"extensions": [
"pomdtr.secrets",
"ms-python.python"
"ms-python.python",
"donjayamanne.python-extension-pack"
]
}
}

33
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,33 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Start Server",
"type": "python",
"request": "launch",
"program": "src/aidgaf/aidgaf-server/server.py",
"console": "integratedTerminal",
"justMyCode": true
},
{
"name": "IDGAF",
"type": "python",
"request": "launch",
"program": "src/aidgaf/aidgaf-server/idgaf.py",
"console": "integratedTerminal",
"justMyCode": true
},
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true
}
]
}

View File

@ -0,0 +1 @@
UTF8="utf-8"

View File

@ -1,23 +1,21 @@
import json
import random
import security
import re
import requests
from http.server import BaseHTTPRequestHandler, HTTPServer
from time import time
from datetime import datetime
import openai
import random
import settings
import hash_calculator
openai.organization = "org-hNNV1yHjZp7T3pn5pdZWaKLm"
# print(openai.Model.list())
URL = "https://api.openai.com/v1/completions"
DATA = {"model": settings.OPEN_AI_COMPLETION_MODEL,
"prompt": settings.PROMPTS[0],
"temperature": 0.90,
"temperature": settings.TEMPERATURE,
"max_tokens": settings.OPEN_AI_MAX_TOKENS
}
@ -25,35 +23,6 @@ request_headers = {"Authorization": "Bearer " +
settings.APIKEY, "Content-Type": "application/json"}
class IDGAFServer(BaseHTTPRequestHandler):
def do_PATCH(self):
# print("Request: "+self.request+ " "+webServer.get_request())
request_body = self.rfile.read(int(self.headers.get('Content-Length')))
str_request=str(request_body,'utf-8')
print(request_body)
if settings.HASHKEY is not None and get_message_hash(str_request) not in str_request:
print("Error: hash not match")
self.send_response(403)
return
if settings.HASHKEY is not None and not verify_message_time(str_request):
print("Error: timestamp expired")
self.send_response(403)
return
command = json.loads(request_body)
print(command)
if command['message']['command'] == 'aidgaf':
[responseCode, response_body] = parse_idgaf_request(command)
self.handle_response(responseCode, response_body)
print("sending:"+response_body)
def handle_response(self, code, body):
self.send_response(code)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes(body, "UTF-8"))
def get_response_base_object(text):
resultObject = {}
@ -64,20 +33,19 @@ def get_response_base_object(text):
resultObject["timestamp"] = datetime.utcnow().timestamp()
return resultObject
def parse_idgaf_request(command):
the_data = get_prompt(command)
gpt_response = requests.post(URL, json=the_data, headers=request_headers)
print(gpt_response)
try:
response_text = gpt_response.json()['choices'][0]['text'].strip()
response=get_gpt_response(the_data)
try:
response_text = response.json()['choices'][0]['text'].strip()
except (KeyError):
response_text=gpt_response.text
response_text = gpt_response.text
obj = get_response_base_object(response_text)
obj['hash']=get_message_hash(json.dumps(obj))
json_result = json.dumps(obj)
return [gpt_response.status_code, json_result]
return [response.status_code, obj]
def get_gpt_response(data):
gpt_response = requests.post(URL, json=data, headers=request_headers)
return gpt_response
def get_prompt(command):
@ -93,41 +61,27 @@ def get_prompt(command):
def get_message_hash(json_command) -> bytes:
"""Get the object named "message", and run a hash over it. """
strip1 = re.sub('.*\"message\":', "", json_command, 1)
strip2 = re.sub(',\"hash\":.*', '', strip1)
json_value = bytes(strip2, "utf-8")
if (settings.HASHKEY is not None):
hash_value = hash_calculator.calculate_hash(json_value, settings.HASHKEY)
return hash_value
return ""
def get_prompt(command):
my_prompt = random.choice(settings.PROMPTS)
my_prompt = my_prompt.replace(
"USERNAME", command['message']['data']['username'])
def verify_message_time(json_command) -> bool:
"""Check message expiration is less than current time + time in settings.
Before we accept the JSON as valid, and parse it, we must check the timestamp.
The timestamp is a Linux Timestamp. So convert it, add maximum message age, and
then verify current time is less than expiration time.
"""
strip_json = re.sub('.*\"timestamp\":', "", json_command, 1)
expiration = int(re.sub('}.*', '', strip_json))+settings.MAX_MESSAGE_AGE
current_time = int(time())
return not current_time > expiration
print("Prompt selected: "+my_prompt)
the_data = DATA
the_data["prompt"] = my_prompt
return the_data
value = '{"service":"papa","message":{"command":"aidgaf","data":{"username":"AdamOutler"},"timestamp":1675725191},"hash":"1bc73914478835d03f9ebdfb46328321d2bb656647e2876d6f162cc1860607fcfca8d825c48e390a6a254ee0835c8a4fe5f9a25795a3a0880ae5a23e9c132cf2"}'
if __name__ == "__main__":
if get_message_hash(value) not in value:
print("Error: hash not match")
if not verify_message_time(value):
print("Error: timestamp expired")
command = json.loads(value)
[code, result] = parse_idgaf_request(command)
print(result)
# curl https://api.openai.com/v1/completions \
# -H "Content-Type: application/json" \
# -H "Authorization: Bearer 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" \

View File

@ -0,0 +1,45 @@
import re
import time
import hash_calculator
import settings
from const import UTF8
def perform_hash_checks(str_request):
hash = get_message_hash(str_request)
if hash not in str_request:
print("Error: hash not match")
return False
if not verify_message_time(str_request):
print("Error: timestamp expired")
return False
return True
def get_message_hash(json_command) -> str:
"""Get the object named "message", and run a hash over it. """
strip1 = re.sub(".*\"message\":", "", json_command, 1)
if ("\"hash\":" in strip1):
strip2 = re.sub(',\"hash\":.*', '', strip1)
else:
strip2 = strip1[:-1]
json_value = bytes(strip2, UTF8)
if (settings.HASHKEY is not None):
hash_value = hash_calculator.calculate_hash(
json_value, settings.HASHKEY)
return hash_value
return ""
def verify_message_time(json_command) -> bool:
"""Check message expiration is less than current time + time in settings.
Before we accept the JSON as valid, and parse it, we must check the timestamp.
The timestamp is a Linux Timestamp. So convert it, add maximum message age, and
then verify current time is less than expiration time.
"""
strip_json = re.sub('.*\"timestamp\":', "", json_command, 1)
expiration = int(re.sub('}.*', '', strip_json))+settings.MAX_MESSAGE_AGE
current_time = int(time.time())
return not current_time > expiration

View File

@ -1,12 +1,77 @@
import json
import random
from http.server import BaseHTTPRequestHandler, HTTPServer
import idgaf
from idgaf import IDGAFServer
from http.server import HTTPServer
import settings
import security
from const import UTF8
default_request_body = b'{"message":{"command":"aidgaf","data":{"username":"AdamOutler"}}}'
class IDGAFServer(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(418)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes("", UTF8))
def do_PATCH(self):
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):
print(command)
if command['message']['command'] == 'aidgaf':
[responseCode, json_response] = idgaf.parse_idgaf_request(command)
json_response['hash'] = security.get_message_hash(json.dumps(response_body))
response_body = json.dumps(json_response)
self.handle_response(responseCode, response_body)
def get_body(self):
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):
self.send_response(code)
self.send_header("Content-type", "text/html")
self.end_headers()
print("sending:"+response_body)
self.wfile.write(bytes(body, UTF8))
def perform_sanity_checks(str_request):
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():
webServer = HTTPServer((settings.HOSTNAME, settings.SERVERPORT), idgaf.IDGAFServer)
print("Server started http://%s:%s" % (settings.HOSTNAME, settings.SERVERPORT))
webServer = HTTPServer(
(settings.HOSTNAME, settings.SERVERPORT), IDGAFServer)
print("Server started http://%s:%s" %
(settings.HOSTNAME, settings.SERVERPORT))
try:
webServer.serve_forever()
@ -16,5 +81,6 @@ def main():
webServer.server_close()
print("Server stopped.")
if __name__ == "__main__":
main()
main()

View File

@ -1,4 +1,5 @@
import os
from const import UTF8
# The hostname used by this app
HOSTNAME: str = os.getenv('HOSTNAME') # localhost or some name
# The port to broadcast the server
@ -9,14 +10,16 @@ APIKEY: str = os.getenv('APIKEY') # secret key from OpenAPI website
if APIKEY is None:
raise Exception("APIKEY Environmental Variable must be set")
# The hash key
HASHKEY: str = None
hashKey = os.getenv('HASHKEY') # shared secret for hmac of message
if (hashKey is not None and hashKey.replace(" ", "") != ""):
HASKHEY = bytes(hashKey, "utf-8")
HASHKEY = bytes(os.getenv('HASHKEY'),UTF8) # shared secret for hmac of message
# The prompts used for OpenAI.
PROMPTS = ["Say \"USERNAME does not give a fuck\" in a thoughtful and clever paragraph of 5 sentences.",
"Say \"USERNAME does not give a fuck\" in a Dr Suess poem.",
"Tell me all about how much \"USERNAME does not give a fuck\" using your most colorful words."]
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.",
"Say \"USERNAME is completely apethetic and does not give a fuck\" in a verbose manner, using your most colorful words and one metaphor."
]
OPEN_AI_MAX_TOKENS = 500
OPEN_AI_COMPLETION_MODEL = "text-davinci-003"
MAX_MESSAGE_AGE = 600
TEMPERATURE = 0.8