diff --git a/Makefile b/Makefile
index f3f767d..74922ed 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ PORT=8000
## Запустить приложение
app:
- poetry run uvicorn --host 0.0.0.0 --factory app.main:create_app --port $(PORT) --reload
+ poetry run uvicorn --host 0.0.0.0 --factory app.main:create_app --port $(PORT) --reload --reload-dir=app --reload-dir=settings
## Отформатировать код
format:
diff --git a/app/api/system/controllers.py b/app/api/system/controllers.py
index 676d687..2e705b2 100644
--- a/app/api/system/controllers.py
+++ b/app/api/system/controllers.py
@@ -5,6 +5,7 @@ from starlette import status
from settings.config import get_settings
router = APIRouter()
+settings = get_settings()
@router.get(
@@ -18,13 +19,11 @@ async def healthcheck() -> ORJSONResponse:
@router.post(
- f"/{get_settings().bot_webhook_url}",
+ f"/{settings.bot_webhook_url}",
name="system:process_bot_updates",
status_code=status.HTTP_202_ACCEPTED,
summary="process bot updates",
)
async def process_bot_updates(request: Request) -> ORJSONResponse:
await request.app.state.queue.put_updates_on_queue(request)
- data = await request.app.state.queue.get_updates_from_queue()
- print(data)
return ORJSONResponse(content=None, status_code=status.HTTP_202_ACCEPTED)
diff --git a/app/chat-gpt/.github/workflows/docker-build-push.yml b/app/chat-gpt/.github/workflows/docker-build-push.yml
new file mode 100644
index 0000000..8c62399
--- /dev/null
+++ b/app/chat-gpt/.github/workflows/docker-build-push.yml
@@ -0,0 +1,33 @@
+name: Docker Build and Push
+on:
+ push:
+ branches:
+ - main
+jobs:
+ build-and-push:
+ runs-on: ubuntu-latest
+ steps:
+
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Set up QEMU - Support for more platforms
+ uses: docker/setup-qemu-action@v2
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v2
+
+ - name: Login to Docker Hub
+ uses: docker/login-action@v1
+ with:
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v2
+ with:
+ context: .
+ file: Dockerfile
+ platforms: linux/amd64,linux/arm64
+ push: true
+ tags: ${{ secrets.DOCKER_USERNAME }}/freegpt-webui:latest
diff --git a/app/chat-gpt/.github/workflows/sync-hugging.yml b/app/chat-gpt/.github/workflows/sync-hugging.yml
new file mode 100644
index 0000000..63967cc
--- /dev/null
+++ b/app/chat-gpt/.github/workflows/sync-hugging.yml
@@ -0,0 +1,19 @@
+name: Sync with Hugging Face Hub
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Sync with Hugging Face
+ uses: ramonvc/huggingface-sync-action@v0.0.1
+ with:
+ github_repo_id: ramonvc/freegpt-webui
+ huggingface_repo_id: monra/freegpt-webui
+ repo_type: space
+ space_sdk: docker
+ hf_token: ${{ secrets.HF_TOKEN }}
\ No newline at end of file
diff --git a/app/chat-gpt/Caddyfile b/app/chat-gpt/Caddyfile
new file mode 100644
index 0000000..f337821
--- /dev/null
+++ b/app/chat-gpt/Caddyfile
@@ -0,0 +1,11 @@
+:8080 {
+
+ # Serving dynamic requests:
+ reverse_proxy chat_gpt:1338
+
+ # Logs:
+ log {
+ output stdout
+ }
+
+}
diff --git a/app/chat-gpt/Dockerfile b/app/chat-gpt/Dockerfile
new file mode 100644
index 0000000..2b931be
--- /dev/null
+++ b/app/chat-gpt/Dockerfile
@@ -0,0 +1,18 @@
+FROM python:3.11-slim
+
+WORKDIR /app
+
+COPY requirements.txt requirements.txt
+
+RUN python -m venv venv
+ENV PATH="/app/venv/bin:$PATH"
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends build-essential libffi-dev cmake libcurl4-openssl-dev \
+ && pip install --upgrade pip && pip3 install --no-cache-dir -r requirements.txt
+
+COPY . .
+
+RUN chmod -R 777 translations
+
+CMD ["python3", "./run.py"]
diff --git a/app/chat-gpt/README.md b/app/chat-gpt/README.md
new file mode 100644
index 0000000..600e25a
--- /dev/null
+++ b/app/chat-gpt/README.md
@@ -0,0 +1,190 @@
+# FreeGPT WebUI
+
+## Build
+```bash
+docker build -t balsh_chat_gpt --network=host .
+```
+
+
+## GPT 3.5/4
+
+NOT REQUIRE ANY API KEY ❌🔑
+
+This project features a WebUI utilizing the [G4F API](https://github.com/xtekky/gpt4free).
+Experience the power of ChatGPT with a user-friendly interface, enhanced jailbreaks, and completely free.
+
+## Known bugs 🚧
+- Stream mode not working properly.
+
+## News 📢
+I have created a new version of FreeGPT WebUI using the [ChimeraGPT API](https://chimeragpt.adventblocks.cc/).
+
+
+This free API allows you to use various AI chat models, including GPT-4, GPT-4-32k, llama-2 and more.
+Check out the project here: [FreeGPT WebUI - Chimera Version](https://github.com/ramonvc/freegpt-webui/tree/chimeragpt-version).
+
+## Project Hosting and Demonstration 🌐🚀
+The project is hosted on multiple platforms to be tested and modified.
+|Platform|Status|API Key|Free|Repo|Demo|
+|--|--|--|--|--|--|
+|[replit](https://replit.com/)||◼️|☑️|[FreeGPT WebUI](https://replit.com/@ramonvc/freegpt-webui)|[Chat](https://freegpt-webui.ramonvc.repl.co/chat/)
+|[hugging face](https://huggingface.co)||◼️|☑️|[FreeGPT WebUI](https://huggingface.co/spaces/monra/freegpt-webui/tree/main)|[Chat](https://huggingface.co/spaces/monra/freegpt-webui)
+|[replit](https://replit.com/)||☑️|☑️|[FreeGPT WebUI - Chimera Version](https://replit.com/@ramonvc/freegpt-webui-chimera)|[Chat](https://freegpt-webui-chimera.ramonvc.repl.co/chat/)
+|[hugging face](https://huggingface.co)||☑️|☑️|[FreeGPT WebUI - Chimera Version](https://huggingface.co/spaces/monra/freegpt-webui-chimera/tree/main)|[Chat](https://huggingface.co/spaces/monra/freegpt-webui-chimera)
+
+## Note ℹ️
+
+ FreeGPT is a project that utilizes various free AI conversation API Providers. Each Provider is an API that provides responses generated by different AI models. The source code related to these services is available in G4F folder.
+
+It is important to note that, due to the extensive reach of this project, the free services registered here may receive a significant number of requests, which can result in temporary unavailability or access limitations. Therefore, it is common to encounter these services being offline or unstable.
+
+We recommend that you search for your own Providers and add them to your personal projects to avoid service instability and unavailability. Within the project, in the Providers folder, you will find several examples of Providers that have worked in the past or are still functioning. It is easy to follow the logic of these examples to find free GPT services and incorporate the requests into your specific FreeGPT project.
+
+Please note that the choice and integration of additional Providers are the user's responsibility and are not directly related to the FreeGPT project, as the project serves as an example of how to combine the G4F API with a web interface.
+
+
+## Table of Contents
+- [To-Do List](#to-do-list-%EF%B8%8F)
+- [Getting Started](#getting-started-white_check_mark)
+ - [Cloning the Repository](#cloning-the-repository-inbox_tray)
+ - [Install Dependencies](#install-dependencies-wrench)
+- [Running the Application](#running-the-application-rocket)
+- [Docker](#docker-)
+ - [Prerequisites](#prerequisites)
+ - [Running the Docker](#running-the-docker)
+- [Incorporated Projects](#incorporated-projects-busts_in_silhouette)
+ - [WebUI](#webui)
+ - [API FreeGPT](#api-g4f)
+- [Star History](#star-history)
+- [Legal Notice](#legal-notice)
+
+##
+
+## To-Do List ✔️
+
+- [x] Integrate the free GPT API into the WebUI
+- [x] Create Docker support
+- [x] Improve the Jailbreak functionality
+- [x] Add the GPT-4 model
+- [x] Enhance the user interface
+- [ ] Check status of API Providers (online/offline)
+- [ ] Enable editing and creating Jailbreaks/Roles in the WebUI
+- [ ] Refactor web client
+
+## Getting Started :white_check_mark:
+To get started with this project, you'll need to clone the repository and have [Python](https://www.python.org/downloads/) installed on your system.
+
+### Cloning the Repository :inbox_tray:
+Run the following command to clone the repository:
+
+```
+git clone https://github.com/ramonvc/freegpt-webui.git
+```
+
+### Install Dependencies :wrench:
+Navigate to the project directory:
+```
+cd freegpt-webui
+```
+
+Install the dependencies:
+```
+pip install -r requirements.txt
+```
+## Running the Application :rocket:
+To run the application, run the following command:
+```
+python run.py
+```
+
+Access the application in your browser using the URL:
+```
+http://127.0.0.1:1338
+```
+or
+```
+http://localhost:1338
+```
+
+
+## Docker 🐳
+### Prerequisites
+Before you start, make sure you have installed [Docker](https://www.docker.com/get-started) on your machine.
+
+### Running the Docker
+Pull the Docker image from Docker Hub:
+```
+docker pull ramonvc/freegpt-webui
+```
+
+Run the application using Docker:
+```
+docker run -p 1338:1338 ramonvc/freegpt-webui
+```
+
+Access the application in your browser using the URL:
+```
+http://127.0.0.1:1338
+```
+or
+```
+http://localhost:1338
+```
+
+When you're done using the application, stop the Docker containers using the following command:
+```
+docker stop
+```
+
+## Incorporated Projects :busts_in_silhouette:
+I highly recommend visiting and supporting both projects.
+
+### WebUI
+The application interface was incorporated from the [chatgpt-clone](https://github.com/xtekky/chatgpt-clone) repository.
+
+### API G4F
+The free GPT-4 API was incorporated from the [GPT4Free](https://github.com/xtekky/gpt4free) repository.
+
+
+
+## Star History
+[](https://star-history.com/#ramonvc/freegpt-webui&Timeline)
+
+
+
+## Legal Notice
+This repository is _not_ associated with or endorsed by providers of the APIs contained in this GitHub repository. This
+project is intended **for educational purposes only**. This is just a little personal project. Sites may contact me to
+improve their security or request the removal of their site from this repository.
+
+Please note the following:
+
+1. **Disclaimer**: The APIs, services, and trademarks mentioned in this repository belong to their respective owners.
+ This project is _not_ claiming any right over them nor is it affiliated with or endorsed by any of the providers
+ mentioned.
+
+2. **Responsibility**: The author of this repository is _not_ responsible for any consequences, damages, or losses
+ arising from the use or misuse of this repository or the content provided by the third-party APIs. Users are solely
+ responsible for their actions and any repercussions that may follow. We strongly recommend the users to follow the
+ TOS of the each Website.
+
+3. **Educational Purposes Only**: This repository and its content are provided strictly for educational purposes. By
+ using the information and code provided, users acknowledge that they are using the APIs and models at their own risk
+ and agree to comply with any applicable laws and regulations.
+
+4. **Copyright**: All content in this repository, including but not limited to code, images, and documentation, is the
+ intellectual property of the repository author, unless otherwise stated. Unauthorized copying, distribution, or use
+ of any content in this repository is strictly prohibited without the express written consent of the repository
+ author.
+
+5. **Indemnification**: Users agree to indemnify, defend, and hold harmless the author of this repository from and
+ against any and all claims, liabilities, damages, losses, or expenses, including legal fees and costs, arising out of
+ or in any way connected with their use or misuse of this repository, its content, or related third-party APIs.
+
+6. **Updates and Changes**: The author reserves the right to modify, update, or remove any content, information, or
+ features in this repository at any time without prior notice. Users are responsible for regularly reviewing the
+ content and any changes made to this repository.
+
+By using this repository or any code related to it, you agree to these terms. The author is not responsible for any
+copies, forks, or reuploads made by other users. This is the author's only account and repository. To prevent
+impersonation or irresponsible actions, you may comply with the GNU GPL license this Repository uses.
diff --git a/app/chat-gpt/__init__.py b/app/chat-gpt/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/app/chat-gpt/babel.cfg b/app/chat-gpt/babel.cfg
new file mode 100644
index 0000000..9d1bdfa
--- /dev/null
+++ b/app/chat-gpt/babel.cfg
@@ -0,0 +1,2 @@
+[python: **/server/.py]
+[jinja2: **/client/html/**.html]
diff --git a/app/chat-gpt/client/css/button.css b/app/chat-gpt/client/css/button.css
new file mode 100644
index 0000000..5f604a8
--- /dev/null
+++ b/app/chat-gpt/client/css/button.css
@@ -0,0 +1,26 @@
+.button {
+ display: flex;
+ padding: 8px 12px;
+ align-items: center;
+ justify-content: center;
+ border: 1px solid var(--conversations);
+ border-radius: var(--border-radius-1);
+ width: 100%;
+ background: transparent;
+ cursor: pointer;
+}
+
+.button span {
+ color: var(--colour-3);
+ font-size: 0.875rem;
+}
+
+.button i::before {
+ margin-right: 8px;
+}
+
+@media screen and (max-width: 990px) {
+ .button span {
+ font-size: 0.75rem;
+ }
+}
diff --git a/app/chat-gpt/client/css/buttons.css b/app/chat-gpt/client/css/buttons.css
new file mode 100644
index 0000000..e13f52d
--- /dev/null
+++ b/app/chat-gpt/client/css/buttons.css
@@ -0,0 +1,4 @@
+.buttons {
+ display: flex;
+ justify-content: left;
+}
diff --git a/app/chat-gpt/client/css/checkbox.css b/app/chat-gpt/client/css/checkbox.css
new file mode 100644
index 0000000..94955b6
--- /dev/null
+++ b/app/chat-gpt/client/css/checkbox.css
@@ -0,0 +1,55 @@
+.checkbox input {
+ height: 0;
+ width: 0;
+ display: none;
+}
+
+.checkbox span {
+ font-size: 0.875rem;
+ color: var(--colour-2);
+ margin-left: 4px;
+}
+
+.checkbox label:after {
+ content: "";
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ left: 5px;
+ width: 20px;
+ height: 20px;
+ background: var(--blur-border);
+ border-radius: 90px;
+ transition: 0.33s;
+}
+
+.checkbox input + label:after,
+.checkbox input:checked + label {
+ background: var(--colour-3);
+}
+
+.checkbox input + label,
+.checkbox input:checked + label:after {
+ background: var(--blur-border);
+}
+
+.checkbox input:checked + label:after {
+ left: calc(100% - 5px - 20px);
+}
+
+@media screen and (max-width: 990px) {
+ .checkbox label {
+ width: 25px;
+ height: 15px;
+ }
+
+ .checkbox label:after {
+ left: 2px;
+ width: 10px;
+ height: 10px;
+ }
+
+ .checkbox input:checked + label:after {
+ left: calc(100% - 2px - 10px);
+ }
+}
diff --git a/app/chat-gpt/client/css/conversation.css b/app/chat-gpt/client/css/conversation.css
new file mode 100644
index 0000000..d20f178
--- /dev/null
+++ b/app/chat-gpt/client/css/conversation.css
@@ -0,0 +1,158 @@
+.conversation {
+ width: 60%;
+ margin: 0px 16px;
+ display: flex;
+ flex-direction: column;
+}
+
+.conversation #messages {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ overflow: auto;
+ overflow-wrap: break-word;
+ padding-bottom: 8px;
+}
+
+.conversation .user-input {
+ max-height: 180px;
+ margin: 16px 0px;
+}
+
+.conversation .user-input input {
+ font-size: 1rem;
+ background: none;
+ border: none;
+ outline: none;
+ color: var(--colour-3);
+}
+
+.conversation .user-input input::placeholder {
+ color: var(--user-input);
+}
+
+.conversation-title {
+ color: var(--colour-3);
+ font-size: 14px;
+}
+
+.conversation .user-input textarea {
+ font-size: 1rem;
+ width: 100%;
+ height: 100%;
+ padding: 12px;
+ background: none;
+ border: none;
+ outline: none;
+ color: var(--colour-3);
+ resize: vertical;
+ max-height: 150px;
+ min-height: 80px;
+}
+
+.box {
+ backdrop-filter: blur(20px);
+ -webkit-backdrop-filter: blur(20px);
+ background-color: var(--blur-bg);
+ height: 100%;
+ width: 100%;
+ border-radius: var(--border-radius-1);
+ border: 1px solid var(--blur-border);
+}
+
+.box.input-box {
+ position: relative;
+ align-items: center;
+ padding: 8px;
+ cursor: pointer;
+}
+
+#send-button {
+ position: absolute;
+ bottom: 25%;
+ right: 10px;
+ z-index: 1;
+ padding: 16px;
+}
+
+#cursor {
+ line-height: 17px;
+ margin-left: 3px;
+ -webkit-animation: blink 0.8s infinite;
+ animation: blink 0.8s infinite;
+ width: 7px;
+ height: 15px;
+}
+
+@keyframes blink {
+ 0% {
+ background: #ffffff00;
+ }
+
+ 50% {
+ background: white;
+ }
+
+ 100% {
+ background: #ffffff00;
+ }
+}
+
+@-webkit-keyframes blink {
+ 0% {
+ background: #ffffff00;
+ }
+
+ 50% {
+ background: white;
+ }
+
+ 100% {
+ background: #ffffff00;
+ }
+}
+
+/* scrollbar */
+.conversation #messages::-webkit-scrollbar {
+ width: 4px;
+ padding: 8px 0px;
+}
+
+.conversation #messages::-webkit-scrollbar-track {
+ background-color: #ffffff00;
+}
+
+.conversation #messages::-webkit-scrollbar-thumb {
+ background-color: #555555;
+ border-radius: 10px;
+}
+
+@media screen and (max-width: 990px) {
+ .conversation {
+ width: 100%;
+ height: 90%;
+ }
+}
+
+@media screen and (max-height: 720px) {
+ .conversation.box {
+ height: 70%;
+ }
+
+ .conversation .user-input textarea {
+ font-size: 0.875rem;
+ }
+}
+
+@media screen and (max-width: 360px) {
+ .box {
+ border-radius: 0;
+ }
+ .conversation {
+ margin: 0;
+ margin-top: 48px;
+ }
+ .conversation .user-input {
+ margin: 2px 0 8px 0;
+ }
+}
diff --git a/app/chat-gpt/client/css/dropdown.css b/app/chat-gpt/client/css/dropdown.css
new file mode 100644
index 0000000..302e911
--- /dev/null
+++ b/app/chat-gpt/client/css/dropdown.css
@@ -0,0 +1,10 @@
+.dropdown {
+ border: 1px solid var(--conversations);
+}
+
+@media screen and (max-width: 990px) {
+ .dropdown {
+ padding: 4px 8px;
+ font-size: 0.75rem;
+ }
+}
diff --git a/app/chat-gpt/client/css/field.css b/app/chat-gpt/client/css/field.css
new file mode 100644
index 0000000..914425a
--- /dev/null
+++ b/app/chat-gpt/client/css/field.css
@@ -0,0 +1,11 @@
+.field {
+ display: flex;
+ align-items: center;
+ padding: 4px;
+}
+
+@media screen and (max-width: 990px) {
+ .field {
+ flex-wrap: nowrap;
+ }
+}
diff --git a/app/chat-gpt/client/css/global.css b/app/chat-gpt/client/css/global.css
new file mode 100644
index 0000000..8de755e
--- /dev/null
+++ b/app/chat-gpt/client/css/global.css
@@ -0,0 +1,70 @@
+@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap");
+* {
+ --font-1: "Inter", sans-serif;
+ --section-gap: 24px;
+ --border-radius-1: 8px;
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ position: relative;
+ font-family: var(--font-1);
+}
+
+.theme-light {
+ --colour-1: #f5f5f5;
+ --colour-2: #000000;
+ --colour-3: #474747;
+ --colour-4: #949494;
+ --colour-5: #ebebeb;
+ --colour-6: #dadada;
+
+ --accent: #3a3a3a;
+ --blur-bg: #ffffff;
+ --blur-border: #dbdbdb;
+ --user-input: #282828;
+ --conversations: #666666;
+}
+
+.theme-dark {
+ --colour-1: #181818;
+ --colour-2: #ccc;
+ --colour-3: #dadada;
+ --colour-4: #f0f0f0;
+ --colour-5: #181818;
+ --colour-6: #242424;
+
+ --accent: #151718;
+ --blur-bg: #242627;
+ --blur-border: #242627;
+ --user-input: #f5f5f5;
+ --conversations: #555555;
+}
+
+html,
+body {
+ background: var(--colour-1);
+ color: var(--colour-3);
+}
+
+ol,
+ul {
+ padding-left: 20px;
+}
+
+.shown {
+ display: flex !important;
+}
+
+a:-webkit-any-link {
+ color: var(--accent);
+}
+
+pre {
+ white-space: pre-wrap;
+}
+
+@media screen and (max-height: 720px) {
+ :root {
+ --section-gap: 16px;
+ }
+}
diff --git a/app/chat-gpt/client/css/hljs.css b/app/chat-gpt/client/css/hljs.css
new file mode 100644
index 0000000..1fcf16b
--- /dev/null
+++ b/app/chat-gpt/client/css/hljs.css
@@ -0,0 +1,68 @@
+.hljs {
+ color: #e9e9f4;
+ background: #28293629;
+ border-radius: var(--border-radius-1);
+ border: 1px solid var(--blur-border);
+ font-size: 15px;
+ word-wrap: break-word;
+ white-space: pre-wrap;
+}
+
+/* style for hljs copy */
+.hljs-copy-wrapper {
+ position: relative;
+ overflow: hidden;
+}
+
+.hljs-copy-wrapper:hover .hljs-copy-button,
+.hljs-copy-button:focus {
+ transform: translateX(0);
+}
+
+.hljs-copy-button {
+ position: absolute;
+ transform: translateX(calc(100% + 1.125em));
+ top: 1em;
+ right: 1em;
+ width: 2rem;
+ height: 2rem;
+ text-indent: -9999px;
+ color: #fff;
+ border-radius: 0.25rem;
+ border: 1px solid #ffffff22;
+ background-color: #2d2b57;
+ background-image: url('data:image/svg+xml;utf-8,');
+ background-repeat: no-repeat;
+ background-position: center;
+ transition: background-color 200ms ease, transform 200ms ease-out;
+}
+
+.hljs-copy-button:hover {
+ border-color: #ffffff44;
+}
+
+.hljs-copy-button:active {
+ border-color: #ffffff66;
+}
+
+.hljs-copy-button[data-copied="true"] {
+ text-indent: 0;
+ width: auto;
+ background-image: none;
+}
+
+.hljs-copy-alert {
+ clip: rect(0 0 0 0);
+ clip-path: inset(50%);
+ height: 1px;
+ overflow: hidden;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+
+@media (prefers-reduced-motion) {
+ .hljs-copy-button {
+ transition: none;
+ }
+}
diff --git a/app/chat-gpt/client/css/label.css b/app/chat-gpt/client/css/label.css
new file mode 100644
index 0000000..d84873d
--- /dev/null
+++ b/app/chat-gpt/client/css/label.css
@@ -0,0 +1,16 @@
+label {
+ cursor: pointer;
+ text-indent: -9999px;
+ width: 50px;
+ height: 30px;
+ backdrop-filter: blur(20px);
+ -webkit-backdrop-filter: blur(20px);
+ background-color: var(--blur-bg);
+ border-radius: var(--border-radius-1);
+ border: 1px solid var(--blur-border);
+ display: block;
+ border-radius: 100px;
+ position: relative;
+ overflow: hidden;
+ transition: 0.33s;
+}
diff --git a/app/chat-gpt/client/css/main.css b/app/chat-gpt/client/css/main.css
new file mode 100644
index 0000000..ec1f1dd
--- /dev/null
+++ b/app/chat-gpt/client/css/main.css
@@ -0,0 +1,14 @@
+.main-container {
+ display: flex;
+ padding: var(--section-gap);
+ height: 100vh;
+ justify-content: center;
+ box-sizing: border-box;
+}
+
+@media screen and (max-width: 360px) {
+ .main-container {
+ padding: 0px;
+ height: 90vh;
+ }
+}
\ No newline at end of file
diff --git a/app/chat-gpt/client/css/message-input.css b/app/chat-gpt/client/css/message-input.css
new file mode 100644
index 0000000..de5f583
--- /dev/null
+++ b/app/chat-gpt/client/css/message-input.css
@@ -0,0 +1,27 @@
+#message-input {
+ margin-right: 30px;
+ height: 64px;
+}
+
+#message-input::-webkit-scrollbar {
+ width: 5px;
+}
+
+#message-input::-webkit-scrollbar-track {
+ background: #f1f1f1;
+}
+
+#message-input::-webkit-scrollbar-thumb {
+ background: #c7a2ff;
+}
+
+#message-input::-webkit-scrollbar-thumb:hover {
+ background: #8b3dff;
+}
+
+@media screen and (max-width: 360px) {
+ #message-input {
+ margin: 0;
+ }
+}
+
diff --git a/app/chat-gpt/client/css/message.css b/app/chat-gpt/client/css/message.css
new file mode 100644
index 0000000..64e0414
--- /dev/null
+++ b/app/chat-gpt/client/css/message.css
@@ -0,0 +1,65 @@
+.message {
+ width: 100%;
+ overflow-wrap: break-word;
+ display: flex;
+ gap: var(--section-gap);
+ padding: var(--section-gap);
+ padding-bottom: 0;
+}
+
+.message:last-child {
+ animation: 0.6s show_message;
+}
+
+@keyframes show_message {
+ from {
+ transform: translateY(10px);
+ opacity: 0;
+ }
+}
+
+.message .avatar-container img {
+ max-width: 48px;
+ max-height: 48px;
+ box-shadow: 0.4px 0.5px 0.7px -2px rgba(0, 0, 0, 0.08), 1.1px 1.3px 2px -2px rgba(0, 0, 0, 0.041),
+ 2.7px 3px 4.8px -2px rgba(0, 0, 0, 0.029), 9px 10px 16px -2px rgba(0, 0, 0, 0.022);
+}
+
+.message .content {
+ display: flex;
+ flex-direction: column;
+ width: 90%;
+ gap: 18px;
+}
+
+.message .content p,
+.message .content li,
+.message .content code {
+ font-size: 1rem;
+ line-height: 1.3;
+}
+
+@media screen and (max-height: 720px) {
+ .message {
+ padding: 12px;
+ gap: 0;
+ }
+
+ .message .content {
+ margin-left: 8px;
+ width: 80%;
+ }
+
+ .message .avatar-container img {
+ max-width: 32px;
+ max-height: 32px;
+ }
+
+ .message .content,
+ .message .content p,
+ .message .content li,
+ .message .content code {
+ font-size: 0.875rem;
+ line-height: 1.3;
+ }
+}
diff --git a/app/chat-gpt/client/css/options.css b/app/chat-gpt/client/css/options.css
new file mode 100644
index 0000000..fb015a5
--- /dev/null
+++ b/app/chat-gpt/client/css/options.css
@@ -0,0 +1,10 @@
+.options-container {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+@media screen and (max-width: 990px) {
+ .options-container {
+ justify-content: space-between;
+ }
+}
diff --git a/app/chat-gpt/client/css/select.css b/app/chat-gpt/client/css/select.css
new file mode 100644
index 0000000..7ec0159
--- /dev/null
+++ b/app/chat-gpt/client/css/select.css
@@ -0,0 +1,35 @@
+select {
+ -webkit-border-radius: 8px;
+ -moz-border-radius: 8px;
+ border-radius: 8px;
+
+ -webkit-backdrop-filter: blur(20px);
+ backdrop-filter: blur(20px);
+
+ cursor: pointer;
+ background-color: var(--blur-bg);
+ border: 1px solid var(--blur-border);
+ color: var(--colour-3);
+ display: block;
+ position: relative;
+ overflow: hidden;
+ outline: none;
+ padding: 8px 16px;
+
+ appearance: none;
+}
+
+/* scrollbar */
+select.dropdown::-webkit-scrollbar {
+ width: 4px;
+ padding: 8px 0px;
+}
+
+select.dropdown::-webkit-scrollbar-track {
+ background-color: #ffffff00;
+}
+
+select.dropdown::-webkit-scrollbar-thumb {
+ background-color: #555555;
+ border-radius: 10px;
+}
diff --git a/app/chat-gpt/client/css/settings.css b/app/chat-gpt/client/css/settings.css
new file mode 100644
index 0000000..0a409f2
--- /dev/null
+++ b/app/chat-gpt/client/css/settings.css
@@ -0,0 +1,44 @@
+.settings-container {
+ color: var(--colour-2);
+ margin: 24px 0px 8px 0px;
+ justify-content: center;
+}
+
+.settings-container span {
+ font-size: 0.875rem;
+ margin: 0;
+}
+
+.settings-container label {
+ width: 24px;
+ height: 16px;
+}
+
+.settings-container .field {
+ justify-content: space-between;
+}
+
+.settings-container .checkbox input + label,
+.settings-container .checkbox input:checked + label:after {
+ background: var(--colour-1);
+}
+
+.settings-container .checkbox input + label:after,
+.settings-container .checkbox input:checked + label {
+ background: var(--colour-3);
+}
+
+.settings-container .checkbox label:after {
+ left: 2px;
+ width: 10px;
+ height: 10px;
+}
+
+.settings-container .checkbox input:checked + label:after {
+ left: calc(100% - 2px - 10px);
+}
+
+.settings-container .dropdown {
+ padding: 4px 8px;
+ font-size: 0.75rem;
+}
diff --git a/app/chat-gpt/client/css/sidebar.css b/app/chat-gpt/client/css/sidebar.css
new file mode 100644
index 0000000..310887c
--- /dev/null
+++ b/app/chat-gpt/client/css/sidebar.css
@@ -0,0 +1,197 @@
+.sidebar {
+ max-width: 260px;
+ padding: var(--section-gap);
+ flex-shrink: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+}
+
+.sidebar .title {
+ font-size: 14px;
+ font-weight: 500;
+}
+
+.sidebar .conversation-sidebar {
+ padding: 8px 12px;
+ display: flex;
+ gap: 18px;
+ align-items: center;
+ user-select: none;
+ justify-content: space-between;
+}
+
+.sidebar .conversation-sidebar .left {
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.sidebar i {
+ color: var(--conversations);
+ cursor: pointer;
+}
+
+.sidebar .top {
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ gap: 16px;
+ padding-right: 8px;
+}
+
+.sidebar .top:hover {
+ overflow: auto;
+}
+
+.sidebar .info {
+ padding: 8px 12px 0px 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ user-select: none;
+ background: transparent;
+ width: 100%;
+ border: none;
+ text-decoration: none;
+}
+
+.sidebar .info span {
+ color: var(--conversations);
+ line-height: 1.5;
+ font-size: 0.75rem;
+}
+
+.sidebar .info i::before {
+ margin-right: 8px;
+}
+
+.sidebar-footer {
+ width: 100%;
+ margin-top: 16px;
+ display: flex;
+ flex-direction: column;
+}
+
+.sidebar-footer button {
+ cursor: pointer;
+ user-select: none;
+ background: transparent;
+}
+
+.sidebar.shown {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 1000;
+}
+
+.sidebar.shown .box {
+ background-color: #16171a;
+ width: 80%;
+ height: 100%;
+ overflow-y: auto;
+}
+
+@keyframes spinner {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+/* scrollbar */
+.sidebar .top::-webkit-scrollbar {
+ width: 4px;
+ padding: 8px 0px;
+}
+
+.sidebar .top::-webkit-scrollbar-track {
+ background-color: #ffffff00;
+}
+
+.sidebar .top::-webkit-scrollbar-thumb {
+ background-color: #555555;
+ border-radius: 10px;
+}
+
+.spinner:before {
+ content: "";
+ box-sizing: border-box;
+ position: absolute;
+ top: 50%;
+ left: 45%;
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ border: 1px solid var(--conversations);
+ border-top-color: white;
+ animation: spinner 0.6s linear infinite;
+}
+
+.menu-button {
+ display: none !important;
+ position: absolute;
+ z-index: 100000;
+ top: 0;
+ left: 0;
+ margin: 10px;
+ font-size: 1rem;
+ cursor: pointer;
+ width: 30px;
+ height: 30px;
+ justify-content: center;
+ align-items: center;
+ transition: 0.33s;
+}
+
+.menu-button i {
+ transition: 0.33s;
+}
+
+.rotated {
+ transform: rotate(360deg);
+}
+
+.menu-button.rotated {
+ position: fixed;
+ top: 10px;
+ left: 10px;
+ z-index: 1001;
+}
+
+@media screen and (max-width: 990px) {
+ .sidebar {
+ display: none;
+ width: 100%;
+ max-width: none;
+ }
+
+ .menu-button {
+ display: flex !important;
+ }
+}
+
+@media (max-width: 990px) {
+ .sidebar .top {
+ padding-top: 48px;
+ }
+}
+
+@media (min-width: 768px) {
+ .sidebar.shown {
+ position: static;
+ width: auto;
+ height: auto;
+ background-color: transparent;
+ }
+
+ .sidebar.shown .box {
+ background-color: #16171a;
+ width: auto;
+ height: auto;
+ overflow-y: auto;
+ }
+}
diff --git a/app/chat-gpt/client/css/stop-generating.css b/app/chat-gpt/client/css/stop-generating.css
new file mode 100644
index 0000000..3c2010d
--- /dev/null
+++ b/app/chat-gpt/client/css/stop-generating.css
@@ -0,0 +1,38 @@
+.stop-generating {
+ position: absolute;
+ bottom: 128px;
+ left: 50%;
+ transform: translateX(-50%);
+ z-index: 1000000;
+}
+
+.stop-generating button {
+ backdrop-filter: blur(20px);
+ -webkit-backdrop-filter: blur(20px);
+ background-color: var(--blur-bg);
+ color: var(--colour-3);
+ cursor: pointer;
+ animation: show_popup 0.4s;
+}
+
+@keyframes show_popup {
+ from {
+ opacity: 0;
+ transform: translateY(10px);
+ }
+}
+
+@keyframes hide_popup {
+ to {
+ opacity: 0;
+ transform: translateY(10px);
+ }
+}
+
+.stop-generating-hiding button {
+ animation: hide_popup 0.4s;
+}
+
+.stop-generating-hidden button {
+ display: none;
+}
diff --git a/app/chat-gpt/client/css/style.css b/app/chat-gpt/client/css/style.css
new file mode 100644
index 0000000..5eca9f5
--- /dev/null
+++ b/app/chat-gpt/client/css/style.css
@@ -0,0 +1,18 @@
+@import "global.css";
+@import "hljs.css";
+@import "main.css";
+@import "sidebar.css";
+@import "conversation.css";
+@import "message.css";
+@import "stop-generating.css";
+@import "typing.css";
+@import "checkbox.css";
+@import "label.css";
+@import "button.css";
+@import "buttons.css";
+@import "dropdown.css";
+@import "field.css";
+@import "select.css";
+@import "options.css";
+@import "settings.css";
+@import "message-input.css";
diff --git a/app/chat-gpt/client/css/typing.css b/app/chat-gpt/client/css/typing.css
new file mode 100644
index 0000000..f998ebe
--- /dev/null
+++ b/app/chat-gpt/client/css/typing.css
@@ -0,0 +1,15 @@
+.typing {
+ position: absolute;
+ top: -25px;
+ left: 0;
+ font-size: 14px;
+ animation: show_popup 0.4s;
+}
+
+.typing-hiding {
+ animation: hide_popup 0.4s;
+}
+
+.typing-hidden {
+ display: none;
+}
diff --git a/app/chat-gpt/client/html/index.html b/app/chat-gpt/client/html/index.html
new file mode 100644
index 0000000..0b7bc5e
--- /dev/null
+++ b/app/chat-gpt/client/html/index.html
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FreeGPT
+
+
+
+