Skip to content

Commit

Permalink
add hub settings + prepare for generation 2
Browse files Browse the repository at this point in the history
- set generation, query_level for hub
- move many files to prepare for generation 2
- teacher can set default generation for new hubs
- clean up sql views
- add sql.ai view but only for "sponsors"
  • Loading branch information
wi-wissen committed Jul 10, 2024
1 parent 8dcffc6 commit c1e396f
Show file tree
Hide file tree
Showing 1,670 changed files with 879 additions and 1,870 deletions.
8 changes: 7 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ APP_MAINTENANCE_STORE=database

APP_COPYRIGHT=wi-wissen.de

DOC_URL=https://wi-wissen.github.io/instahub-doc-de/
HUB_DEFAULT_GENERATION=1
HUB_DOC_1_URL=https://wi-wissen.github.io/instahub-doc-de/

BCRYPT_ROUNDS=12

Expand Down Expand Up @@ -55,6 +56,11 @@ MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="[email protected]"
MAIL_FROM_NAME="${APP_NAME}"

AZURE_RESOURCE_NAME=
AZURE_DEPLOYMENT_ID=
AZURE_OPENAI_KEY=
AZURE_VERSION=2024-02-01

VITE_APP_NAME="${APP_NAME}"

WORD=achatgrau,ahornrot,agavengruen,alaskagrau,alpinaweiss,altrosa,aluminiumgrau,amarant,amarantrot,amazonasgruen,ameisenrot,ananasgelb,anthrazit,anthrazitgrau,antikgelb,antikrot,antiktuerkis,antikweiss,apfelgruen,aquamarin,aquamarinblau,asphaltgrau,atlantikblau,atlantisblau,azorenblau,azurblau,ballettrosa,bananengelb,basaltgrau,beige,beigerot,betongrau,birkengruen,blattgruen,blau,bleigrau,bluescreenblau,blutorange,blutrot,braun,braunbeige,braunrot,brillantblau,brombeerrot,bronze,burgunderrot,cappuccino,capriblau,carrerarot,cayennerot,cherry,chromgelb,creepergruen,cremeweiss,currygelb,cyan,dahliengelb,delphinblau,diamantblau,diamantgruen,diamantrot,diamantschwarz,dunkelblau,dunkelbraun,dunkelgelb,dunkelgrau,dunkelgruen,dunkellila,dunkelrosa,dunkelrot,eisblau,eisengrau,elefantengrau,elfenbein,enzianblau,erdbeerrot,erikarot,espressobraun,estorilblau,farblos,farngruen,fehengrau,fenstergrau,feuerrot,flamingorosa,flamingorot,flaschengruen,flieder,froschgruen,fruehlingsgruen,fuchsienrot,gelb,gelbgruen,gelblich,gelborange,geraniumrot,giftgruen,gilblich,ginstergelb,gletscherblau,gold,goldbraun,golden,goldgelb,granitgrau,graphitgrau,grasgruen,grau,graubeige,gruen,gruenbeige,gruenlich,guelden,haselnussbraun,heidelbeerblau,hellblau,hellbraun,hellelfenbein,hellgelb,hellgrau,hellgruen,hellrosa,hellrot,hellrotorange,himbeerrot,himmelblau,honiggelb,hummerrot,indianerrot,indigo,indigoblau,indigorot,indischgelb,indischrot,infernorot,inkarnat,italienischrot,jadegruen,jerichorot,johannisbeerrot,kadmiumgelb,kaffeebraun,kamillengelb,kanariengelb,karamellbraun,kardinalrot,karibikblau,karminrot,karminrot,kastanienbraun,kieferngruen,kieselgrau,kirschrot,kiwigruen,khakigrau,khakigruen,kobaltblau,kobaltgruen,koenigsblau,korallenrosa,korallenrot,kornblumenblau,koronagelb,kosmosschwarz,kupferrot,lachsorange,lachsrosa,lachsrot,laubgruen,lavendelblau,lehmbraun,lemongruen,leuchtgelb,leuchthellorange,leuchthellrot,leuchtorange,leuchtrot,lichtblau,lila,limonengruen,lindgruen,lotusrot,magenta,magnolienrosa,magnolienrot,mahagonibraun,mahagonirot,maigruen,maisgelb,marmor,mandelbraun,marineblau,mauritiusblau,mausgrau,meeresgruen,melonengelb,mintgruen,mohnrot,moosgrau,moosgruen,nachtblau,narzissengelb,neapelgelb,neonblau,neongelb,neongruen,neonlila,neonorange,neonpink,neonrosa,neonrot,neontuerkis,neonviolett,nougatbraun,nussbraun,ocker,ockerbraun,ockergelb,ockerrot,olivgelb,olivgrau,olivgruen,orange,orangegelb,orangerot,orchidee,orientrot,oxidrot,ozeanblau,papageirot,paprikarot,papyrus,papyrusweiss,pastell,pastellgelb,pastellorange,patinagruen,pazifikblau,pechrabenschwarz,perlbeige,perlgold,perlgrau,perlorange,perlrosa,perlrubinrot,perlweiss,permamentrosa,permamentrot,persischrot,petrol,pfirsichrot,pigmentgruen,pink,pistaziengruen,platingrau,plazentarot,porzellanblau,pflaumenblau,pumucklrot,purpur,purpurlila,purpurrot,quarzgrau,quittegelb,quittengelb,rapsgelb,rehbraun,reinorange,reinrot,resedagruen,rhabarberrot,rindenbraun,ringelblumengelb,rosa,rosenrosa,rosenrot,rosig,rostbraun,rostrot,rot,rotorange,royalblau,rubinrot,safrangelb,safranrot,saharagelb,sandgelb,sandgelb,sandsteinrot,saphirblau,scharlachrot,schiefergrau,schilfgruen,schneeweiss,schokoladenbraun,schwarz,schwarzbraun,schwarzrot,schwefelgelb,seegruen,seidengrau,sepiabraun,siena,sienabraun,signalgelb,signalorange,signalrot,silber,silbergrau,silbrig,smalteblau,smaragdgruen,sonnengelb,stahlblau,staubgrau,suedseeblau,steingrau,tabakbraun,tannengruen,taubenblau,terrabraun,terracotta,tieforange,tiefschwarz,tintenblau,tintenrot,tintenschwarz,titangrau,tizianrot,tomatenrot,torfbraun,tumblau,tuerkis,tuerkischrot,umbra,universalblau,ultramarinblau,veilchenblau,venezianischrot,violett,walnussbraun,wasserblau,weinrot,weiss,wiesengruen,wuestenrot,xenon,zartgruen,zartrosa,zeltgrau,zementgrau,ziegelrot,zimtbraun,zinkgelb,zinnoberrot,zitronengelb,zitrusgelb,zyan
Expand Down
18 changes: 18 additions & 0 deletions app/Helpers/HubHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,24 @@ public function name()
}
}

