mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-12-06 02:30:41 -08:00
commit
292d5b69cd
5 changed files with 17 additions and 102 deletions
|
|
@ -10,7 +10,6 @@ from email.utils import formatdate
|
||||||
import os.path
|
import os.path
|
||||||
import hashlib
|
import hashlib
|
||||||
import asyncio
|
import asyncio
|
||||||
from urllib.parse import quote_plus
|
|
||||||
from fastapi import FastAPI, Response, Request, UploadFile, Depends
|
from fastapi import FastAPI, Response, Request, UploadFile, Depends
|
||||||
from fastapi.middleware.wsgi import WSGIMiddleware
|
from fastapi.middleware.wsgi import WSGIMiddleware
|
||||||
from fastapi.responses import StreamingResponse, RedirectResponse, HTMLResponse, JSONResponse
|
from fastapi.responses import StreamingResponse, RedirectResponse, HTMLResponse, JSONResponse
|
||||||
|
|
@ -552,7 +551,7 @@ class Api:
|
||||||
HTTP_404_NOT_FOUND: {}
|
HTTP_404_NOT_FOUND: {}
|
||||||
})
|
})
|
||||||
async def get_image(filename, request: Request):
|
async def get_image(filename, request: Request):
|
||||||
target = os.path.join(images_dir, quote_plus(filename))
|
target = os.path.join(images_dir, os.path.basename(filename))
|
||||||
ext = os.path.splitext(filename)[1][1:]
|
ext = os.path.splitext(filename)[1][1:]
|
||||||
stat_result = SimpleNamespace()
|
stat_result = SimpleNamespace()
|
||||||
stat_result.st_size = 0
|
stat_result.st_size = 0
|
||||||
|
|
|
||||||
|
|
@ -1122,6 +1122,7 @@ ul {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
padding: 10px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-sidebar i {
|
.mobile-sidebar i {
|
||||||
|
|
@ -1421,11 +1422,12 @@ form .field.saved .fa-xmark {
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapsible {
|
.field.collapsible {
|
||||||
border: 1px solid var(--blur-border);
|
border: 1px solid var(--blur-border);
|
||||||
border-radius: var(--border-radius-1);
|
border-radius: var(--border-radius-1);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapsible-header {
|
.collapsible-header {
|
||||||
|
|
@ -1442,7 +1444,11 @@ form .field.saved .fa-xmark {
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapsible-content {
|
.collapsible-content {
|
||||||
padding: 10px;
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapsible-content.api-key {
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapsible-content.hidden {
|
.collapsible-content.hidden {
|
||||||
|
|
@ -1539,6 +1545,7 @@ form .field.saved .fa-xmark {
|
||||||
.conversations, .settings, .conversation {
|
.conversations, .settings, .conversation {
|
||||||
flex: 1 1 300px;
|
flex: 1 1 300px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Media queries for mobile devices */
|
/* Media queries for mobile devices */
|
||||||
|
|
@ -1557,92 +1564,9 @@ form .field.saved .fa-xmark {
|
||||||
order: -1;
|
order: -1;
|
||||||
min-height: 80vh;
|
min-height: 80vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttons .field {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#model, #provider {
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-input .input-area {
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea#message-input {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-sidebar {
|
|
||||||
display: block;
|
|
||||||
position: fixed;
|
|
||||||
top: 10px;
|
|
||||||
left: 10px;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.conversations {
|
|
||||||
position: fixed;
|
|
||||||
left: -100%;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
transition: left 0.3s;
|
|
||||||
z-index: 999;
|
|
||||||
background: var(--bg-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.conversations.active {
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Flexible form elements */
|
|
||||||
.user-input .input-area {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
max-width: 100%;
|
|
||||||
min-height: 50px;
|
|
||||||
resize: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adaptive buttons */
|
|
||||||
button {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-label {
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adaptive model menu */
|
|
||||||
#model, #provider {
|
|
||||||
max-width: 150px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.buttons .field {
|
|
||||||
flex: 1 1 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#model, #provider {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toolbar {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info .convo-title {
|
.info .convo-title {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1651,8 +1651,10 @@ window.addEventListener('popstate', hide_sidebar, false);
|
||||||
sidebar_button.addEventListener("click", async () => {
|
sidebar_button.addEventListener("click", async () => {
|
||||||
if (sidebar.classList.contains("shown")) {
|
if (sidebar.classList.contains("shown")) {
|
||||||
await hide_sidebar();
|
await hide_sidebar();
|
||||||
|
chat.classList.remove("hidden");
|
||||||
} else {
|
} else {
|
||||||
await show_menu();
|
await show_menu();
|
||||||
|
chat.classList.add("hidden");
|
||||||
}
|
}
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
});
|
});
|
||||||
|
|
@ -2096,7 +2098,7 @@ async function on_api() {
|
||||||
<span class="label">Providers API key</span>
|
<span class="label">Providers API key</span>
|
||||||
<i class="fa-solid fa-chevron-down"></i>
|
<i class="fa-solid fa-chevron-down"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapsible-content hidden"></div>
|
<div class="collapsible-content api-key hidden"></div>
|
||||||
`;
|
`;
|
||||||
settings.querySelector(".paper").appendChild(providersListContainer);
|
settings.querySelector(".paper").appendChild(providersListContainer);
|
||||||
|
|
||||||
|
|
@ -2739,13 +2741,3 @@ document.getElementById("showLog").addEventListener("click", ()=> {
|
||||||
settings.classList.add("hidden");
|
settings.classList.add("hidden");
|
||||||
log_storage.scrollTop = log_storage.scrollHeight;
|
log_storage.scrollTop = log_storage.scrollHeight;
|
||||||
});
|
});
|
||||||
|
|
||||||
document.querySelector('.mobile-sidebar').addEventListener('click', function() {
|
|
||||||
document.querySelector('.conversations').classList.toggle('active');
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener('click', function(e) {
|
|
||||||
if(!e.target.closest('.conversations') && !e.target.closest('.mobile-sidebar')) {
|
|
||||||
document.querySelector('.conversations').classList.remove('active');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,8 @@ async def copy_images(
|
||||||
) as session:
|
) as session:
|
||||||
async def copy_image(image: str, target: str = None) -> str:
|
async def copy_image(image: str, target: str = None) -> str:
|
||||||
"""Process individual image and return its local URL"""
|
"""Process individual image and return its local URL"""
|
||||||
target_path = None
|
target_path = target
|
||||||
try:
|
if target_path is None:
|
||||||
# Generate filename components
|
# Generate filename components
|
||||||
file_hash = hashlib.sha256(image.encode()).hexdigest()[:16]
|
file_hash = hashlib.sha256(image.encode()).hexdigest()[:16]
|
||||||
timestamp = int(time.time())
|
timestamp = int(time.time())
|
||||||
|
|
@ -88,7 +88,7 @@ async def copy_images(
|
||||||
f"{extension}"
|
f"{extension}"
|
||||||
)
|
)
|
||||||
target_path = os.path.join(images_dir, filename)
|
target_path = os.path.join(images_dir, filename)
|
||||||
|
try:
|
||||||
# Handle different image types
|
# Handle different image types
|
||||||
if image.startswith("data:"):
|
if image.startswith("data:"):
|
||||||
with open(target_path, "wb") as f:
|
with open(target_path, "wb") as f:
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ from ..providers.asyncio import to_sync_generator
|
||||||
from ..errors import MissingRequirementsError
|
from ..errors import MissingRequirementsError
|
||||||
from .. import debug
|
from .. import debug
|
||||||
|
|
||||||
PLAIN_FILE_EXTENSIONS = ["txt", "xml", "json", "js", "har", "sh", "py", "php", "css", "yaml", "sql", "log", "csv", "twig", "md"]
|
PLAIN_FILE_EXTENSIONS = ["txt", "xml", "json", "js", "har", "sh", "py", "php", "css", "yaml", "sql", "log", "csv", "twig", "md", "arc"]
|
||||||
PLAIN_CACHE = "plain.cache"
|
PLAIN_CACHE = "plain.cache"
|
||||||
DOWNLOADS_FILE = "downloads.json"
|
DOWNLOADS_FILE = "downloads.json"
|
||||||
FILE_LIST = "files.txt"
|
FILE_LIST = "files.txt"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue