superbrain-server 1.0.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/superbrain.js +196 -0
- package/package.json +23 -0
- package/payload/.dockerignore +45 -0
- package/payload/.env.example +58 -0
- package/payload/Dockerfile +73 -0
- package/payload/analyzers/__init__.py +0 -0
- package/payload/analyzers/audio_transcribe.py +225 -0
- package/payload/analyzers/caption.py +244 -0
- package/payload/analyzers/music_identifier.py +346 -0
- package/payload/analyzers/text_analyzer.py +117 -0
- package/payload/analyzers/visual_analyze.py +218 -0
- package/payload/analyzers/webpage_analyzer.py +789 -0
- package/payload/analyzers/youtube_analyzer.py +320 -0
- package/payload/api.py +1676 -0
- package/payload/config/.api_keys.example +22 -0
- package/payload/config/model_rankings.json +492 -0
- package/payload/config/openrouter_free_models.json +1364 -0
- package/payload/config/whisper_model.txt +1 -0
- package/payload/config_settings.py +185 -0
- package/payload/core/__init__.py +0 -0
- package/payload/core/category_manager.py +219 -0
- package/payload/core/database.py +811 -0
- package/payload/core/link_checker.py +300 -0
- package/payload/core/model_router.py +1253 -0
- package/payload/docker-compose.yml +120 -0
- package/payload/instagram/__init__.py +0 -0
- package/payload/instagram/instagram_downloader.py +253 -0
- package/payload/instagram/instagram_login.py +190 -0
- package/payload/main.py +912 -0
- package/payload/requirements.txt +39 -0
- package/payload/reset.py +311 -0
- package/payload/start-docker-prod.sh +125 -0
- package/payload/start-docker.sh +56 -0
- package/payload/start.py +1302 -0
- package/payload/static/favicon.ico +0 -0
- package/payload/stop-docker.sh +16 -0
- package/payload/utils/__init__.py +0 -0
- package/payload/utils/db_stats.py +108 -0
- package/payload/utils/manage_token.py +91 -0
|
Binary file
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# SuperBrain Docker Stop Script
|
|
4
|
+
|
|
5
|
+
echo "š Stopping SuperBrain..."
|
|
6
|
+
|
|
7
|
+
# Use docker compose if available, otherwise docker-compose
|
|
8
|
+
if command -v docker compose &> /dev/null; then
|
|
9
|
+
DOCKER_COMPOSE="docker compose"
|
|
10
|
+
else
|
|
11
|
+
DOCKER_COMPOSE="docker-compose"
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
$DOCKER_COMPOSE down
|
|
15
|
+
|
|
16
|
+
echo "ā
SuperBrain stopped."
|
|
File without changes
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
SQLite Database Statistics
|
|
4
|
+
Shows storage usage, document count, and collection info
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
# Ensure backend root is in sys.path (needed when run directly)
|
|
11
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
12
|
+
|
|
13
|
+
from core.database import get_db
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def format_bytes(bytes_size):
|
|
17
|
+
"""Convert bytes to human-readable format"""
|
|
18
|
+
for unit in ['B', 'KB', 'MB', 'GB']:
|
|
19
|
+
if bytes_size < 1024.0:
|
|
20
|
+
return f"{bytes_size:.2f} {unit}"
|
|
21
|
+
bytes_size /= 1024.0
|
|
22
|
+
return f"{bytes_size:.2f} TB"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_database_stats():
|
|
26
|
+
"""Get comprehensive database statistics"""
|
|
27
|
+
|
|
28
|
+
print("=" * 80)
|
|
29
|
+
print("š SUPERBRAIN DATABASE STATISTICS (SQLite)")
|
|
30
|
+
print("=" * 80)
|
|
31
|
+
print()
|
|
32
|
+
|
|
33
|
+
db = get_db()
|
|
34
|
+
|
|
35
|
+
if not db.is_connected():
|
|
36
|
+
print("ā Not connected to database")
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
stats = db.get_stats()
|
|
41
|
+
doc_count = stats['document_count']
|
|
42
|
+
storage_mb = stats['storage_mb']
|
|
43
|
+
category_counts = stats['categories']
|
|
44
|
+
storage_bytes = storage_mb * 1024 * 1024
|
|
45
|
+
|
|
46
|
+
# āā Storage āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
47
|
+
print("š¾ STORAGE USAGE")
|
|
48
|
+
print("-" * 80)
|
|
49
|
+
print(f"Database file: {db.db_path}")
|
|
50
|
+
print(f"File size: {format_bytes(storage_bytes)}")
|
|
51
|
+
print(f"Storage (MB): {storage_mb} MB")
|
|
52
|
+
print()
|
|
53
|
+
|
|
54
|
+
# āā Documents āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
55
|
+
print("š DOCUMENT INFORMATION")
|
|
56
|
+
print("-" * 80)
|
|
57
|
+
print(f"Total Posts: {doc_count}")
|
|
58
|
+
if doc_count > 0 and storage_bytes > 0:
|
|
59
|
+
print(f"Average Post Size: {format_bytes(storage_bytes / doc_count)}")
|
|
60
|
+
print()
|
|
61
|
+
|
|
62
|
+
# āā Schema āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
63
|
+
print("š COLUMNS IN analyses TABLE")
|
|
64
|
+
print("-" * 80)
|
|
65
|
+
columns = [
|
|
66
|
+
"shortcode", "url", "username", "analyzed_at", "updated_at",
|
|
67
|
+
"post_date", "likes", "title", "summary", "tags",
|
|
68
|
+
"music", "category", "visual_analysis", "audio_transcription", "text_analysis"
|
|
69
|
+
]
|
|
70
|
+
for i, col in enumerate(columns, 1):
|
|
71
|
+
print(f"{i:2}. {col}")
|
|
72
|
+
print()
|
|
73
|
+
|
|
74
|
+
# āā Categories āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
75
|
+
print("š CATEGORY BREAKDOWN")
|
|
76
|
+
print("-" * 80)
|
|
77
|
+
if category_counts:
|
|
78
|
+
for name, count in sorted(category_counts.items(), key=lambda x: -x[1]):
|
|
79
|
+
print(f"{name:<20} {count:>5} posts")
|
|
80
|
+
else:
|
|
81
|
+
print("No posts yet")
|
|
82
|
+
print()
|
|
83
|
+
|
|
84
|
+
# āā Recent āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
85
|
+
print("š
RECENT POSTS (Last 5)")
|
|
86
|
+
print("-" * 80)
|
|
87
|
+
recent = db.get_recent(5)
|
|
88
|
+
if recent:
|
|
89
|
+
for i, doc in enumerate(recent, 1):
|
|
90
|
+
title = (doc.get('title') or 'No title')[:50]
|
|
91
|
+
date = doc.get('analyzed_at', 'Unknown')
|
|
92
|
+
category = doc.get('category', 'N/A')
|
|
93
|
+
print(f"{i}. [{category}] {title}")
|
|
94
|
+
print(f" Analyzed: {date}")
|
|
95
|
+
else:
|
|
96
|
+
print("No posts yet")
|
|
97
|
+
|
|
98
|
+
print()
|
|
99
|
+
print("=" * 80)
|
|
100
|
+
|
|
101
|
+
except Exception as e:
|
|
102
|
+
print(f"ā Error getting stats: {e}")
|
|
103
|
+
import traceback
|
|
104
|
+
traceback.print_exc()
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
get_database_stats()
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SuperBrain API Token Manager
|
|
3
|
+
Manage your API authentication token
|
|
4
|
+
"""
|
|
5
|
+
import sys
|
|
6
|
+
import os
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
import secrets
|
|
9
|
+
import string
|
|
10
|
+
|
|
11
|
+
TOKEN_FILE = Path(__file__).parent.parent / "token.txt"
|
|
12
|
+
|
|
13
|
+
def generate_token(length=8):
|
|
14
|
+
"""Generate an 8-character alphanumeric Access Token"""
|
|
15
|
+
alphabet = string.ascii_uppercase + string.digits
|
|
16
|
+
return ''.join(secrets.choice(alphabet) for _ in range(length))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def is_valid_token(token: str) -> bool:
|
|
20
|
+
"""Validate token format: exactly 8 alphanumeric characters."""
|
|
21
|
+
return len(token) == 8 and token.isalnum()
|
|
22
|
+
|
|
23
|
+
def load_token():
|
|
24
|
+
"""Load existing token"""
|
|
25
|
+
if TOKEN_FILE.exists():
|
|
26
|
+
with open(TOKEN_FILE, 'r') as f:
|
|
27
|
+
return f.read().strip()
|
|
28
|
+
return None
|
|
29
|
+
|
|
30
|
+
def save_token(token):
|
|
31
|
+
"""Save token to file"""
|
|
32
|
+
with open(TOKEN_FILE, 'w') as f:
|
|
33
|
+
f.write(token)
|
|
34
|
+
print(f"\nā
Token saved to: {TOKEN_FILE}")
|
|
35
|
+
|
|
36
|
+
def main():
|
|
37
|
+
print("\n" + "="*80)
|
|
38
|
+
print("š SuperBrain Access Token Manager")
|
|
39
|
+
print("="*80)
|
|
40
|
+
|
|
41
|
+
current_token = load_token()
|
|
42
|
+
|
|
43
|
+
if current_token:
|
|
44
|
+
print(f"\nš Current Token: {current_token}")
|
|
45
|
+
else:
|
|
46
|
+
print("\nā ļø No token found!")
|
|
47
|
+
|
|
48
|
+
print("\nOptions:")
|
|
49
|
+
print(" 1. Generate new random token")
|
|
50
|
+
print(" 2. Set custom token")
|
|
51
|
+
print(" 3. View current token")
|
|
52
|
+
print(" 4. Exit")
|
|
53
|
+
|
|
54
|
+
choice = input("\nEnter choice (1-4): ").strip()
|
|
55
|
+
|
|
56
|
+
if choice == "1":
|
|
57
|
+
new_token = generate_token()
|
|
58
|
+
save_token(new_token)
|
|
59
|
+
print(f"\nš New Token: {new_token}")
|
|
60
|
+
print("\nš” Use this in API requests:")
|
|
61
|
+
print(f" Header: X-API-Key: {new_token}")
|
|
62
|
+
print("\nā ļø Restart the API server for changes to take effect!")
|
|
63
|
+
|
|
64
|
+
elif choice == "2":
|
|
65
|
+
custom_token = input("\nEnter custom 8-character token: ").strip().upper()
|
|
66
|
+
if not is_valid_token(custom_token):
|
|
67
|
+
print("\nā Invalid token! Use exactly 8 alphanumeric characters.")
|
|
68
|
+
return
|
|
69
|
+
save_token(custom_token)
|
|
70
|
+
print(f"\nš Token set to: {custom_token}")
|
|
71
|
+
print("\nā ļø Restart the API server for changes to take effect!")
|
|
72
|
+
|
|
73
|
+
elif choice == "3":
|
|
74
|
+
if current_token:
|
|
75
|
+
print(f"\nš Current Token: {current_token}")
|
|
76
|
+
print("\nš” Use in API requests:")
|
|
77
|
+
print(f" Header: X-API-Key: {current_token}")
|
|
78
|
+
else:
|
|
79
|
+
print("\nā ļø No token found!")
|
|
80
|
+
|
|
81
|
+
elif choice == "4":
|
|
82
|
+
print("\nš Goodbye!")
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
else:
|
|
86
|
+
print("\nā Invalid choice!")
|
|
87
|
+
|
|
88
|
+
print("\n" + "="*80 + "\n")
|
|
89
|
+
|
|
90
|
+
if __name__ == "__main__":
|
|
91
|
+
main()
|