this app was already compiled how can i change the api key #!/bin/bash

set -e

BUILD_DIR="$HOME/Desktop/LegalExtractorBuild"
DESKTOP_DIR="$HOME/Desktop"
APP_NAME="LegalExtractor"

mkdir -p "$BUILD_DIR"
python3 -m venv "$BUILD_DIR/venv"
source "$BUILD_DIR/venv/bin/activate"

pip install --upgrade pip
pip install groq PyQt5 pyinstaller markdown tenacity

cat << 'EOF' > "$BUILD_DIR/legal_extractor.py"
import os
import sys
import json
import subprocess
import time
from groq import Groq
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import markdown
from tenacity import retry, stop_after_attempt, wait_fixed

DEFAULT_MODEL = "llama3-70b-8192"
DEFAULT_API_KEY = "<TRUFFLEHOG_REDACTED_GROQ>"
CHUNK_SIZE = 4000
DELAY_BETWEEN_REQUESTS = 1

class AIThread(QThread):
    response_ready = pyqtSignal(str)
    error_occurred = pyqtSignal(str)

    def __init__(self, api_key, messages, model):
        super().__init__()
        self.api_key, self.messages, self.model = api_key, messages, model

    @retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
    def make_api_call(self, client, messages, model):
        return client.chat.completions.create(messages=messages, model=model, temperature=0)

    def run(self):
        try:
            client = Groq(api_key=self.api_key)
            chat_completion = self.make_api_call(client, self.messages, self.model)
            self.response_ready.emit(chat_completion.choices[0].message.content)
        except Exception as e:
            self.error_occurred.emit(str(e))

class ProgressWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        layout = QVBoxLayout(self)
        self.progress_bar = QProgressBar(self)
        self.status_label = QLabel("Processing...", self)
        layout.addWidget(self.status_label)
        layout.addWidget(self.progress_bar)
        self.setWindowTitle("Processing")
        self.resize(300, 100)

    def update_progress(self, value, maximum):
        self.progress_bar.setMaximum(maximum)
        self.progress_bar.setValue(value)

    def update_status(self, status):
        self.status_label.setText(status)

class LegalExtractor(QWidget):
    def __init__(self):
        super().__init__()
        self.api_key = DEFAULT_API_KEY
        self.model = DEFAULT_MODEL
        self.chunks = []
        self.extractions = []
        self.progress_window = ProgressWindow()
        self.initUI()

    def initUI(self):
        layout = QVBoxLayout(self)

        self.file_path_edit = QLineEdit()
        self.file_path_edit.setPlaceholderText("Drag and drop file here or click Browse")
        self.file_path_edit.setReadOnly(True)
        layout.addWidget(self.file_path_edit)

        browse_button = QPushButton('Browse')
        browse_button.clicked.connect(self.browse_file)
        layout.addWidget(browse_button)

        self.process_button = QPushButton('Process File')
        self.process_button.clicked.connect(self.process_file)
        layout.addWidget(self.process_button)

        self.result_display = QTextEdit()
        self.result_display.setReadOnly(True)
        layout.addWidget(self.result_display)

        self.aggregate_button = QPushButton('Aggregate Results')
        self.aggregate_button.clicked.connect(self.aggregate_results)
        self.aggregate_button.setEnabled(False)
        layout.addWidget(self.aggregate_button)

        self.export_raw_button = QPushButton('Export Raw as TXT')
        self.export_raw_button.clicked.connect(self.export_raw)
        self.export_raw_button.setEnabled(False)
        layout.addWidget(self.export_raw_button)

        self.export_aggregated_button = QPushButton('Export Aggregated as TXT')
        self.export_aggregated_button.clicked.connect(self.export_aggregated)
        self.export_aggregated_button.setEnabled(False)
        layout.addWidget(self.export_aggregated_button)

        self.setAcceptDrops(True)
        self.setWindowTitle('Legal Document Extractor')
        self.resize(600, 400)

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        files = [u.toLocalFile() for u in event.mimeData().urls()]
        if files:
            self.file_path_edit.setText(files[0])

    def browse_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "Select File")
        if file_path:
            self.file_path_edit.setText(file_path)

    def process_file(self):
        file_path = self.file_path_edit.text()
        if not file_path:
            self.show_error("No file selected", "Please select a file to process.")
            return

        self.result_display.clear()
        self.progress_window.show()
        self.progress_window.update_status("Extracting text...")
        QApplication.processEvents()

        try:
            text = self.extract_text(file_path)
            self.chunks = self.chunk_text(text)
            
            self.extractions = []
            self.progress_window.update_status("Processing chunks...")
            self.progress_window.update_progress(0, len(self.chunks))

            for i, chunk in enumerate(self.chunks, 1):
                self.progress_window.update_progress(i, len(self.chunks))
                self.progress_window.update_status(f"Processing chunk {i}/{len(self.chunks)}")
                QApplication.processEvents()

                prompt = (f"Extract all legal cases, legal statutes, and legal rules in bluebook format. "
                          f"Provide only the extracted information without any additional commentary. Text: {chunk}")

                messages = [
                    {"role": "system", "content": "You are a legal expert tasked with extracting legal information from documents."},
                    {"role": "user", "content": prompt}
                ]

                ai_thread = AIThread(self.api_key, messages, self.model)
                ai_thread.response_ready.connect(self.handle_extraction_response)
                ai_thread.error_occurred.connect(self.handle_error)
                ai_thread.start()
                ai_thread.wait()

                time.sleep(DELAY_BETWEEN_REQUESTS)

            self.progress_window.hide()
            self.result_display.append("Processing complete. Click 'Aggregate Results' to view the extracted information.")
            self.aggregate_button.setEnabled(True)
            self.export_raw_button.setEnabled(True)

        except Exception as e:
            self.progress_window.hide()
            self.show_error("Error processing file", str(e))

    def extract_text(self, file_path):
        textra_path = os.path.join(os.path.dirname(sys.executable), 'textra')
        result = subprocess.run([textra_path, file_path], capture_output=True, text=True)
        if result.returncode != 0:
            raise Exception(f"Error extracting text: {result.stderr}")
        return result.stdout

    def chunk_text(self, text):
        return [text[i:i+CHUNK_SIZE] for i in range(0, len(text), CHUNK_SIZE)]

    def handle_extraction_response(self, response):
        self.extractions.append(response)

    def handle_error(self, error_message):
        self.progress_window.hide()
        self.show_error("AI Error", f"An error occurred: {error_message}")

    def show_error(self, title, message):
        QMessageBox.critical(self, title, message)

    def aggregate_results(self):
        self.result_display.clear()
        self.result_display.append("Aggregating results...")
        self.progress_window.show()
        self.progress_window.update_status("Aggregating results...")
        QApplication.processEvents()

        prompt = ("You are a legal expert. Given the following extracted legal information, "
                  "create a perfect non-redundant master list of all unique legal cases, "
                  "legal statutes, and legal rules in bluebook format. Remove any duplicates "
                  "and organize the information clearly. Here's the extracted information:\n\n" +
                  "\n".join(self.extractions))

        messages = [
            {"role": "system", "content": "You are a legal expert tasked with aggregating and organizing legal information."},
            {"role": "user", "content": prompt}
        ]

        ai_thread = AIThread(self.api_key, messages, self.model)
        ai_thread.response_ready.connect(self.handle_aggregation_response)
        ai_thread.error_occurred.connect(self.handle_error)
        ai_thread.start()

    def handle_aggregation_response(self, response):
        self.aggregated_result = response
        html = markdown.markdown(response)
        self.result_display.clear()
        self.result_display.append(html)
        self.export_aggregated_button.setEnabled(True)
        self.progress_window.hide()

    def export_raw(self):
        file_path, _ = QFileDialog.getSaveFileName(self, "Save Raw Extractions", "", "Text Files (*.txt)")
        if file_path:
            with open(file_path, 'w') as f:
                for extraction in self.extractions:
                    f.write(extraction + "\n\n" + "-"*50 + "\n\n")
            QMessageBox.information(self, "Export Successful", f"Raw extractions saved to {file_path}")

    def export_aggregated(self):
        if hasattr(self, 'aggregated_result'):
            file_path, _ = QFileDialog.getSaveFileName(self, "Save Aggregated Result", "", "Text Files (*.txt)")
            if file_path:
                with open(file_path, 'w') as f:
                    f.write(self.aggregated_result)
                QMessageBox.information(self, "Export Successful", f"Aggregated result saved to {file_path}")
        else:
            QMessageBox.warning(self, "No Aggregated Result", "Please aggregate the results before exporting.")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = LegalExtractor()
    ex.show()
    sys.exit(app.exec_())
EOF

cat << EOF > "$BUILD_DIR/legal_extractor.spec"
# -*- mode: python ; coding: utf-8 -*-

block_cipher = None

a = Analysis(['legal_extractor.py'],
             pathex=['$BUILD_DIR'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          [],
          exclude_binaries=True,
          name='LegalExtractor',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          console=False )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               upx_exclude=[],
               name='LegalExtractor')
app = BUNDLE(coll,
             name='LegalExtractor.app',
             icon=None,
             bundle_identifier=None)
EOF

pyinstaller "$BUILD_DIR/legal_extractor.spec"

mkdir -p "$BUILD_DIR/dist/LegalExtractor.app/Contents/MacOS"

# Copy textra binary to the app bundle
cp "$DESKTOP_DIR/textra" "$BUILD_DIR/dist/LegalExtractor.app/Contents/MacOS/"

mv "$BUILD_DIR/dist/LegalExtractor.app" "$DESKTOP_DIR/"

deactivate

echo "LegalExtractor.app has been created on your Desktop at $DESKTOP_DIR/LegalExtractor.app"
echo "The textra binary has been included in the app bundle."

# Add a check for successful build
if [ -e "$DESKTOP_DIR/LegalExtractor.app" ]; then
    echo "LegalExtractor.app has been successfully created on your Desktop."
else
    echo "Error: LegalExtractor.app was not created successfully. Please check the build logs for errors."
fi

# Cleanup
read -p "Do you want to remove the build directory? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
    rm -rf "$BUILD_DIR"
    echo "Build directory removed."
else
    echo "Build directory kept at $BUILD_DIR"
fi

echo "Setup complete. Enjoy using LegalExtractor!"