public function generation()
{
if ($this->isHub()) {
return $this->hub->generation;
} else {
return null;
}
}

public function query_level()
{
if ($this->isHub()) {
return $this->hub->query_level;
} else {
return null;
}
}

public function url($name = null)
{
$protocol = $_SERVER['PROTOCOL'] = isset($_SERVER['HTTPS']) && ! empty($_SERVER['HTTPS']) ? 'https' : 'http';
Expand Down
26 changes: 17 additions & 9 deletions app/Http/Controllers/FileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ public function showPhoto($filename)
{
$entry = Photo::where('url', '=', 'photos/'.$filename)->firstOrFail();

//$this->authorize('view', $entry);
$url = $entry->url;
if (strpos($url, '_960') == false || strpos($url, '-unsplash') == false) {
$url = 'photos/generation_1/'.$filename; // legacy support
}

if (Storage::disk('local')->exists($entry->url)) {
$file = Storage::disk('local')->get($entry->url);
if (Storage::disk('local')->exists($url)) {
$file = Storage::disk('local')->get($url);

return (new Response($file, 200))
->header('Content-Type', Storage::mimeType($entry->url))
->header('Content-Type', Storage::mimeType($url))
->header('Content-Disposition', 'attachment; filename="'.'photo'.'"');
} else {
abort(404);
Expand All @@ -53,10 +56,15 @@ public function showAvatar($filename)

$user = User::where('avatar', '=', 'avatars/'.$filename)->firstOrFail();

$file = Storage::disk('local')->get($user->avatar);
$avatar = $user->avatar;
if (preg_match('/^(\d{3})\.jpg$/', $filename) && intval($filename) <= 196) {
$avatar = 'avatars/generation_1/'.$filename; // legacy support
}

$file = Storage::disk('local')->get($avatar);

return (new Response($file, 200))
->header('Content-Type', Storage::mimeType($user->avatar))
->header('Content-Type', Storage::mimeType($avatar))
->header('Content-Disposition', 'attachment; filename="'.$user->username.'"');
}

Expand All @@ -70,10 +78,10 @@ public function destroyAvatar($filename)
{
$user = User::where('avatar', '=', 'avatars/'.$filename)->firstOrFail();

$preset_avatars = ['000.jpg', '001.jpg', '002.jpg', '003.jpg', '004.jpg', '005.jpg', '006.jpg', '007.jpg', '008.jpg', '009.jpg', '010.jpg', '011.jpg', '012.jpg', '013.jpg', '014.jpg', '015.jpg', '016.jpg', '017.jpg', '018.jpg', '019.jpg', '020.jpg', '021.jpg', '022.jpg', '023.jpg', '024.jpg', '025.jpg', '026.jpg', '027.jpg', '028.jpg', '029.jpg', '030.jpg', '031.jpg', '032.jpg', '033.jpg', '034.jpg', '035.jpg', '036.jpg', '037.jpg', '038.jpg', '039.jpg', '040.jpg', '041.jpg', '042.jpg', '043.jpg', '044.jpg', '045.jpg', '046.jpg', '047.jpg', '048.jpg', '049.jpg', '050.jpg', '051.jpg', '052.jpg', '053.jpg', '054.jpg', '055.jpg', '056.jpg', '057.jpg', '058.jpg', '059.jpg', '060.jpg', '061.jpg', '062.jpg', '063.jpg', '064.jpg', '065.jpg', '066.jpg', '067.jpg', '068.jpg', '069.jpg', '070.jpg', '071.jpg', '072.jpg', '073.jpg', '074.jpg', '075.jpg', '076.jpg', '077.jpg', '078.jpg', '079.jpg', '080.jpg', '081.jpg', '082.jpg', '083.jpg', '084.jpg', '085.jpg', '086.jpg', '087.jpg', '088.jpg', '089.jpg', '090.jpg', '091.jpg', '092.jpg', '093.jpg', '094.jpg', '095.jpg', '096.jpg', '097.jpg', '098.jpg', '099.jpg', '100.jpg', '101.jpg', '102.jpg', '103.jpg', '104.jpg', '105.jpg', '106.jpg', '107.jpg', '108.jpg', '109.jpg', '110.jpg', '111.jpg', '112.jpg', '113.jpg', '114.jpg', '115.jpg', '116.jpg', '117.jpg', '118.jpg', '119.jpg', '120.jpg', '121.jpg', '122.jpg', '123.jpg', '124.jpg', '125.jpg', '126.jpg', '127.jpg', '128.jpg', '129.jpg', '130.jpg', '131.jpg', '132.jpg', '133.jpg', '134.jpg', '135.jpg', '136.jpg', '137.jpg', '138.jpg', '139.jpg', '140.jpg', '141.jpg', '142.jpg', '143.jpg', '144.jpg', '145.jpg', '146.jpg', '147.jpg', '148.jpg', '149.jpg', '150.jpg', '151.jpg', '152.jpg', '153.jpg', '154.jpg', '155.jpg', '156.jpg', '157.jpg', '158.jpg', '159.jpg', '160.jpg', '161.jpg', '162.jpg', '163.jpg', '164.jpg', '165.jpg', '166.jpg', '167.jpg', '168.jpg', '169.jpg', '170.jpg', '171.jpg', '172.jpg', '173.jpg', '174.jpg', '175.jpg', '176.jpg', '177.jpg', '178.jpg', '179.jpg', '180.jpg', '181.jpg', '182.jpg', '183.jpg', '184.jpg', '185.jpg', '186.jpg', '187.jpg', '188.jpg', '189.jpg', '190.jpg', '191.jpg', '192.jpg', '193.jpg', '194.jpg', '195.jpg', '196.jpg'];
$isPresetAvatar = preg_match('/^(\d{3})\.jpg$/', $filename) && intval($filename) <= 196;

if (! in_array($filename, $preset_avatars)) {
//uploaded avater
if (!$isPresetAvatar) {
// uploaded avatar
return Storage::disk('local')->delete($user->avatar);
}
}
Expand Down
17 changes: 10 additions & 7 deletions app/Http/Controllers/HubController.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,16 @@ function ($attribute, $value, $fail) {

RequestHub::setHubDB($hub->id);

DB::statement('SET FOREIGN_KEY_CHECKS = 0');
Schema::dropIfExists('users'); //not necesary but sometimes happend strage bug while registering..
DB::statement('SET FOREIGN_KEY_CHECKS = 1');

Artisan::call('migrate', ['--path' => 'database/migrations/create/users', '--force' => true]);
Artisan::call('db:seed', ['--class' => 'UsersTableSeeder', '--force' => true]);
Schema::dropIfExists('migrations'); //sorry laravel, but thats the only way.
// hydrate hub
if(Auth::user()->hub_default_creating == 'users') {
$hub->changeTables(['users'], 'users');
}
else if(Auth::user()->hub_default_creating == 'all_empty') {
$hub->changeTables(['users'], 'create');
}
else if(Auth::user()->hub_default_creating == 'all_full') {
$hub->changeTables(['users','photos','tags','likes','follows','comments','analytics','ads'], 'fill');
}

//insert admin
$url = 'avatar.png';
Expand Down
14 changes: 14 additions & 0 deletions app/Http/Controllers/SqlController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Http\Controllers;

use App\Facades\RequestHub;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
Expand All @@ -21,6 +22,19 @@ public function sql()

public function selectGui()
{
if(RequestHub::query_level() != 'gui' && RequestHub::query_level() != 'ai') {
abort(403);
}

return view('admin.select');
}

public function sqlAi()
{
if(RequestHub::query_level() != 'ai') {
abort(403);
}

return view('admin.ai');
}
}
64 changes: 21 additions & 43 deletions app/Livewire/Admin/Sql.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ class Sql extends Component
public $result = '';
public $tables = '';
public $message = null;
public $type = null;
public $results = [];


public function mount()
{
Expand All @@ -30,61 +31,38 @@ public function runQuery()
{
$this->result = '';
$this->message = null;
$this->type = null;

try {
if (strpos(strtolower(trim($this->query)), 'select') !== 0) {
DB::statement($this->query);
$this->message = 'Anfrage ausgeführt.';
$this->type = 'success';
$this->message = [
'type' => 'success',
'text' => __('Query executed.'),
];
} else {
$r = DB::select($this->query);
if (!$r) {
$this->message = __('Query executed. 0 results found.');
$this->type = 'warning';
$this->results = DB::select($this->query);
if (! $this->results) {
$this->message = [
'type' => 'warning',
'text' => __('Query executed. 0 results found.'),
];
} else {
$this->message = __('Query executed successfully. :count results found.', ['count' => count($r)]);
$this->type = 'success';
$this->result = $this->formatResult($r);
$this->message = [
'type' => 'success',
'text' => __('Query executed successfully. :count results found.', ['count' => count($this->results)])
];
}
}
} catch (QueryException $ex) {
$this->message = $ex->getMessage();
$this->type = 'danger';
} catch (QueryException $e) {
$this->message = [
'type' => 'danger',
'text' => $e->getMessage()
];
}

session(['last_query' => $this->query]);
}

private function formatResult($r)
{
$cols = array_keys((array) $r[0]);
$t = "<table class='table mb-0'>";
$t .= "<thead><tr>";
foreach ($cols as $col) {
$t .= "<th>" . htmlspecialchars($col) . "</th>";
}
$t .= "</tr></thead><tbody>";
foreach ($r as $row) {
$t .= "<tr>";
foreach ($cols as $col) {
$value = $row->$col;
if ($value === null) {
$t .= "<td><code>NULL</code></td>";
} elseif (filter_var($value, FILTER_VALIDATE_URL)) {
$t .= "<td><a href='" . htmlspecialchars($value) . "'>" . htmlspecialchars($value) . "</a></td>";
} elseif (preg_match("/^.*\.(jpg|jpeg|png|gif)$/i", $value)) {
$t .= "<td><a href='/" . htmlspecialchars($value) . "'>" . htmlspecialchars($value) . "</a></td>";
} else {
$t .= "<td>" . htmlspecialchars($value) . "</td>";
}
}
$t .= "</tr>";
}
$t .= "</tbody></table>";
return $t;
}

private function loadTables()
{
$r = DB::table('information_schema.tables')->where('table_schema', DB::getDatabaseName())->get();
Expand Down
150 changes: 150 additions & 0 deletions app/Livewire/Admin/SqlAi.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<?php

namespace App\Livewire\Admin;

use Livewire\Component;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use OpenAI;
use Throwable;

class SqlAi extends Component
{
public $prompt = '';
public $query = '';
public $result = '';
public $tables = '';
public $message = null;
public $results = [];

public function mount()
{
$this->prompt = session('last_prompt', '');
$this->loadTables();
}

public function render()
{
return view('livewire.admin.sql-ai');
}

public function runQuery()
{
$this->result = '';
$this->message = null;

if(! $this->prompt) {
return;
}

try {
$client = OpenAI::factory()
->withBaseUri(config('azure.resource_name').'.openai.azure.com/openai/deployments/'.config('azure.deployment_id'))
->withHttpHeader('api-key', config('azure.openai_key'))
->withQueryParam('api-version', config('azure.api_version'))
->make();

$result = $client->chat()->create([
'messages' => [
['role' => 'system', 'content' => $this->buildSystemPrompt()],
['role' => 'user', 'content' => $this->prompt],
],
'max_tokens' => 100,
]);

$this->query = $this->extractSQL($result->choices[0]->message->content);

if($this->query == 'UNKNOWN') {
$this->message = [
'type' => 'danger',
'text' => __('The input cannot be implemented with a database query.'),
];

return;
}
} catch (Throwable $e) {
$this->message = [
'type' => 'danger',
'text' => (config('app.debug')) ? $e->getMessage() : __('Error in the AI query.'),
];

return;
}

try {
if (strpos(strtolower(trim($this->query)), 'select') !== 0) {
DB::statement($this->query);
$this->message = [
'type' => 'success',
'text' => __('Query executed.'),
];
} else {
$this->results = DB::select($this->query);
if (! $this->results) {
$this->message = [
'type' => 'warning',
'text' => __('Query executed. 0 results found.'),
];
} else {
$this->message = [
'type' => 'success',
'text' => __('Query executed successfully. :count results found.', ['count' => count($this->results)])
];
}
}
} catch (QueryException $e) {
$this->message = [
'type' => 'danger',
'text' => $e->getMessage()
];
}

session(['last_prompt' => $this->prompt]);
}

private function buildSystemPrompt()
{
$command = <<<'EOT'
Du bist ein SQL-Generator. Du antwortest ausschließlich in gültigen SQL.
Der Nutzer hat eine Aufgabe, die sich mit SQL Lösen lässt. Andernfalls schreibe nur UNKNOWN
Folgende einzelne Tabellen können abgefragt werden:
EOT;

return $command . '\n' . $this->loadTables();
}

private function loadTables()
{
$r = DB::table('information_schema.tables')->where('table_schema', DB::getDatabaseName())->get();
$dbclass = '';
foreach ($r as $v) {
if (!strcmp($v->TABLE_TYPE, 'BASE TABLE') && $v->TABLE_NAME != 'migrations') {
$dbclass .= $v->TABLE_NAME . ': ';
$columns = Schema::getColumnListing($v->TABLE_NAME);
$dbclass .= implode(', ', $columns);
$dbclass .= '\n';
}
}
$this->tables = $dbclass;
}

private function extractSQL($input) {
// Entferne Leerzeichen am Anfang und Ende
$input = trim($input);

// Prüfe, ob der Input mit Markdown-Codeblock-Syntax beginnt
if (preg_match('/^```sql\s*(.*?)\s*```$/s', $input, $matches)) {
// Extrahiere den SQL-Code aus dem Markdown-Codeblock
return trim($matches[1]);
} elseif (preg_match('/^```\s*(.*?)\s*```$/s', $input, $matches)) {
// Für den Fall, dass 'sql' nach '```' fehlt, aber es trotzdem ein Codeblock ist
return trim($matches[1]);
} else {
// Wenn kein Markdown-Codeblock gefunden wurde, gib den gesamten Input zurück
return $input;
}
}
}
Loading

0 comments on commit c1e396f

Please sign in to comment.