Skip to content

Commit

Permalink
added override extension
Browse files Browse the repository at this point in the history
  • Loading branch information
hunterirving committed Sep 2, 2024
1 parent 82ccc13 commit 3836ee5
Show file tree
Hide file tree
Showing 9 changed files with 306 additions and 162 deletions.
148 changes: 72 additions & 76 deletions extensions/chatgpt/chatgpt.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from flask import request, render_template_string
from openai import OpenAI
import extensions.config as config
from html_utils import transcode_html

# Initialize the OpenAI client with your API key
client = OpenAI(api_key=config.open_ai_api_key)
Expand All @@ -13,97 +12,94 @@
previous_model = selected_model

system_prompts = [
{"role": "system", "content": "Please provide your response in plain text using only ASCII characters. "
"Never use any special or esoteric characters that might not be supported by older systems. "},
{"role": "system", "content": "Your responses will be presented to the user within "
"the body of an html document. Be aware that any html tags you respond with will be interpreted and rendered as html. "
"Therefore, when discussing an html tag, do not wrap it in <>, as it will be rendered as html. Instead, wrap the name "
"of the tag in <b> tags to emphasize it, for example \"the <b>a</b> tag\". "
"You do not need to provide a <body> tag. "
"When responding with a list, ALWAYS format it using <ol> or <ul> with individual list items wrapped in <li> tags. "
"When responding with a link, the <a> tag."},
{"role": "system", "content": "When responding with code or other formatted text (including prose or poetry), always insert "
"<pre></pre> tags with <code></code> tags nested inside (which contain the formatted content)."
"If the user asks you to respond 'in a code block', this is what they mean. NEVER use three backticks "
"(```like so``` (markdown style)) when discussing code. If you need to highlight a variable name or text of similar (short) length, "
"wrap it in <code> tags (without the aforementioned <pre> tags). Do not forget to close html tags where appropriate. "
"When using a code block, ensure that individual lines of text do not exceed 60 characters."},
{"role": "system", "content": "NEVER use **this format** (markdown style) to bold text - instead, wrap text in <b> tags or <i> "
"tags (when appropriate) to emphasize it."},
{"role": "system", "content": "Please provide your response in plain text using only ASCII characters. "
"Never use any special or esoteric characters that might not be supported by older systems. "},
{"role": "system", "content": "Your responses will be presented to the user within "
"the body of an html document. Be aware that any html tags you respond with will be interpreted and rendered as html. "
"Therefore, when discussing an html tag, do not wrap it in <>, as it will be rendered as html. Instead, wrap the name "
"of the tag in <b> tags to emphasize it, for example \"the <b>a</b> tag\". "
"You do not need to provide a <body> tag. "
"When responding with a list, ALWAYS format it using <ol> or <ul> with individual list items wrapped in <li> tags. "
"When responding with a link, the <a> tag."},
{"role": "system", "content": "When responding with code or other formatted text (including prose or poetry), always insert "
"<pre></pre> tags with <code></code> tags nested inside (which contain the formatted content)."
"If the user asks you to respond 'in a code block', this is what they mean. NEVER use three backticks "
"(```like so``` (markdown style)) when discussing code. If you need to highlight a variable name or text of similar (short) length, "
"wrap it in <code> tags (without the aforementioned <pre> tags). Do not forget to close html tags where appropriate. "
"When using a code block, ensure that individual lines of text do not exceed 60 characters."},
{"role": "system", "content": "NEVER use **this format** (markdown style) to bold text - instead, wrap text in <b> tags or <i> "
"tags (when appropriate) to emphasize it."},
]

HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ChatGPT</title>
<meta charset="UTF-8">
<title>ChatGPT</title>
</head>
<body>
<form method="post" action="/">
<input type="text" size="49" name="command" required autocomplete="off">
<input type="submit" value="Submit">
<select id="model" name="model">
<option value="gpt-4o" {{ 'selected' if selected_model == 'gpt-4o' else '' }}>GPT-4o</option>
<option value="gpt-4-turbo" {{ 'selected' if selected_model == 'gpt-4-turbo' else '' }}>GPT-4</option>
<option value="gpt-3.5-turbo" {{ 'selected' if selected_model == 'gpt-3.5-turbo' else '' }}>GPT-3.5</option>
</select>
</form>
<div id="chat">
<p>{{ output|safe }}</p>
</div>
<form method="post" action="/">
<input type="text" size="49" name="command" required autocomplete="off">
<input type="submit" value="Submit">
<select id="model" name="model">
<option value="gpt-4o" {{ 'selected' if selected_model == 'gpt-4o' else '' }}>GPT-4o</option>
<option value="gpt-4-turbo" {{ 'selected' if selected_model == 'gpt-4-turbo' else '' }}>GPT-4</option>
<option value="gpt-3.5-turbo" {{ 'selected' if selected_model == 'gpt-3.5-turbo' else '' }}>GPT-3.5</option>
</select>
</form>
<div id="chat">
<p>{{ output|safe }}</p>
</div>
</body>
</html>
"""

def handle_request(req):
if req.method == 'POST':
content, status_code = handle_post(req)
elif req.method == 'GET':
content, status_code = handle_get(req)
else:
content, status_code = "Not Found", 404
return content, status_code
if req.method == 'POST':
content, status_code = handle_post(req)
elif req.method == 'GET':
content, status_code = handle_get(req)
else:
content, status_code = "Not Found", 404
return content, status_code

def handle_get(request):
return chat_interface(request), 200
return chat_interface(request), 200

def handle_post(request):
return chat_interface(request), 200
return chat_interface(request), 200

def chat_interface(request):
global messages, selected_model, previous_model
output = ""

if request.method == 'POST':
user_input = request.form['command']
selected_model = request.form['model']

# Check if the model has changed
if selected_model != previous_model:
previous_model = selected_model
messages = [{"role": "user", "content": user_input}]
else:
messages.append({"role": "user", "content": user_input})

# Prepare messages, ensuring not to exceed the most recent 10 interactions
messages_to_send = system_prompts + messages[-10:]

# Send the messages to OpenAI and get the response
response = client.chat.completions.create(
model=selected_model,
messages=messages_to_send
)
response_body = response.choices[0].message.content
messages.append({"role": "system", "content": response_body})

# Sanitize the response body
response_body = transcode_html(response_body, "html5", False)

for msg in reversed(messages[-10:]):
if msg['role'] == 'user':
output += f"<b>User:</b> {msg['content']}<br>"
elif msg['role'] == 'system':
output += f"<b>ChatGPT:</b> {msg['content']}<br>"

return render_template_string(HTML_TEMPLATE, output=output, selected_model=selected_model)
global messages, selected_model, previous_model
output = ""

if request.method == 'POST':
user_input = request.form['command']
selected_model = request.form['model']

# Check if the model has changed
if selected_model != previous_model:
previous_model = selected_model
messages = [{"role": "user", "content": user_input}]
else:
messages.append({"role": "user", "content": user_input})

# Prepare messages, ensuring not to exceed the most recent 10 interactions
messages_to_send = system_prompts + messages[-10:]

# Send the messages to OpenAI and get the response
response = client.chat.completions.create(
model=selected_model,
messages=messages_to_send
)
response_body = response.choices[0].message.content
messages.append({"role": "system", "content": response_body})

for msg in reversed(messages[-10:]):
if msg['role'] == 'user':
output += f"<b>User:</b> {msg['content']}<br>"
elif msg['role'] == 'system':
output += f"<b>ChatGPT:</b> {msg['content']}<br>"

return render_template_string(HTML_TEMPLATE, output=output, selected_model=selected_model)
3 changes: 0 additions & 3 deletions extensions/claude/claude.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from flask import request, render_template_string
import anthropic
import extensions.config as config
from html_utils import transcode_html

# Initialize the Anthropic client with your API key
client = anthropic.Anthropic(api_key=config.anthropic_api_key)
Expand Down Expand Up @@ -93,8 +92,6 @@ def chat_interface(request):
response_body = response.content[0].text
messages.append({"role": "assistant", "content": response_body})

# Sanitize the response body
response_body = transcode_html(response_body, "html5", False)
except Exception as e:
response_body = f"An error occurred: {str(e)}"
messages.append({"role": "assistant", "content": response_body})
Expand Down
27 changes: 12 additions & 15 deletions extensions/hackaday/hackaday.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from flask import request, redirect, render_template_string
import requests
from bs4 import BeautifulSoup, Comment
from html_utils import transcode_html
from datetime import datetime
import re
from urllib.parse import urlparse, unquote
Expand Down Expand Up @@ -58,7 +57,7 @@ def process_html(content, url):
meta_authors_span.append(soup.new_tag('br'))
meta_authors_list.replace_with(meta_authors_span)

# Replace <h1> tags with class "entry-title" with <b> tags, preserving their inner contents and adding <br><br>
# Replace <h1> tags with class "entry-title" with <b> tags, preserving their inner contents and adding <br>
entry_titles = soup.find_all('h1', class_='entry-title')
for h1 in entry_titles:
b_tag = soup.new_tag('b')
Expand Down Expand Up @@ -302,7 +301,7 @@ def process_html(content, url):
# Create the copyright div
copyright_div = soup.new_tag('div')
current_year = datetime.now().year
copyright_div.string = f"Copyright © {current_year} | Hackaday, Hack A Day, and the Skull and Wrenches Logo are Trademarks of Hackaday.com"
copyright_div.string = f"Copyright (c) {current_year} | Hackaday, Hack A Day, and the Skull and Wrenches Logo are Trademarks of Hackaday.com"
copyright_p = soup.new_tag('p')
copyright_p.append(copyright_div)

Expand Down Expand Up @@ -420,8 +419,8 @@ def process_html(content, url):

content = content.strip()
if len(content) > 200:
last_space = content[:200].rfind(' ')
content = content[:last_space]
last_space = content[:201].rfind(' ')
content = content[:last_space + 1]

div.string = content

Expand Down Expand Up @@ -535,7 +534,7 @@ def process_html(content, url):
if header:
title_b = header.find('b')
if title_b:
article_title = title_b.text.strip().split('<br')[0] # Remove <br> or <br/> if present
article_title = title_b.text.strip().split('<br>')[0] # Remove <br> if present
new_title = f"{article_title} | Hackaday"
else:
new_title = "Hackaday | Fresh Hacks Every Day"
Expand All @@ -560,17 +559,16 @@ def process_html(content, url):
if hackaday_native_search:
hackaday_native_search.decompose()

# Remove all class attributes to make page load faster
for tag in soup.find_all(class_=True):
del tag['class']
# Add a space at the beginning of each <span class="says"> tag
for span in soup.find_all('span', class_='says'):
span.string = ' ' + (span.string or '')

# Remove empty lines between tags throughout the document
for element in soup(text=lambda text: isinstance(text, str) and not text.strip()):
element.extract()

# Convert problem characters and return
updated_html = str(soup)
# print(updated_html)
return updated_html

def handle_get(req):
Expand Down Expand Up @@ -604,16 +602,15 @@ def handle_request(req):
def add_br_after_comments(soup):
def process_ol(ol):
children = ol.find_all('li', recursive=False)
for index, li in enumerate(children):
for li in children:
inner_ol = li.find('ol', recursive=False)
if inner_ol:
# Add <br> before the inner ol
inner_ol.insert_before(soup.new_tag('br'))
process_ol(inner_ol)
else:
# Add <br> after the current li unless it is the last li
if index != len(children) - 1:
li.insert_after(soup.new_tag('br'))

# Always add <br> after the current li
li.insert_after(soup.new_tag('br'))

comment_lists = soup.find_all('ol', class_='comment-list')
for comment_list in comment_lists:
Expand Down
4 changes: 1 addition & 3 deletions extensions/npr/npr.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from flask import request, redirect
import requests
from bs4 import BeautifulSoup
from html_utils import transcode_html

DOMAIN = "npr.org"

Expand Down Expand Up @@ -29,8 +28,7 @@ def handle_get(req):
if tag.has_attr('src'):
tag['src'] = f"/{tag['src'].lstrip('/')}"

content = transcode_html(str(soup), "html5", False)
return content, response.status_code
return str(soup), response.status_code
except Exception as e:
return f"Error: {str(e)}", 500

Expand Down
48 changes: 48 additions & 0 deletions extensions/override/override.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from flask import request, render_template_string

DOMAIN = "override.test"

HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<title>Override Control</title>
</head>
<body>
<h1>Override Control</h1>
<form method="post">
<input type="submit" name="action" value="Enable Override">
<input type="submit" name="action" value="Disable Override">
</form>
<p>Current status: {{ status }}</p>
{% if override_active %}
<p>Requested URL: {{ requested_url }}</p>
{% endif %}
</body>
</html>
"""

override_active = False

def get_override_status():
global override_active
return override_active

def handle_request(req):
global override_active

if req.method == 'POST':
action = req.form.get('action')
if action == 'Enable Override':
override_active = True
elif action == 'Disable Override':
override_active = False

status = "Override Active" if override_active else "Override Inactive"

requested_url = req.url if override_active else ""

return render_template_string(HTML_TEMPLATE,
status=status,
override_active=override_active,
requested_url=requested_url)
Loading

0 comments on commit 3836ee5

Please sign in to comment.