diff --git a/.gitignore b/.gitignore index e427ff3..d387093 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ */node_modules/ */build/ +.env diff --git a/ai/__pycache__/__init__.cpython-311.pyc b/ai/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..8bcb2fb Binary files /dev/null and b/ai/__pycache__/__init__.cpython-311.pyc differ diff --git a/ai/__pycache__/local_ai_api.cpython-311.pyc b/ai/__pycache__/local_ai_api.cpython-311.pyc new file mode 100644 index 0000000..fa9977d Binary files /dev/null and b/ai/__pycache__/local_ai_api.cpython-311.pyc differ diff --git a/config/__pycache__/wsgi.cpython-311.pyc b/config/__pycache__/wsgi.cpython-311.pyc index 79ce690..b807168 100644 Binary files a/config/__pycache__/wsgi.cpython-311.pyc and b/config/__pycache__/wsgi.cpython-311.pyc differ diff --git a/config/wsgi.py b/config/wsgi.py index e2fbd58..0bd1abf 100644 --- a/config/wsgi.py +++ b/config/wsgi.py @@ -8,9 +8,11 @@ https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/ """ import os +from dotenv import load_dotenv from django.core.wsgi import get_wsgi_application +load_dotenv() os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') application = get_wsgi_application() diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index cd6f855..5f1a588 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000..838490d Binary files /dev/null and b/core/__pycache__/forms.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 9aa598b..6e44947 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 1f807fa..7e5f23d 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 6867ddf..050d896 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 8c38f3f..80f9113 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,3 +1,8 @@ from django.contrib import admin +from .models import Post -# Register your models here. +@admin.register(Post) +class PostAdmin(admin.ModelAdmin): + list_display = ('author', 'created_at', 'intent') + list_filter = ('created_at', 'intent') + search_fields = ('content', 'author__username') \ No newline at end of file diff --git a/core/forms.py b/core/forms.py new file mode 100644 index 0000000..d660379 --- /dev/null +++ b/core/forms.py @@ -0,0 +1,27 @@ +from django import forms +from django.contrib.auth.forms import UserCreationForm +from django.contrib.auth.models import User +from .models import Post + +class SignUpForm(UserCreationForm): + email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.') + + class Meta: + model = User + fields = ('username', 'email', 'password', 'password2') + +class PostForm(forms.ModelForm): + content = forms.CharField( + widget=forms.Textarea( + attrs={ + "class": "w-full bg-gray-800 border border-gray-700 rounded-lg p-4 text-white focus:outline-none focus:ring-2 focus:ring-teal-500", + "placeholder": "What's on your mind?", + "rows": 3, + } + ), + label="", + ) + + class Meta: + model = Post + fields = ["content"] diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..88adf57 --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 5.2.7 on 2025-12-18 17:57 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Post', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/core/migrations/0002_post_intent.py b/core/migrations/0002_post_intent.py new file mode 100644 index 0000000..1f63823 --- /dev/null +++ b/core/migrations/0002_post_intent.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2025-12-18 18:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='post', + name='intent', + field=models.CharField(default='Neutral', max_length=50), + ), + ] diff --git a/core/migrations/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000..ccbd2cc Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/0002_post_intent.cpython-311.pyc b/core/migrations/__pycache__/0002_post_intent.cpython-311.pyc new file mode 100644 index 0000000..6fa9c5f Binary files /dev/null and b/core/migrations/__pycache__/0002_post_intent.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 71a8362..4c9d4f9 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,13 @@ +from django.contrib.auth.models import User from django.db import models -# Create your models here. +class Post(models.Model): + author = models.ForeignKey(User, on_delete=models.CASCADE) + title = models.CharField(max_length=200) + slug = models.SlugField(unique=True) + content = models.TextField() + created_at = models.DateTimeField(auto_now_add=True) + intent = models.CharField(max_length=50, default='Neutral') + + def __str__(self): + return f'Post by {self.author.username} on {self.created_at.strftime("%Y-%m-%d")}' \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..6ab8899 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -3,7 +3,7 @@ - {% block title %}Knowledge Base{% endblock %} + {% block title %}Cipher Shield{% endblock %} {% if project_description %} @@ -13,13 +13,64 @@ {% endif %} + {% load static %} {% block head %}{% endblock %} - - {% block content %}{% endblock %} + + +
+
+ {% block content %}{% endblock %} +
+
+ diff --git a/core/templates/core/ad_generator.html b/core/templates/core/ad_generator.html new file mode 100644 index 0000000..23bdf19 --- /dev/null +++ b/core/templates/core/ad_generator.html @@ -0,0 +1,52 @@ +{% extends 'base.html' %} +{% load static %} + +{% block content %} +
+

Ad Generation Tool

+ +
+
+
+
+
Enter Product Details
+
+ {% csrf_token %} +
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+
+
+
+
Generated Ad Creative
+ {% if ad_copy and ad_image_url %} +
+ Generated Ad Image +
+
Ad Copy
+

{{ ad_copy }}

+
+
+ {% else %} +

Your generated ad creative will appear here.

+ {% endif %} +
+
+
+
+
+{% endblock %} diff --git a/core/templates/core/ai_chat.html b/core/templates/core/ai_chat.html new file mode 100644 index 0000000..8200205 --- /dev/null +++ b/core/templates/core/ai_chat.html @@ -0,0 +1,53 @@ +{% extends 'base.html' %} + +{% block content %} +
+

AI Chat

+
+
+ {% csrf_token %} +
+ + +
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/core/templates/core/blog.html b/core/templates/core/blog.html new file mode 100644 index 0000000..29f69ae --- /dev/null +++ b/core/templates/core/blog.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block content %} +
+

Blog

+
+ {% for post in posts %} +
+
+
+

{{ post.title }}

+

{{ post.content|truncatewords:50 }}

+ Read More → +
+ +
+
+ {% endfor %} +
+
+{% endblock %} diff --git a/core/templates/core/graphics_editor.html b/core/templates/core/graphics_editor.html new file mode 100644 index 0000000..52f925a --- /dev/null +++ b/core/templates/core/graphics_editor.html @@ -0,0 +1,112 @@ +{% extends 'base.html' %} + +{% block content %} +
+

Cipher Shield Graphics

+

Your personal graphics designing software

+ +
+
+

Tools

+
+ + +
+ + +
+ + +
+ + +
+ +
+ + +
+
+ +
+
+
+ + + +{% endblock %} diff --git a/core/templates/core/image_generator.html b/core/templates/core/image_generator.html new file mode 100644 index 0000000..ea36718 --- /dev/null +++ b/core/templates/core/image_generator.html @@ -0,0 +1,47 @@ +{% extends 'base.html' %} +{% load static %} + +{% block content %} +
+
+
+

Cipher Shield: Image Generation

+

Unleash your creativity. Describe the image you want to create, and let our AI bring it to life.

+ +
+
+
+ {% csrf_token %} +
+ +
+ +
+
+
+ +
+ + {% if image_url %} +

Your Masterpiece

+ Generated Image + {% endif %} + {% if error_message %} +
+ {{ error_message }} +
+ {% endif %} +
+ +
+
+
+ + +{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..5db9952 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,57 @@ {% extends "base.html" %} +{% load static %} -{% block title %}{{ project_name }}{% endblock %} +{% block title %}Cipher Shield{% endblock %} {% block head %} +{{ block.super }} - - + + {% endblock %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+
+

Cipher Shield

+

The future of secure social networking.

+
+ +
+
+ {% csrf_token %} + {{ form.as_p }} + +
-

AppWizzy AI is collecting your requirements and applying the first changes.

-

This page will refresh automatically as the plan is implemented.

-

- Runtime: Django {{ django_version }} · Python {{ python_version }} - — UTC {{ current_time|date:"Y-m-d H:i:s" }} -

-
-
- -{% endblock %} \ No newline at end of file + +
+ {% for post in posts %} +
+
+
+
+ {{ post.author.username.0|upper }} +
+
+
+

{{ post.author.username }}

+ +
+

{{ post.created_at|date:"F d, Y, P" }}

+
+
+

{{ post.content }}

+
+
+ {% empty %} +
+

No posts yet. Be the first to share something!

+
+ {% endfor %} +
+ +{% endblock %} diff --git a/core/templates/core/landing_page.html b/core/templates/core/landing_page.html new file mode 100644 index 0000000..484249c --- /dev/null +++ b/core/templates/core/landing_page.html @@ -0,0 +1,29 @@ +{% extends "base.html" %} +{% load static %} + +{% block title %}Super Affiliate AI{% endblock %} + +{% block head %} +{{ block.super }} + + + + +{% endblock %} + +{% block content %} +
+
+

Promote HubSpot

+

The Ultimate All-in-One Platform for Your Business

+
+ +
+
+

Why Promote HubSpot?

+

HubSpot offers a full platform of marketing, sales, customer service, and CRM software — plus the methodology, resources, and support to help businesses grow better. As a HubSpot affiliate, you'll earn a commission on every new customer you refer.

+ Get Started with HubSpot! +
+
+
+{% endblock %} diff --git a/core/templates/core/login.html b/core/templates/core/login.html new file mode 100644 index 0000000..4c204c6 --- /dev/null +++ b/core/templates/core/login.html @@ -0,0 +1,14 @@ +{% extends 'base.html' %} + +{% block content %} +
+
+

Login

+
+ {% csrf_token %} + {{ form.as_p }} + +
+
+
+{% endblock %} diff --git a/core/templates/core/signup.html b/core/templates/core/signup.html new file mode 100644 index 0000000..77c5034 --- /dev/null +++ b/core/templates/core/signup.html @@ -0,0 +1,14 @@ +{% extends 'base.html' %} + +{% block content %} +
+
+

Sign Up

+
+ {% csrf_token %} + {{ form.as_p }} + +
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..65974db 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,18 @@ from django.urls import path +from django.contrib.auth import views as auth_views -from .views import home +from .views import landing_page, social_feed, image_generator, ad_generator, graphics_editor, signup, ai_chat, post_list, post_detail urlpatterns = [ - path("", home, name="home"), + path("", landing_page, name="landing_page"), + path("blog/", post_list, name="post_list"), + path("blog//", post_detail, name="post_detail"), + path("social/", social_feed, name="social_feed"), + path("image-generator/", image_generator, name="image_generator"), + path("ad-generator/", ad_generator, name="ad_generator"), + path("graphics-editor/", graphics_editor, name="graphics_editor"), + path("ai-chat/", ai_chat, name="ai_chat"), + path("signup/", signup, name="signup"), + path("login/", auth_views.LoginView.as_view(template_name="core/login.html"), name="login"), + path("logout/", auth_views.LogoutView.as_view(next_page="login"), name="logout"), ] diff --git a/core/views.py b/core/views.py index c9aed12..76e1764 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,249 @@ +from django.shortcuts import render, redirect, get_object_or_404 + +def landing_page(request): + return render(request, 'core/landing_page.html') +from django.contrib.auth.decorators import login_required +from .models import Post +from .forms import PostForm, SignUpForm +import logging import os -import platform +import json +from django.contrib.auth import login +from ai.local_ai_api import LocalAIApi -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone +logger = logging.getLogger(__name__) + +def signup(request): + if request.method == 'POST': + form = SignUpForm(request.POST) + if form.is_valid(): + user = form.save() + return redirect('social_feed') + else: + form = SignUpForm() + return render(request, 'core/signup.html', {'form': form}) -def home(request): - """Render the landing screen with loader and environment details.""" - host_name = request.get_host().lower() - agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" - now = timezone.now() +def social_feed(request): + if request.method == 'POST': + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + # AI Intent Analysis + try: + content = form.cleaned_data['content'] + prompt = ( + "Analyze the following post and classify its intent into one of " + "the following categories: Neutral, Safe, Caution, Warning. " + "Only return the category name and nothing else." + ) + + response = LocalAIApi.create_response( + { + "input": [ + {"role": "system", "content": prompt}, + {"role": "user", "content": content} + ], + }, + ) + + if response.get("success"): + ai_intent = LocalAIApi.extract_text(response) + if ai_intent in ["Neutral", "Safe", "Caution", "Warning"]: + post.intent = ai_intent + else: + post.intent = "Neutral" + else: + post.intent = "Neutral" + + except Exception as e: + logger.error("Error during AI intent analysis: %s", e) + post.intent = "Neutral" + + post.save() + return redirect('social_feed') + else: + form = PostForm() + + posts = Post.objects.all().order_by('-created_at') context = { - "project_name": "New Style", - "agent_brand": agent_brand, - "django_version": django_version(), - "python_version": platform.python_version(), - "current_time": now, - "host_name": host_name, - "project_description": os.getenv("PROJECT_DESCRIPTION", ""), - "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), + 'posts': posts, + 'form': form, } - return render(request, "core/index.html", context) + return render(request, 'core/index.html', context) + + +def image_generator(request): + if request.method == 'POST': + prompt = request.POST.get('prompt') + + try: + response = LocalAIApi.create_response({ + "input": [ + { + "role": "system", + "content": "You are an AI image generator. Create an image based on the user's prompt." + }, + {"role": "user", "content": prompt} + ], + "model": "dall-e-3", + "parameters": { + "size": "1024x1024" + } + }) + + if response.get("success"): + data = response.get("data", {}) + output = data.get("output", []) + image_url = None + for item in output: + if item.get("type") == "image": + image_url = item.get("url") + break + if image_url: + return render(request, 'core/image_generator.html', {'image_url': image_url}) + else: + error_message = "Image URL not found in the response." + return render(request, 'core/image_generator.html', {'error_message': error_message}) + else: + error_message = response.get("error", "An unknown error occurred.") + return render(request, 'core/image_generator.html', {'error_message': error_message}) + + except Exception as e: + logger.error("Error during image generation: %s", e) + error_message = str(e) + return render(request, 'core/image_generator.html', {'error_message': error_message}) + + return render(request, 'core/image_generator.html') + + +def ad_generator(request): + if request.method == 'POST': + product_name = request.POST.get('product_name') + product_description = request.POST.get('product_description') + target_audience = request.POST.get('target_audience') + + try: + # Generate ad copy + ad_copy_prompt = f"Create a compelling ad copy for a product named '{product_name}'. " \ + f"The product is about: {product_description}. " \ + f"The target audience is {target_audience}." + + ad_copy_response = LocalAIApi.create_response({ + "input": [ + {"role": "system", "content": "You are an expert copywriter."}, + {"role": "user", "content": ad_copy_prompt} + ] + }) + if ad_copy_response.get("success"): + ad_copy = LocalAIApi.extract_text(ad_copy_response) + else: + ad_copy = "Could not generate ad copy." + + # Generate ad image + ad_image_prompt = f"Create a visually appealing image for an ad for '{product_name}'. " \ + f"{product_description}" + + ad_image_response = LocalAIApi.create_response({ + "input": [ + { + "role": "system", + "content": "You are an AI image generator. Create an image for an ad based on the user's prompt." + }, + {"role": "user", "content": ad_image_prompt} + ], + "model": "dall-e-3", + "parameters": { + "size": "1024x1024" + } + }) + + if ad_image_response.get("success"): + data = ad_image_response.get("data", {}) + output = data.get("output", []) + ad_image_url = None + for item in output: + if item.get("type") == "image": + ad_image_url = item.get("url") + break + else: + ad_image_url = "" + + + return render(request, 'core/ad_generator.html', { + 'ad_copy': ad_copy, + 'ad_image_url': ad_image_url, + 'product_name': product_name, + 'product_description': product_description, + 'target_audience': target_audience, + }) + + except Exception as e: + logger.error("Error during ad generation: %s", e) + error_message = str(e) + return render(request, 'core/ad_generator.html', {'error_message': error_message}) + + return render(request, 'core/ad_generator.html') + +def graphics_editor(request): + return render(request, 'core/graphics_editor.html') + + +from django.http import JsonResponse +from django.views.decorators.csrf import csrf_exempt + +@csrf_exempt +def ai_chat(request): + if request.method == 'POST': + prompt = request.POST.get('prompt') + + # Basic validation + if not prompt: + return JsonResponse({'error': 'Prompt is required.'}, status=400) + + try: + conversation = [ + { + "role": "system", + "content": ( + "You are a helpful assistant that can control a web browser. " + "You can perform tasks like navigating to web pages, filling out forms, and clicking on links. " + "When asked to perform a browser action, you should respond with a JavaScript code block to be executed in the browser. " + "The browser is displayed in an iframe, and you can access it using `window.frames[0]`. " + "For example, to navigate to a new page, you can use `window.frames[0].location.href = 'https://www.google.com';`. " + "To click a button, you can use `window.frames[0].document.querySelector('#my-button').click();`. " + "To fill out an input field, you can use `window.frames[0].document.querySelector('#my-input').value = 'my value';`. " + "To get the text content of an element, you can use `window.frames[0].document.querySelector('#my-element').textContent`. " + "If you are not being asked to do a browser action, you can respond with a conversational response." + ) + }, + {"role": "user", "content": prompt} + ] + + response = LocalAIApi.create_response( + { + "input": conversation, + } + ) + + if response.get("success"): + return JsonResponse(response) + else: + error_message = response.get("error", "An unknown error occurred.") + return JsonResponse({'error': error_message}, status=500) + + except Exception as e: + logger.error("Error in ai_chat view: %s", e) + return JsonResponse({'error': str(e)}, status=500) + + return JsonResponse({'error': 'Only POST requests are allowed.'}, status=405) + +def post_list(request): + posts = Post.objects.all().order_by('-created_at') + return render(request, 'core/blog.html', {'posts': posts}) + +def post_detail(request, slug): + post = get_object_or_404(Post, slug=slug) + return render(request, 'core/article_detail.html', {'post': post}) \ No newline at end of file diff --git a/manage.py b/manage.py index 8e7ac79..5dfbe21 100755 --- a/manage.py +++ b/manage.py @@ -2,10 +2,11 @@ """Django's command-line utility for administrative tasks.""" import os import sys - +from dotenv import load_dotenv def main(): """Run administrative tasks.""" + load_dotenv() os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') try: from django.core.management import execute_from_command_line diff --git a/native_app/index.html b/native_app/index.html new file mode 100644 index 0000000..da58aca --- /dev/null +++ b/native_app/index.html @@ -0,0 +1,82 @@ + + + + + + AI Chat + + + +

AI Chat

+
+ + +
+
+
+ + +
+ + + diff --git a/native_app/main.js b/native_app/main.js new file mode 100644 index 0000000..5f3a79f --- /dev/null +++ b/native_app/main.js @@ -0,0 +1,71 @@ +const { app, BrowserWindow, ipcMain, BrowserView } = require('electron'); +const fetch = require('node-fetch'); +const path = require('path'); + +let view; + +function createWindow () { + const win = new BrowserWindow({ + width: 1200, + height: 600, + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + nodeIntegration: true, + contextIsolation: false, + } + }); + + win.loadFile('index.html'); + + view = new BrowserView(); + win.setBrowserView(view); + view.setBounds({ x: 400, y: 0, width: 800, height: 600 }); + view.webContents.loadURL('https://electronjs.org'); +} + +app.whenReady().then(() => { + createWindow(); + + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } + }); +}); + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit(); + } +}); + +ipcMain.on('load-url', (event, url) => { + view.webContents.loadURL(url); +}); + +ipcMain.on('execute-js', (event, code) => { + view.webContents.executeJavaScript(code); +}); + +ipcMain.on('send-message', async (event, message) => { + try { + const response = await fetch('http://127.0.0.1:8000/ai_chat/', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + // Note: You'll need to handle CSRF tokens and authentication if your Django app requires it. + }, + body: `message=${encodeURIComponent(message)}` + }); + + if (response.ok) { + const data = await response.json(); + event.reply('ai-response', data.reply); + } else { + event.reply('ai-response', 'Error: Could not get a response from the AI.'); + } + } catch (error) { + console.error(error); + event.reply('ai-response', 'Error: Could not connect to the AI service.'); + } +}); \ No newline at end of file diff --git a/native_app/package-lock.json b/native_app/package-lock.json new file mode 100644 index 0000000..87e913a --- /dev/null +++ b/native_app/package-lock.json @@ -0,0 +1,917 @@ +{ + "name": "native_app", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "native_app", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "node-fetch": "^2.7.0" + }, + "devDependencies": { + "electron": "^39.2.7" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.19.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz", + "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/electron": { + "version": "39.2.7", + "resolved": "https://registry.npmjs.org/electron/-/electron-39.2.7.tgz", + "integrity": "sha512-KU0uFS6LSTh4aOIC3miolcbizOFP7N1M46VTYVfqIgFiuA2ilfNaOHLDS9tCMvwwHRowAsvqBrh9NgMXcTOHCQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^22.7.7", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/native_app/package.json b/native_app/package.json new file mode 100644 index 0000000..a6f27b9 --- /dev/null +++ b/native_app/package.json @@ -0,0 +1,19 @@ +{ + "name": "native_app", + "version": "1.0.0", + "description": "", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "electron ." + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "electron": "^39.2.7" + }, + "dependencies": { + "node-fetch": "^2.7.0" + } +} diff --git a/native_app/preload.js b/native_app/preload.js new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt index e22994c..9055bc3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ Django==5.2.7 mysqlclient==2.2.7 python-dotenv==1.1.1 +openai==1.3.3 diff --git a/static/css/custom.css b/static/css/custom.css index 925f6ed..6c3a8df 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,4 +1,80 @@ -/* Custom styles for the application */ body { - font-family: system-ui, -apple-system, sans-serif; + background: linear-gradient(to right, #0F2027, #203A43, #2C5364); + font-family: 'Inter', sans-serif; + color: #fff; +} + +.font-poppins { + font-family: 'Poppins', sans-serif; +} + +.font-inter { + font-family: 'Inter', sans-serif; +} + +.glass-card { + background: rgba(255, 255, 255, 0.1); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border-radius: 1rem; + border: 1px solid rgba(255, 255, 255, 0.15); + box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37); +} + +/* Redefine form styles from forms.py to avoid specificity issues */ +.glass-card form .w-full.bg-gray-800 { + background-color: rgba(31, 41, 55, 0.5) !important; + border-color: rgba(55, 65, 81, 0.5) !important; +} + +/* Intent Badge Styles */ +.intent-badge { + width: 10px; + height: 10px; + border-radius: 50%; + margin-left: 8px; + display: inline-block; +} + +.intent-neutral { + background-color: #9CA3AF; /* gray-400 */ +} + +.intent-safe { + background-color: #10B981; /* green-500 */ +} + +.intent-caution { + background-color: #F59E0B; /* yellow-500 */ +} + +.intent-warning { + background-color: #EF4444; /* red-500 */ +} + +/* Image Generator Styles */ +.btn-primary { + background-color: #4A90E2; + border-color: #4A90E2; + transition: background-color 0.3s ease; +} + +.btn-primary:hover { + background-color: #357ABD; + border-color: #357ABD; +} + +.form-control { + background-color: rgba(255, 255, 255, 0.2); + border: none; + color: #fff; +} + +.form-control::placeholder { + color: rgba(255, 255, 255, 0.7); +} + +.card { + background-color: rgba(0,0,0,0.2); + border: none; } diff --git a/staticfiles/css/custom.css b/staticfiles/css/custom.css index 108056f..6c3a8df 100644 --- a/staticfiles/css/custom.css +++ b/staticfiles/css/custom.css @@ -1,21 +1,80 @@ - -:root { - --bg-color-start: #6a11cb; - --bg-color-end: #2575fc; - --text-color: #ffffff; - --card-bg-color: rgba(255, 255, 255, 0.01); - --card-border-color: rgba(255, 255, 255, 0.1); -} body { - margin: 0; + background: linear-gradient(to right, #0F2027, #203A43, #2C5364); font-family: 'Inter', sans-serif; - background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end)); - color: var(--text-color); - display: flex; - justify-content: center; - align-items: center; - min-height: 100vh; - text-align: center; - overflow: hidden; - position: relative; + color: #fff; +} + +.font-poppins { + font-family: 'Poppins', sans-serif; +} + +.font-inter { + font-family: 'Inter', sans-serif; +} + +.glass-card { + background: rgba(255, 255, 255, 0.1); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border-radius: 1rem; + border: 1px solid rgba(255, 255, 255, 0.15); + box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37); +} + +/* Redefine form styles from forms.py to avoid specificity issues */ +.glass-card form .w-full.bg-gray-800 { + background-color: rgba(31, 41, 55, 0.5) !important; + border-color: rgba(55, 65, 81, 0.5) !important; +} + +/* Intent Badge Styles */ +.intent-badge { + width: 10px; + height: 10px; + border-radius: 50%; + margin-left: 8px; + display: inline-block; +} + +.intent-neutral { + background-color: #9CA3AF; /* gray-400 */ +} + +.intent-safe { + background-color: #10B981; /* green-500 */ +} + +.intent-caution { + background-color: #F59E0B; /* yellow-500 */ +} + +.intent-warning { + background-color: #EF4444; /* red-500 */ +} + +/* Image Generator Styles */ +.btn-primary { + background-color: #4A90E2; + border-color: #4A90E2; + transition: background-color 0.3s ease; +} + +.btn-primary:hover { + background-color: #357ABD; + border-color: #357ABD; +} + +.form-control { + background-color: rgba(255, 255, 255, 0.2); + border: none; + color: #fff; +} + +.form-control::placeholder { + color: rgba(255, 255, 255, 0.7); +} + +.card { + background-color: rgba(0,0,0,0.2); + border: none; }