This commit is contained in:
HolgerHatGarKeineNode
2023-04-25 23:09:21 +02:00
parent 5a4322b035
commit ed54b25567
32 changed files with 683 additions and 12 deletions

213
app/CodeIsSpeech.php Normal file
View File

@@ -0,0 +1,213 @@
<?php
namespace App;
use App\Models\BitcoinEvent;
use App\Models\Course;
use App\Models\LibraryItem;
use App\Models\MeetupEvent;
use App\Models\OrangePill;
use App\Models\User;
use Illuminate\Support\Facades\Http;
trait CodeIsSpeech
{
public function bookCasesHighScoreTable()
{
$firstUser = User::query()
->withCount('orangePills')
->orderByDesc('orange_pills_count')
->first();
return sprintf("
Derzeit liegt %s ganz vorne in der Highscore-Tabelle.
Er oder sie hat sage und schreibe %s Bücher in Schränke gestellt.
",
$firstUser->name,
$firstUser->orange_pills_count
);
}
public function bookCasesCommentBookcase()
{
return sprintf("
%s ist ein cooler Bittcoiner und hat ein Buch in einen Schrank gestellt.
Finde den Schrank mit Hilfe der Karte und trage auch deine Buch-Eingabe hier ein.
Gehe auf die Highscore-Tabelle um zu sehen, wer die meisten Bücher in Schränke gestellt hat.
",
$this->bookCase->orangePills->first()->user->name
);
}
public function bookCasesWorld()
{
return sprintf("
Hier siehst du die Anzahl der Bücherschranke-Einträge und auch die Anzahl der Bittcoiner, die ein Buch in ein Regal gestellt haben.
Auf der Weltkarte kannst du sehen, welche Regale noch kein Buch haben.
Diese Regale sind gräulich gefärbt.
Regale in oransch haben bereits ein Buch.
Es kann jedoch sein, dass das Buch schon eine lange Reise hinter sich hat und ganz wo anders auf der Welt zu finden ist.
Wenn du auf einen Marker klickst gelangst du zu den Details des Regals.
Derzeit haben %s Bittcoiner %s Bücher in Regale eingestellt.
",
User::query()
->whereHas('orangePills')
->count(),
OrangePill::query()
->count()
);
}
public function bitcoinEventTableBitcoinEvent()
{
return sprintf("
Alle Termine für Bitcoin-Ivents werden hier angezeigt.
Finde einen Termin, der dir passt und klicke auf den 'Link', um zu den Details zu gelangen.
Die Termine haben eine Flagge, die das Land anzeigt, in dem das Event stattfindet.
",
);
}
public function libraryTableLibraryItems()
{
return sprintf("
Du kannst in unserer Bibliothek nach Themen suchen, die dich interessieren.
Tippe einen Suchbegriff ein oder wähle einen Schlagwort aus, um die Ergebnisse zu filtern.
Wenn du selbst eigene interessante Artikel oder Bibliotheks-Einträge eingeben möchtest, musst du eingeloggt sein.
Klicke auf 'Inhalte eintragen' und fülle das Formular aus.
So wird die Bibliothek immer besser und du kannst die Inhalte mit anderen teilen.
",
);
}
public function schoolTableEvent()
{
$filterId = null;
if (isset($this->getAppliedFilters()['course_id'])) {
$filterId = $this->getAppliedFilters()['course_id'];
} else {
return;
}
$course = Course::query()
->with(['lecturer'])
->find($filterId);
return sprintf("
Du hast den Kurs '%s' von %s gefiltert.
Finde hier einen Termin, der dir passt und klicke auf 'Registrieren', um zu den Details zu gelangen.
Auf der Karte findest du weitere Kurse, die in deiner Nähe stattfinden.
Klicke einen Marker um die Filterung nach Terminen zu ändern.
",
$course->name,
$course->lecturer->name
);
}
public function schoolTableCourse()
{
return sprintf("
Du bist auf der Übersichts-Seite der Kurse.
Finde hier ein Themen-Gebiet, das dich interessiert und klicke auf den Link, um zu den Terminen zu gelangen.
",
);
}
public function meetupLanding()
{
return sprintf("
Du bist auf der Mietap Seite von %s.
Suche dir einen Termin aus und freue dich auf ein Treffen mit Gleichgesinnten oder einfach nur auf einen gemütlichen Abend.
Wenn ein Mietap Termin fehlt, dann logge dich im System ein und wähle deine Mietaps unter 'Meine Meetups' aus, um einen neuen Termin anzulegen.
",
$this->meetup->name,
);
}
public function meetupWorld()
{
return sprintf("
Du bist auf der Mietap Weltkarte von Einundzwanzig.
Suche dir ein Land aus und klicke auf den Marker, um zu einem Mietap zu gelangen.
Wenn ein Mietap fehlt, dann logge dich im System ein und lege ein neues Mietap an.
");
}
public function profileLnbits()
{
return sprintf("
Setze hier die Einstellungen für deine LN Bitts Wollet. Bitte verwende deine eigene Instanz von LN Bitts, die auf deiner eigenen Bitcoin Nod installiert ist.
");
}
public function articleView(): string
{
return str(strip_tags($this->libraryItem->value))
->stripTags()
->words(255, '')
->toString();
}
public function articleOverview()
{
$tip = Http::get('https://mempool.space/api/blocks/tip/height');
$fees = Http::get('https://mempool.space/api/v1/fees/recommended')
->json();
$createText = "Um einen Artikel zu schreiben, klicke auf den 'Artikel einreichen' Link oder um einen bezahlten Artikel zu schreiben, klicke auf 'Reiche einen bezahlten News-Artikel ein'.";
if (auth()->check() && !auth()->user()->lnbits['read_key']) {
$createText = "Um einen Artikel zu schreiben, klicke auf den 'Artikel einreichen' Link oder um einen bezahlten Artikel zu schreiben, richte zuerst deine Verbindung zu LN Bitts ein. Klicke dazu auf 'Setze LN Bitts für bezahlte Artikel ein'";
}
return sprintf("
Du bist auf der News Seite von Einundzwanzig.
Wir haben für dich derzeit insgesamt %s Artikel geschrieben.
Die derzeitige Bitcoin Blockzeit ist %s.
Die schnellsten Transaktionen verschickst du derzeit mit einer Gebühr von %s Satoschi pro Byte.
%s
",
LibraryItem::query()
->where('news', true)
->count(),
$tip->json(),
$fees['fastestFee'],
$createText
);
}
public function authLn()
{
return sprintf("
Du bist auf der Login Seite von Einundzwanzig.
Du kannst dich hier mit deiner Lightning Applikation einloggen.
Benutze diesen QR-Code oder kopiere ihn in deine Lightning-App. Oder klicke auf den QR-Code, um dich mit der Applikation einzuloggen.
Deine Lightning Applikation muss L N URL auth unterstützen.
Du siehst ganz unten in der Box eine Liste von Lightning Applikationen, die L N URL auth unterstützen.
");
}
public function welcome()
{
return sprintf("
Hallo und herzlich willkommen auf dem Portal von Einundzwanzig.
Klicke einfach auf Login, um Events einzutragen oder News Artikel zu schreiben.
Du brauchst eine Lightning Applikation dafür.
Viel Spaß!
Derzeit sind %s Events eingetragen.
Markus Turm hat %s Artikel geschrieben und %s Artikel dezentralisiert.
Wir haben %s Bitcoin Bücher in Bücherregale verteilt.
Du kannst die einen Termin von insgesamt %s Treffen aussuchen.
",
BitcoinEvent::count(),
LibraryItem::where('created_by', 2)
->where('news', true)
->count(),
LibraryItem::where('created_by', '<>', 2)
->where('news', true)
->count(),
OrangePill::count(),
MeetupEvent::where('start', '>=', now())
->count()
);
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Console\Commands\TTS;
use App\Events\AudioTextToSpeechChangedEvent;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
class CodeIsSpeech extends Command
{
/**
* The name and signature of the console command.
* @var string
*/
protected $signature = 'tts:encode {--text=}';
/**
* The console command description.
* @var string
*/
protected $description = 'Command description';
/**
* Execute the console command.
*/
public function handle()
{
$response = Http::get('http://host.docker.internal:5002/api/tts', [
'text' => File::get(storage_path('app/public/tts/'.$this->option('text').'.txt')),
'speaker_id' => null,
'style_wav' => null,
'language_id' => null,
]);
File::put(storage_path('app/public/tts/'.$this->option('text').'.wav'), $response->body());
event(new AudioTextToSpeechChangedEvent(url('storage/tts/'.$this->option('text').'.wav')));
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class AudioTextToSpeechChangedEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(public string $src)
{
//
}
/**
* Get the channels the event should broadcast on.
*
*/
public function broadcastOn(): \Illuminate\Broadcasting\Channel|array
{
return new Channel('plebchannel');
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class PaidMessageEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(public string $message, public string $checkid)
{
//
}
/**
* Get the channels the event should broadcast on.
*
*/
public function broadcastOn(): \Illuminate\Broadcasting\Channel|array
{
return new Channel('plebchannel');
}
}

View File

@@ -5,12 +5,15 @@ namespace App\Http\Livewire\Auth;
use App\Models\LoginKey; use App\Models\LoginKey;
use App\Models\User; use App\Models\User;
use App\Notifications\ModelCreatedNotification; use App\Notifications\ModelCreatedNotification;
use App\Traits\HasTextToSpeech;
use eza\lnurl; use eza\lnurl;
use Livewire\Component; use Livewire\Component;
use SimpleSoftwareIO\QrCode\Facades\QrCode; use SimpleSoftwareIO\QrCode\Facades\QrCode;
class LNUrlAuth extends Component class LNUrlAuth extends Component
{ {
use HasTextToSpeech;
public ?string $k1 = null; public ?string $k1 = null;
protected ?string $url = null; protected ?string $url = null;

View File

@@ -4,11 +4,14 @@ namespace App\Http\Livewire\BitcoinEvent;
use App\Models\BitcoinEvent; use App\Models\BitcoinEvent;
use App\Models\Country; use App\Models\Country;
use App\Traits\HasTextToSpeech;
use Livewire\Component; use Livewire\Component;
use RalphJSmit\Laravel\SEO\Support\SEOData; use RalphJSmit\Laravel\SEO\Support\SEOData;
class BitcoinEventTable extends Component class BitcoinEventTable extends Component
{ {
use HasTextToSpeech;
public Country $country; public Country $country;
public ?int $year = null; public ?int $year = null;

View File

@@ -4,6 +4,7 @@ namespace App\Http\Livewire\BookCase;
use App\Models\BookCase; use App\Models\BookCase;
use App\Models\Country; use App\Models\Country;
use App\Traits\HasTextToSpeech;
use Livewire\Component; use Livewire\Component;
use Livewire\WithFileUploads; use Livewire\WithFileUploads;
use RalphJSmit\Laravel\SEO\Support\SEOData; use RalphJSmit\Laravel\SEO\Support\SEOData;
@@ -11,6 +12,7 @@ use Spatie\MediaLibrary\MediaCollections\Models\Media;
class CommentBookCase extends Component class CommentBookCase extends Component
{ {
use HasTextToSpeech;
use WithFileUploads; use WithFileUploads;
public Country $country; public Country $country;
@@ -21,6 +23,13 @@ class CommentBookCase extends Component
public BookCase $bookCase; public BookCase $bookCase;
public function mount()
{
$this->bookCase->load([
'orangePills.user',
]);
}
public function save() public function save()
{ {
$this->validate([ $this->validate([

View File

@@ -4,11 +4,14 @@ namespace App\Http\Livewire\BookCase;
use App\Models\Country; use App\Models\Country;
use App\Models\User; use App\Models\User;
use App\Traits\HasTextToSpeech;
use Livewire\Component; use Livewire\Component;
use RalphJSmit\Laravel\SEO\Support\SEOData; use RalphJSmit\Laravel\SEO\Support\SEOData;
class HighscoreTable extends Component class HighscoreTable extends Component
{ {
use HasTextToSpeech;
public Country $country; public Country $country;
public bool $viewingModal = false; public bool $viewingModal = false;

View File

@@ -4,11 +4,14 @@ namespace App\Http\Livewire\BookCase;
use App\Models\BookCase; use App\Models\BookCase;
use App\Models\Country; use App\Models\Country;
use App\Traits\HasTextToSpeech;
use Livewire\Component; use Livewire\Component;
use RalphJSmit\Laravel\SEO\Support\SEOData; use RalphJSmit\Laravel\SEO\Support\SEOData;
class WorldMap extends Component class WorldMap extends Component
{ {
use HasTextToSpeech;
public Country $country; public Country $country;
public function render() public function render()

View File

@@ -137,7 +137,7 @@ class Header extends Component
->orderByDesc('date') ->orderByDesc('date')
->take(2) ->take(2)
->get(), ->get(),
'projectProposals' => ProjectProposal::query()->with(['votes'])->get(), 'projectProposals' => ProjectProposal::query()->with(['user','votes'])->get(),
'cities' => City::query() 'cities' => City::query()
->select(['latitude', 'longitude']) ->select(['latitude', 'longitude'])
->get(), ->get(),

View File

@@ -3,12 +3,15 @@
namespace App\Http\Livewire\Frontend; namespace App\Http\Livewire\Frontend;
use App\Models\Country; use App\Models\Country;
use App\Traits\HasTextToSpeech;
use Illuminate\Support\Facades\Cookie; use Illuminate\Support\Facades\Cookie;
use Livewire\Component; use Livewire\Component;
use RalphJSmit\Laravel\SEO\Support\SEOData; use RalphJSmit\Laravel\SEO\Support\SEOData;
class Welcome extends Component class Welcome extends Component
{ {
use HasTextToSpeech;
public string $c = 'de'; public string $c = 'de';
public string $l = 'de'; public string $l = 'de';

View File

@@ -0,0 +1,87 @@
<?php
namespace App\Http\Livewire;
use App\Traits\LNBitsTrait;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Livewire\Component;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use WireUi\Traits\Actions;
class Hello extends Component
{
use Actions;
use LNBitsTrait;
public $message = '';
public $qrCode = '';
public $invoice = '';
public $paymentHash = '';
public $checkid = null;
public bool $invoicePaid = false;
public function rules()
{
return [
'message' => 'required|string|max:255',
];
}
public function mount()
{
try {
// {"url":"","wallet_id":"","read_key":""}
$invoice = $this->createInvoice(
sats: 21,
memo: 'Payment for: Bitcoin im Ländle 2023 - Code is Speech',
lnbits: [
'url' => 'https://legend.lnbits.com',
'wallet_id' => 'b9b095edd0db4bf8995f1bbc90b195c5',
'read_key' => '67e6d7f94f5345119d6c799d768a029e',
],
);
} catch (\Exception $e) {
$this->notification()
->error('LNBits error: '.$e->getMessage());
return;
}
$this->paymentHash = $invoice['payment_hash'];
$this->qrCode = base64_encode(QrCode::format('png')
->size(300)
->merge('/public/img/einundzwanzig.png', .3)
->errorCorrection('H')
->generate($invoice['payment_request']));
$this->invoice = $invoice['payment_request'];
$this->checkid = $invoice['checking_id'];
}
public function checkPaymentHash()
{
try {
$invoice = $this->check($this->checkid, [
'url' => 'https://legend.lnbits.com',
'wallet_id' => 'b9b095edd0db4bf8995f1bbc90b195c5',
'read_key' => '67e6d7f94f5345119d6c799d768a029e',
]);
} catch (\Exception $e) {
$this->notification()
->error('LNBits error: '.$e->getMessage());
return;
}
if (isset($invoice['paid']) && $invoice['paid']) {
$this->invoicePaid = true;
} else {
Log::error(json_encode($invoice, JSON_THROW_ON_ERROR));
}
}
public function render()
{
return view('livewire.hello')->layout('layouts.guest');
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Http\Livewire; namespace App\Http\Livewire;
use Illuminate\Support\Facades\File;
use Livewire\Component; use Livewire\Component;
use WireUi\Traits\Actions; use WireUi\Traits\Actions;
@@ -9,11 +10,50 @@ class LaravelEcho extends Component
{ {
use Actions; use Actions;
protected $listeners = ['echo:plebchannel,.App\Events\PlebLoggedInEvent' => 'plebLoggedIn']; public $audioSrc = '';
protected $listeners = [
'echo:plebchannel,.App\Events\PlebLoggedInEvent' => 'plebLoggedIn',
'echo:plebchannel,.App\Events\AudioTextToSpeechChangedEvent' => 'audioTextToSpeechChanged',
'echo:plebchannel,.App\Events\PaidMessageEvent' => 'paidMessage',
];
public function rules()
{
return [
'audioSrc' => 'required',
];
}
public function paidMessage($data)
{
$text = sprintf("
%s
%s.
",
'Nachricht aus dem Publikum.',
str($data['message'])
->stripTags()
->toString()
);
File::put(storage_path('app/public/tts/'.$data['checkid'].'.txt'), $text);
dispatch(new \App\Jobs\CodeIsSpeech($data['checkid']))->delay(now()->addSecond());
}
public function audioTextToSpeechChanged($data)
{
$this->audioSrc = $data['src'];
}
public function plebLoggedIn($data) public function plebLoggedIn($data)
{ {
if (auth()->check()) { if (auth()->check()) {
$text = sprintf("
%s hat sich gerade eingeloggt. Markus Turm ist begeistert.
", $data['name']);
File::put(storage_path('app/public/tts/userLoggedIn.txt'), $text);
dispatch(new \App\Jobs\CodeIsSpeech('userLoggedIn'))->delay(now()->addSecond());
$this->notification() $this->notification()
->confirm([ ->confirm([
'img' => $data['img'], 'img' => $data['img'],

View File

@@ -6,11 +6,14 @@ use App\Models\Country;
use App\Models\Library; use App\Models\Library;
use App\Models\LibraryItem; use App\Models\LibraryItem;
use App\Models\Tag; use App\Models\Tag;
use App\Traits\HasTextToSpeech;
use Livewire\Component; use Livewire\Component;
use RalphJSmit\Laravel\SEO\Support\SEOData; use RalphJSmit\Laravel\SEO\Support\SEOData;
class LibraryTable extends Component class LibraryTable extends Component
{ {
use HasTextToSpeech;
public Country $country; public Country $country;
public array $filters = []; public array $filters = [];

View File

@@ -5,11 +5,14 @@ namespace App\Http\Livewire\Meetup;
use App\Models\Country; use App\Models\Country;
use App\Models\Meetup; use App\Models\Meetup;
use App\Models\MeetupEvent; use App\Models\MeetupEvent;
use App\Traits\HasTextToSpeech;
use Livewire\Component; use Livewire\Component;
use RalphJSmit\Laravel\SEO\Support\SEOData; use RalphJSmit\Laravel\SEO\Support\SEOData;
class LandingPage extends Component class LandingPage extends Component
{ {
use HasTextToSpeech;
public Meetup $meetup; public Meetup $meetup;
public Country $country; public Country $country;

View File

@@ -4,11 +4,14 @@ namespace App\Http\Livewire\Meetup;
use App\Models\Country; use App\Models\Country;
use App\Models\Meetup; use App\Models\Meetup;
use App\Traits\HasTextToSpeech;
use Livewire\Component; use Livewire\Component;
use RalphJSmit\Laravel\SEO\Support\SEOData; use RalphJSmit\Laravel\SEO\Support\SEOData;
class WorldMap extends Component class WorldMap extends Component
{ {
use HasTextToSpeech;
public Country $country; public Country $country;
public function filterByMarker($id) public function filterByMarker($id)

View File

@@ -3,6 +3,7 @@
namespace App\Http\Livewire\News; namespace App\Http\Livewire\News;
use App\Models\LibraryItem; use App\Models\LibraryItem;
use App\Traits\HasTextToSpeech;
use App\Traits\NostrTrait; use App\Traits\NostrTrait;
use Livewire\Component; use Livewire\Component;
use RalphJSmit\Laravel\SEO\Support\SEOData; use RalphJSmit\Laravel\SEO\Support\SEOData;
@@ -12,6 +13,7 @@ class ArticleOverview extends Component
{ {
use Actions; use Actions;
use NostrTrait; use NostrTrait;
use HasTextToSpeech;
public $perPage = 9; public $perPage = 9;

View File

@@ -4,12 +4,15 @@ namespace App\Http\Livewire\News\Form;
use App\Models\LibraryItem; use App\Models\LibraryItem;
use App\Traits\HasTagsTrait; use App\Traits\HasTagsTrait;
use Illuminate\Support\Facades\File;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
use Livewire\Component; use Livewire\Component;
use Livewire\WithFileUploads; use Livewire\WithFileUploads;
use WireUi\Traits\Actions;
class NewsArticleForm extends Component class NewsArticleForm extends Component
{ {
use Actions;
use HasTagsTrait; use HasTagsTrait;
use WithFileUploads; use WithFileUploads;
@@ -104,6 +107,20 @@ class NewsArticleForm extends Component
public function save() public function save()
{ {
$this->validate(); $this->validate();
if (str($this->libraryItem->value)->contains('Turm')) {
$text = sprintf("
Markus Turm hat deinen Artikel geprüft aber nicht freigegeben.
Dein Artikel ist leider nicht toxisch genug.
Außerdem musst du mindestens 2 Provokation pro Absatz einbauen, um die gewünschte Turm Qualität zu erreichen.
");
File::put(storage_path('app/public/tts/news_error.txt'), $text);
dispatch(new \App\Jobs\CodeIsSpeech('news_error', false))->delay(now()->addSecond());
$this->notification()->error('Markus Turm hat deinen Artikel abgelehnt.');
return;
}
$this->libraryItem->save(); $this->libraryItem->save();
$this->libraryItem->syncTagsWithType( $this->libraryItem->syncTagsWithType(

View File

@@ -3,6 +3,7 @@
namespace App\Http\Livewire\News; namespace App\Http\Livewire\News;
use App\Models\LibraryItem; use App\Models\LibraryItem;
use App\Traits\HasTextToSpeech;
use App\Traits\LNBitsTrait; use App\Traits\LNBitsTrait;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -17,6 +18,7 @@ class InternArticleView extends Component
{ {
use Actions; use Actions;
use LNBitsTrait; use LNBitsTrait;
use HasTextToSpeech;
public LibraryItem $libraryItem; public LibraryItem $libraryItem;

View File

@@ -2,7 +2,9 @@
namespace App\Http\Livewire\Profile; namespace App\Http\Livewire\Profile;
use App\Traits\HasTextToSpeech;
use App\Traits\LNBitsTrait; use App\Traits\LNBitsTrait;
use Illuminate\Support\Facades\File;
use Livewire\Component; use Livewire\Component;
use WireUi\Traits\Actions; use WireUi\Traits\Actions;
@@ -10,6 +12,7 @@ class LNBits extends Component
{ {
use Actions; use Actions;
use LNBitsTrait; use LNBitsTrait;
use HasTextToSpeech;
public array $settings = [ public array $settings = [
'url' => 'https://legend.lnbits.com', 'url' => 'https://legend.lnbits.com',
@@ -30,6 +33,9 @@ class LNBits extends Component
{ {
if (auth()->user()->lnbits) { if (auth()->user()->lnbits) {
$this->settings = auth()->user()->lnbits; $this->settings = auth()->user()->lnbits;
if ($this->settings['url'] === null) {
$this->settings['url'] = 'https://legend.lnbits.com';
}
} }
} }
@@ -39,6 +45,12 @@ class LNBits extends Component
if ($this->checkLnbitsSettings($this->settings['read_key'], $this->settings['url'], $this->settings['wallet_id']) === false) { if ($this->checkLnbitsSettings($this->settings['read_key'], $this->settings['url'], $this->settings['wallet_id']) === false) {
$this->notification() $this->notification()
->error(__('LNBits settings are not valid!')); ->error(__('LNBits settings are not valid!'));
$legends = "Außerdem hast du nicht deine eigene Nod verwendet. Markus Turm wird darüber sehr traurig sein. Komm in die Einundzwanzig Telegramm Gruppe, und melde dich sofort bei Markus Turm mit einer Entschuldigung.";
$text = sprintf("
Es gab einen Fehler beim Speichern der LN Bitts Einstellungen. Bitte überprüfe die A P I Daten. %s
", $this->settings['url'] === 'https://legend.lnbits.com' ? $legends : '');
File::put(storage_path('app/public/tts/lnbits_error.txt'), $text);
dispatch(new \App\Jobs\CodeIsSpeech('lnbits_error', false))->delay(now()->addSecond());
return; return;
} }

View File

@@ -3,11 +3,14 @@
namespace App\Http\Livewire\School; namespace App\Http\Livewire\School;
use App\Models\Country; use App\Models\Country;
use App\Traits\HasTextToSpeech;
use Livewire\Component; use Livewire\Component;
use RalphJSmit\Laravel\SEO\Support\SEOData; use RalphJSmit\Laravel\SEO\Support\SEOData;
class CourseTable extends Component class CourseTable extends Component
{ {
use HasTextToSpeech;
public Country $country; public Country $country;
public function render() public function render()

View File

@@ -4,6 +4,7 @@ namespace App\Http\Livewire\School;
use App\Models\Country; use App\Models\Country;
use App\Models\CourseEvent; use App\Models\CourseEvent;
use App\Traits\HasTextToSpeech;
use Livewire\Component; use Livewire\Component;
use RalphJSmit\Laravel\SEO\Support\SEOData; use RalphJSmit\Laravel\SEO\Support\SEOData;

View File

@@ -5,6 +5,7 @@ namespace App\Http\Livewire\Tables;
use App\Models\Category; use App\Models\Category;
use App\Models\CourseEvent; use App\Models\CourseEvent;
use App\Models\Lecturer; use App\Models\Lecturer;
use App\Traits\HasTextToSpeech;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Rappasoft\LaravelLivewireTables\DataTableComponent; use Rappasoft\LaravelLivewireTables\DataTableComponent;
use Rappasoft\LaravelLivewireTables\Views\Column; use Rappasoft\LaravelLivewireTables\Views\Column;
@@ -14,6 +15,8 @@ use Rappasoft\LaravelLivewireTables\Views\Filters\TextFilter;
class EventTable extends DataTableComponent class EventTable extends DataTableComponent
{ {
use HasTextToSpeech;
public string $country; public string $country;
public bool $viewingModal = false; public bool $viewingModal = false;

54
app/Jobs/CodeIsSpeech.php Normal file
View File

@@ -0,0 +1,54 @@
<?php
namespace App\Jobs;
use App\Events\AudioTextToSpeechChangedEvent;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
class CodeIsSpeech implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public function __construct(public $id, public bool $encode = true)
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
if ($this->encode) {
$response = Http::get('http://host.docker.internal:5002/api/tts', [
'text' => File::get(storage_path('app/public/tts/'.$this->id.'.txt')),
'speaker_id' => null,
'style_wav' => null,
'language_id' => null,
]);
File::put(storage_path('app/public/tts/'.$this->id.'.wav'), $response->body());
} elseif (!File::exists(storage_path('app/public/tts/'.$this->id.'.wav'))) {
$response = Http::get('http://host.docker.internal:5002/api/tts', [
'text' => File::get(storage_path('app/public/tts/'.$this->id.'.txt')),
'speaker_id' => null,
'style_wav' => null,
'language_id' => null,
]);
File::put(storage_path('app/public/tts/'.$this->id.'.wav'), $response->body());
}
event(new AudioTextToSpeechChangedEvent(url('storage/tts/'.$this->id.'.wav')));
}
}

View File

@@ -4,6 +4,7 @@ namespace App\Listeners;
use App\Events\PlebLoggedInEvent; use App\Events\PlebLoggedInEvent;
use App\Gamify\Points\LoggedIn; use App\Gamify\Points\LoggedIn;
use Illuminate\Support\Facades\File;
class AddLoginReputation class AddLoginReputation
{ {

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Traits;
use App\CodeIsSpeech;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Route;
trait HasTextToSpeech
{
use CodeIsSpeech;
public function mountHasTextToSpeech()
{
$id = str(Route::currentRouteName())
->replace('.', ' ')
->camel()
->toString();
$text = $this->$id();
File::put(storage_path('app/public/tts/'.$id.'.txt'), $text);
if (
in_array($id, [
//'authLn',
'profileLnbits',
'meetupWorld',
'bitcoinEventTableBitcoinEvent',
'libraryTableLibraryItems',
'schoolTableCourse',
])
&& File::exists(storage_path('app/public/tts/'.$id.'.wav'))
) {
dispatch(new \App\Jobs\CodeIsSpeech($id, false))->delay(now()->addSecond());
} elseif (in_array($id, ['welcome']) && auth()->check()) {
} else {
dispatch(new \App\Jobs\CodeIsSpeech($id))->delay(now()->addSecond());
}
}
}

View File

@@ -8,7 +8,7 @@ services:
args: args:
WWWGROUP: '${WWWGROUP}' WWWGROUP: '${WWWGROUP}'
NOSTR_PRIVATE_KEY: '${NOSTR_PRIVATE_KEY}' NOSTR_PRIVATE_KEY: '${NOSTR_PRIVATE_KEY}'
image: sail-8.2/app image: sail-8.2/einundzwanzig
extra_hosts: extra_hosts:
- 'host.docker.internal:host-gateway' - 'host.docker.internal:host-gateway'
ports: ports:

View File

@@ -12,3 +12,14 @@ stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0 stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0 stderr_logfile_maxbytes=0
[program:horizon]
command=/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan horizon
user=sail
autostart=true
autorestart=true
stopwaitsecs=3600
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

View File

@@ -37,9 +37,9 @@
{{ $weather }} (um {{ \App\Support\Carbon::parse($changed)->asTime() }} Uhr aktualisiert - jede 4. Stunde) {{ $weather }} (um {{ \App\Support\Carbon::parse($changed)->asTime() }} Uhr aktualisiert - jede 4. Stunde)
</div> </div>
@else @else
<div class="text-md leading-6 text-gray-900 text-center max-w-screen-2xl"> {{--<div class="text-md leading-6 text-gray-900 text-center max-w-screen-2xl">
Wetterdaten werden in Kürze wieder verfügbar sein. (OpenAI Quota exceeded) Wetterdaten werden in Kürze wieder verfügbar sein. (OpenAI Quota exceeded)
</div> </div>--}}
@endif @endif
<div <div
x-data="{ x-data="{

View File

@@ -0,0 +1,31 @@
<div>
<div
class="mt-10 flex flex-col items-center justify-center gap-x-6 bg-white pb-12">
@if(!$invoicePaid)
<div class="text-xl font-semibold text-gray-900 py-6">
Deine Nachricht wird live vorgelesen.
</div>
<div class="text-xl font-semibold text-gray-900 py-6 w-full px-12">
<x-textarea wire:model="message" label="Deine Nachricht hier" corner-hint="max. 255 Zeichen"/>
</div>
<div class="text-xl font-semibold text-gray-900 py-6">
{{ __('Click QR-Code to open your wallet') }}
</div>
<div class="flex justify-center" wire:key="qrcode">
<a href="lightning:{{ $this->invoice }}">
<img src="{{ 'data:image/png;base64, '. $this->qrCode }}"
alt="qrcode">
</a>
</div>
<div class="text-xl font-semibold text-gray-900 py-6">
21 sats
</div>
<div wire:poll.keep-alive="checkPaymentHash"
wire:key="checkPaymentHash"></div>
@else
<div class="text-xl font-semibold text-gray-900 py-6">
Danke für deine Nachricht. Wenn alles klappt, dann werden wir die Nachricht gleich hören.
</div>
@endif
</div>
</div>

View File

@@ -1,3 +1,15 @@
<div> <div
{{-- The whole world belongs to you. --}} x-data="{
audioSrc: @entangle('audioSrc'),
play() {
console.log(this.audioSrc);
$refs.sourceRef.src = this.audioSrc + '?t=' + new Date().getTime();
$refs.playMe.load();
$refs.playMe.play();
},
}"
>
<audio x-ref="playMe">
<source x-ref="sourceRef" src="" type="audio/wav" x-init="$watch('audioSrc', value => play())"/>
</audio>
</div> </div>

View File

@@ -18,6 +18,9 @@ Route::get('/img-public/{path}', \App\Http\Controllers\ImageController::class)
Route::get('auth/auth47', \App\Http\Livewire\Auth\Auth47Component::class) Route::get('auth/auth47', \App\Http\Livewire\Auth\Auth47Component::class)
->name('auth.auth47'); ->name('auth.auth47');
Route::get('hello', \App\Http\Livewire\Hello::class)
->name('hello');
Route::post('auth/auth47-callback', function (Request $request) { Route::post('auth/auth47-callback', function (Request $request) {
$auth47Version = $request->auth47_response; $auth47Version = $request->auth47_response;
$challenge = $request->challenge; $challenge = $request->challenge;