🎨 **Style:** Fixed indentation inconsistencies in meetup_user migration file.

🛠️ **Factory:** Created factories for `TwitterAccount`, `EmailCampaign`, `EmailTexts`, and `BookCase`.
 **Helper:** Added `NostrHelper` with methods for generating fake/mocked Nostr data.
⬆️ **Dependencies:** Updated multiple Composer dependencies including `laravel/framework`, `astrotomic/laravel-translatable`, and others to their latest versions.
This commit is contained in:
BT
2026-05-02 19:17:02 +01:00
parent c81b168a11
commit 1f0bfba0d3
57 changed files with 3980 additions and 2142 deletions
@@ -0,0 +1,42 @@
<?php
namespace Database\Factories;
use App\Models\BitcoinEvent;
use App\Models\User;
use App\Models\Venue;
use Database\Factories\Helpers\NostrHelper;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<BitcoinEvent>
*/
class BitcoinEventFactory extends Factory
{
protected $model = BitcoinEvent::class;
public function definition(): array
{
$from = fake()->dateTimeBetween('+1 week', '+6 months');
$to = (clone $from)->modify('+1 day');
return [
'venue_id' => Venue::factory(),
'from' => $from,
'to' => $to,
'title' => fake()->randomElement([
'Bitcoin Conference',
'Lightning Summit',
'Nostrasia',
'Bitcoin Park Meetup',
'Sound Money Symposium',
'Plan B Forum',
]).' '.$from->format('Y'),
'description' => fake()->paragraphs(2, true),
'link' => fake()->url(),
'show_worldwide' => fake()->boolean(15),
'nostr_status' => NostrHelper::fakeNostrEventStatus(),
'created_by' => User::factory(),
];
}
}
+37
View File
@@ -0,0 +1,37 @@
<?php
namespace Database\Factories;
use App\Models\BookCase;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<BookCase>
*/
class BookCaseFactory extends Factory
{
protected $model = BookCase::class;
public function definition(): array
{
return [
'title' => 'Bitcoin Bücherregal '.fake()->unique()->numberBetween(1, 99999),
'latitude' => fake()->latitude(47.0, 55.0),
'longitude' => fake()->longitude(5.0, 16.0),
'address' => fake()->streetAddress().', '.fake()->postcode().' '.fake()->city(),
'type' => fake()->randomElement(['public', 'private']),
'open' => fake()->randomElement(['24/7', 'Mo-Fr 09:00-18:00', 'Wochenenden', null]),
'comment' => fake()->boolean(60) ? fake()->sentence() : null,
'contact' => fake()->boolean(50) ? fake()->email() : null,
'bcz' => null,
'digital' => fake()->boolean(20),
'icontype' => 'default',
'deactivated' => false,
'deactreason' => '',
'entrytype' => fake()->randomElement(['public', 'private']),
'homepage' => fake()->boolean(40) ? fake()->url() : null,
'created_by' => User::factory(),
];
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace Database\Factories;
use App\Models\Category;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends Factory<Category>
*/
class CategoryFactory extends Factory
{
protected $model = Category::class;
public function definition(): array
{
$name = ucfirst(fake()->unique()->word()).' '.fake()->unique()->numberBetween(1, 9999);
return [
'name' => $name,
'slug' => Str::slug($name),
];
}
}
+59 -7
View File
@@ -2,26 +2,78 @@
namespace Database\Factories;
use App\Models\City;
use App\Models\Country;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\City>
* @extends Factory<City>
*/
class CityFactory extends Factory
{
protected $model = City::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
* @var array<string, array<int, array{name: string, lat: float, lon: float}>>
*/
private static array $citiesByCode = [
'DE' => [
['name' => 'Berlin', 'lat' => 52.5200, 'lon' => 13.4050],
['name' => 'München', 'lat' => 48.1351, 'lon' => 11.5820],
['name' => 'Hamburg', 'lat' => 53.5511, 'lon' => 9.9937],
['name' => 'Köln', 'lat' => 50.9375, 'lon' => 6.9603],
['name' => 'Frankfurt', 'lat' => 50.1109, 'lon' => 8.6821],
['name' => 'Leipzig', 'lat' => 51.3397, 'lon' => 12.3731],
['name' => 'Dresden', 'lat' => 51.0504, 'lon' => 13.7373],
['name' => 'Stuttgart', 'lat' => 48.7758, 'lon' => 9.1829],
],
'AT' => [
['name' => 'Wien', 'lat' => 48.2082, 'lon' => 16.3738],
['name' => 'Graz', 'lat' => 47.0707, 'lon' => 15.4395],
['name' => 'Innsbruck', 'lat' => 47.2692, 'lon' => 11.4041],
['name' => 'Salzburg', 'lat' => 47.8095, 'lon' => 13.0550],
],
'CH' => [
['name' => 'Zürich', 'lat' => 47.3769, 'lon' => 8.5417],
['name' => 'Bern', 'lat' => 46.9480, 'lon' => 7.4474],
['name' => 'Genf', 'lat' => 46.2044, 'lon' => 6.1432],
],
'US' => [
['name' => 'New York', 'lat' => 40.7128, 'lon' => -74.0060],
['name' => 'Austin', 'lat' => 30.2672, 'lon' => -97.7431],
['name' => 'Miami', 'lat' => 25.7617, 'lon' => -80.1918],
],
];
public function definition(): array
{
$name = fake()->unique()->city();
return [
'name' => fake()->city(),
'country_id' => 1,
'country_id' => Country::factory(),
'name' => $name,
'slug' => Str::slug($name).'-'.fake()->unique()->numberBetween(1000, 99999),
'longitude' => fake()->longitude(),
'latitude' => fake()->latitude(),
'created_by' => \App\Models\User::factory(),
'osm_relation' => null,
'simplified_geojson' => null,
'population' => fake()->numberBetween(10000, 5000000),
'population_date' => fake()->date(),
'created_by' => User::factory(),
];
}
public function inGermany(): static
{
$city = collect(self::$citiesByCode['DE'])->random();
return $this->state(fn (array $attrs) => [
'name' => $city['name'],
'slug' => Str::slug($city['name']).'-de-'.fake()->unique()->numberBetween(1000, 99999),
'latitude' => $city['lat'],
'longitude' => $city['lon'],
]);
}
}
+24 -7
View File
@@ -2,24 +2,41 @@
namespace Database\Factories;
use App\Models\Country;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Country>
* @extends Factory<Country>
*/
class CountryFactory extends Factory
{
protected $model = Country::class;
/**
* Define the model's default state.
*
* @return array<string, mixed>
* @var array<int, array<string, mixed>>
*/
private static array $countries = [
['name' => 'Deutschland', 'english_name' => 'Germany', 'code' => 'DE', 'language_codes' => ['de'], 'longitude' => 10.4515, 'latitude' => 51.1657],
['name' => 'Österreich', 'english_name' => 'Austria', 'code' => 'AT', 'language_codes' => ['de'], 'longitude' => 14.5501, 'latitude' => 47.5162],
['name' => 'Schweiz', 'english_name' => 'Switzerland', 'code' => 'CH', 'language_codes' => ['de', 'fr', 'it'], 'longitude' => 8.2275, 'latitude' => 46.8182],
['name' => 'Vereinigte Staaten', 'english_name' => 'United States', 'code' => 'US', 'language_codes' => ['en'], 'longitude' => -95.7129, 'latitude' => 37.0902],
['name' => 'Spanien', 'english_name' => 'Spain', 'code' => 'ES', 'language_codes' => ['es'], 'longitude' => -3.7492, 'latitude' => 40.4637],
['name' => 'Frankreich', 'english_name' => 'France', 'code' => 'FR', 'language_codes' => ['fr'], 'longitude' => 2.2137, 'latitude' => 46.2276],
['name' => 'Vereinigtes Königreich', 'english_name' => 'United Kingdom', 'code' => 'GB', 'language_codes' => ['en'], 'longitude' => -3.4360, 'latitude' => 55.3781],
['name' => 'Niederlande', 'english_name' => 'Netherlands', 'code' => 'NL', 'language_codes' => ['nl'], 'longitude' => 5.2913, 'latitude' => 52.1326],
];
public function definition(): array
{
$country = self::$countries[$this->faker->unique()->numberBetween(0, count(self::$countries) - 1)];
return [
'name' => fake()->country(),
'code' => fake()->countryCode(),
'language_codes' => ['en'],
'name' => $country['name'],
'english_name' => $country['english_name'],
'code' => $country['code'],
'language_codes' => $country['language_codes'],
'longitude' => $country['longitude'],
'latitude' => $country['latitude'],
];
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace Database\Factories;
use App\Models\Course;
use App\Models\CourseEvent;
use App\Models\User;
use App\Models\Venue;
use Database\Factories\Helpers\NostrHelper;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<CourseEvent>
*/
class CourseEventFactory extends Factory
{
protected $model = CourseEvent::class;
public function definition(): array
{
$from = fake()->dateTimeBetween('+1 day', '+3 months');
$to = (clone $from)->modify('+2 hours');
return [
'course_id' => Course::factory(),
'venue_id' => Venue::factory(),
'from' => $from,
'to' => $to,
'link' => 'https://einundzwanzig.space/courses/'.fake()->slug(),
'nostr_status' => NostrHelper::fakeNostrEventStatus(),
'created_by' => User::factory(),
];
}
}
+37
View File
@@ -0,0 +1,37 @@
<?php
namespace Database\Factories;
use App\Models\Course;
use App\Models\Lecturer;
use App\Models\User;
use Database\Factories\Helpers\NostrHelper;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<Course>
*/
class CourseFactory extends Factory
{
protected $model = Course::class;
public function definition(): array
{
return [
'lecturer_id' => Lecturer::factory(),
'name' => fake()->randomElement([
'Bitcoin Basics',
'Lightning Network Workshop',
'Self Custody Mastery',
'Hardware Wallet Setup',
'Nostr für Anfänger',
'Sound Money & Austrian Economics',
'Bitcoin Mining 101',
'Privacy & Coinjoin',
]).' #'.fake()->unique()->numberBetween(1, 99999),
'description' => fake()->paragraphs(2, true),
'nostr_status' => NostrHelper::fakeNostrEventStatus(),
'created_by' => User::factory(),
];
}
}
@@ -0,0 +1,24 @@
<?php
namespace Database\Factories;
use App\Models\EmailCampaign;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<EmailCampaign>
*/
class EmailCampaignFactory extends Factory
{
protected $model = EmailCampaign::class;
public function definition(): array
{
return [
'name' => 'Bitcoin Newsletter '.fake()->unique()->numberBetween(1, 9999),
'list_file_name' => 'list_'.fake()->unique()->slug(2).'.csv',
'subject_prompt' => 'Schreibe einen ansprechenden Betreff über Bitcoin und Sound Money.',
'text_prompt' => 'Verfasse einen freundlichen Newsletter über die neuesten Bitcoin-Entwicklungen.',
];
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace Database\Factories;
use App\Models\EmailCampaign;
use App\Models\EmailTexts;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<EmailTexts>
*/
class EmailTextsFactory extends Factory
{
protected $model = EmailTexts::class;
public function definition(): array
{
return [
'email_campaign_id' => EmailCampaign::factory(),
'sender_md5' => md5(fake()->unique()->safeEmail()),
'subject' => fake()->sentence(),
'text' => fake()->paragraphs(3, true),
];
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace Database\Factories;
use App\Models\Episode;
use App\Models\Podcast;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends Factory<Episode>
*/
class EpisodeFactory extends Factory
{
protected $model = Episode::class;
public function definition(): array
{
return [
'guid' => (string) Str::uuid(),
'podcast_id' => Podcast::factory(),
'data' => json_encode([
'title' => 'Folge '.fake()->numberBetween(1, 999).': '.fake()->sentence(4),
'description' => fake()->paragraph(),
'pubDate' => fake()->dateTimeBetween('-1 year', 'now')->format(DATE_RFC2822),
'duration' => fake()->numberBetween(900, 7200),
'enclosure' => [
'url' => 'https://media.einundzwanzig.space/'.Str::random(16).'.mp3',
'type' => 'audio/mpeg',
],
]),
'created_by' => User::factory(),
];
}
}
@@ -0,0 +1,96 @@
<?php
namespace Database\Factories\Helpers;
use Illuminate\Support\Str;
class NostrHelper
{
/**
* @return array<int, string>
*/
public static function realNpubs(): array
{
return [
'npub1sg6plzptd64u62a878hep2kev88swjh3tw00gjsfl8f237lmu63q0uf63m', // jack
'npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s', // saylor
'npub1qny3tkh0acurzla8x3zy4nhrjz5zd8l9sy9jys09umwng00manysew95gx', // odell
'npub1u8lnhlw5usp3t9vmpz60ejpyt649z33hu82wc2hpv6m5xdqmuxhs46turz', // gigi
'npub1az9xj85cmxv8e9j9y80lvqp97crsqdu2fpu3srwthd99qfu9qsgstam8y8', // marty bent
'npub1a2cww4kn9wqte4ry70vyfwqyqvpswksna27rtxd8vty6c74era8sdcw83a', // lyn alden
'npub1a3hrd4wfawu0pkvm2nrqapcwjfa7gh23ymp7uksdg6flnv7c4ehq6dpcyu', // dergigi
'npub1ev0eu6cy4dt5rrrju3xz77f8ww26pcnaty3xq5tlh2eheahuzxpsd2zrqp', // pleb
'npub1mj8mcsdj3lp3xyamr0pwfwsnumv4w3z4yqfg8wpcrk6lqkx6n7ksz0n5z3', // gpt-3
'npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft', // ODELL
'npub10ghxwy0z9wq75e5ehl5xsymq5d28etr96ya5j6vz76m9z3l9j2sqphr8wm', // Hodl Hodl
'npub16dhgpql60vmd4mnydjut87vla23a38j689jssaqlqqlzrtqtd0kqex4nf2', // Bitcoin Mechanic
'npub1xy54p83r6wnpyhs52xjeztd7qyyeu9ghymz8v66yu8kt3jzx75rs2qvz8x', // Tomer
'npub1nstrcu63lzpjkz94djajuz2evrgu2psd66cwgc0gz0c0qazezx0q9urg5l', // tooner
'npub1zk6u7mxlflguqteghn8q7xtu47hyerruv6379c3z9w8s7ywqq02qrh40nr', // amboss
'npub16f3y4ej62vca7s0wlf0kpzjn7zwx48xg6n4hph5e8mr8u9qrjnxstxn5lr', // dazbea
'npub1xkym0yhu9hgwes2vchden6etqkrt5pja5l7w0ywqp7042at8638stslfsr', // dergigi
'npub1y3yzfnkvkkdtv9j83fz9zk8jrxun7nzc8h3rnnwmnmlnxfdpqyxs9hu03l', // bitcoinmechanic
'npub1u85ksjsrjsezndvr0vqnrr98c7l68k73stfp02n9d4lpr8t3ya3qz92sf2', // jack mallers
'npub1nytmln3wdhzaa7y9zk83w6js5ydp4z2nm8r4vsewlmcrlnktwwzs7l40v0', // proof of work
];
}
/**
* @return array<int, string>
*/
public static function realLightningAddresses(): array
{
return [
'gigi@walletofsatoshi.com',
'tony@strike.me',
'jack@cash.app',
'odell@getalby.com',
'marty@walletofsatoshi.com',
'lyn@strike.me',
'pleb@getalby.com',
'satoshi@nakamoto.btc',
'darth@walletofsatoshi.com',
'orange@getalby.com',
];
}
public static function randomNpub(): string
{
if (random_int(1, 100) <= 70) {
return self::realNpubs()[array_rand(self::realNpubs())];
}
return 'npub1'.Str::random(58);
}
public static function randomLightningAddress(?string $username = null): string
{
if ($username !== null) {
$domain = collect(['getalby.com', 'walletofsatoshi.com', 'strike.me', 'lnbits.io', 'coincorner.io'])->random();
return Str::slug($username).'@'.$domain;
}
return self::realLightningAddresses()[array_rand(self::realLightningAddresses())];
}
public static function fakeNostrEventStatus(): ?string
{
if (random_int(1, 100) <= 90) {
return null;
}
$relays = ['wss://relay.damus.io', 'wss://nos.lol', 'wss://relay.nostr.band', 'wss://nostr.wine'];
$eventId = bin2hex(random_bytes(32));
return 'Sent event '.substr($eventId, 0, 16).'... to '.collect($relays)->random();
}
/**
* Generate a hex pubkey (64 chars) used in Nostr filters.
*/
public static function randomHexPubkey(): string
{
return bin2hex(random_bytes(32));
}
}
+6 -7
View File
@@ -2,22 +2,21 @@
namespace Database\Factories;
use App\Models\Highscore;
use Database\Factories\Helpers\NostrHelper;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Highscore>
* @extends Factory<Highscore>
*/
class HighscoreFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
protected $model = Highscore::class;
public function definition(): array
{
return [
'npub' => 'npub1'.fake()->regexify('[a-z0-9]{20}'),
'npub' => NostrHelper::randomNpub(),
'name' => fake()->name(),
'satoshis' => fake()->numberBetween(0, 100000),
'blocks' => fake()->numberBetween(0, 1000),
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace Database\Factories;
use App\Models\Lecturer;
use App\Models\User;
use Database\Factories\Helpers\NostrHelper;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<Lecturer>
*/
class LecturerFactory extends Factory
{
protected $model = Lecturer::class;
public function definition(): array
{
$firstName = fake()->firstName();
$lastName = fake()->lastName();
$name = $firstName.' '.$lastName.' '.fake()->unique()->numberBetween(1, 99999);
return [
'name' => $name,
'active' => true,
'description' => fake()->paragraphs(2, true),
'subtitle' => 'Bitcoin-Pädagoge & Autor',
'intro' => fake()->paragraph(),
'twitter_username' => '@'.fake()->userName(),
'website' => 'https://'.fake()->domainName(),
'lightning_address' => NostrHelper::randomLightningAddress($firstName),
'lnurl' => null,
'node_id' => null,
'nostr' => NostrHelper::randomNpub(),
'paynym' => null,
'created_by' => User::factory(),
];
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace Database\Factories;
use App\Models\Library;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<Library>
*/
class LibraryFactory extends Factory
{
protected $model = Library::class;
public function definition(): array
{
return [
'name' => fake()->unique()->randomElement([
'Bitcoin Standard Library',
'Lightning Network Resources',
'Nostr Knowledge Base',
'Self Custody Guides',
'Sound Money Classics',
'Cypherpunk Archive',
]).' '.fake()->unique()->numberBetween(1, 9999),
'is_public' => true,
'language_codes' => ['en', 'de'],
'parent_id' => null,
'created_by' => User::factory(),
];
}
}
+61
View File
@@ -0,0 +1,61 @@
<?php
namespace Database\Factories;
use App\Models\Episode;
use App\Models\Lecturer;
use App\Models\LibraryItem;
use App\Models\User;
use Database\Factories\Helpers\NostrHelper;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<LibraryItem>
*/
class LibraryItemFactory extends Factory
{
protected $model = LibraryItem::class;
public function definition(): array
{
$name = fake()->randomElement([
'Was ist Bitcoin?',
'How Lightning Works',
'Self Custody erklärt',
'Nostr Protocol Deep Dive',
'Hyperbitcoinization Thesis',
'Sound Money Principles',
'Privacy on Bitcoin',
'Mining Economics',
]).' #'.fake()->unique()->numberBetween(1, 99999);
return [
'lecturer_id' => Lecturer::factory(),
'episode_id' => null,
'order_column' => fake()->unique()->numberBetween(1, 1_000_000),
'name' => $name,
'type' => fake()->randomElement(['article', 'video', 'podcast_episode', 'pdf']),
'language_code' => fake()->randomElement(['en', 'de']),
'value' => "# {$name}\n\n".fake()->paragraphs(3, true),
'subtitle' => fake()->sentence(),
'excerpt' => fake()->paragraph(),
'main_image_caption' => null,
'read_time' => fake()->numberBetween(2, 30).' min',
'approved' => true,
'news' => fake()->boolean(20),
'tweet' => false,
'nostr_status' => NostrHelper::fakeNostrEventStatus(),
'value_to_be_paid' => null,
'sats' => fake()->boolean(15) ? fake()->numberBetween(100, 21000) : null,
'created_by' => User::factory(),
];
}
public function withEpisode(): static
{
return $this->state(fn () => [
'episode_id' => Episode::factory(),
'type' => 'podcast_episode',
]);
}
}
+17 -9
View File
@@ -2,29 +2,37 @@
namespace Database\Factories;
use App\Enums\RecurrenceType;
use App\Models\Meetup;
use App\Models\MeetupEvent;
use App\Models\User;
use Database\Factories\Helpers\NostrHelper;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\MeetupEvent>
* @extends Factory<MeetupEvent>
*/
class MeetupEventFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
protected $model = MeetupEvent::class;
public function definition(): array
{
return [
'meetup_id' => \App\Models\Meetup::factory(),
'start' => now()->addWeek(),
'meetup_id' => Meetup::factory(),
'start' => now()->addDays(fake()->numberBetween(1, 60)),
'location' => fake()->address(),
'description' => fake()->paragraph(),
'link' => fake()->url(),
'attendees' => [],
'might_attendees' => [],
'created_by' => \App\Models\User::factory(),
'nostr_status' => NostrHelper::fakeNostrEventStatus(),
'recurrence_type' => fake()->boolean(40) ? RecurrenceType::Monthly : null,
'recurrence_day_of_week' => null,
'recurrence_day_position' => null,
'recurrence_interval' => 1,
'recurrence_end_date' => null,
'created_by' => User::factory(),
];
}
}
+25 -10
View File
@@ -2,27 +2,42 @@
namespace Database\Factories;
use App\Models\City;
use App\Models\Meetup;
use App\Models\User;
use Database\Factories\Helpers\NostrHelper;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Meetup>
* @extends Factory<Meetup>
*/
class MeetupFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
protected $model = Meetup::class;
public function definition(): array
{
$name = fake()->company();
$cityName = fake()->city();
$name = 'Bitcoin Meetup '.$cityName;
return [
'name' => $name,
'slug' => \Illuminate\Support\Str::slug($name),
'city_id' => City::factory(),
'name' => $name.' '.fake()->unique()->numberBetween(1, 99999),
'slug' => Str::slug($name).'-'.fake()->unique()->numberBetween(1000, 99999),
'intro' => fake()->paragraph(),
'telegram_link' => 'https://t.me/'.Str::slug($cityName).'_btc',
'webpage' => 'https://'.Str::slug($cityName).'.einundzwanzig.space',
'twitter_username' => fake()->boolean(40) ? '@btc_'.Str::slug($cityName) : null,
'github_data' => [],
'created_by' => \App\Models\User::factory(),
'matrix_group' => null,
'community' => fake()->boolean(80) ? 'einundzwanzig' : null,
'visible_on_map' => true,
'simplex' => null,
'signal' => null,
'nostr' => NostrHelper::randomNpub(),
'nostr_status' => NostrHelper::fakeNostrEventStatus(),
'created_by' => User::factory(),
];
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace Database\Factories;
use App\Models\BookCase;
use App\Models\OrangePill;
use App\Models\User;
use Database\Factories\Helpers\NostrHelper;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<OrangePill>
*/
class OrangePillFactory extends Factory
{
protected $model = OrangePill::class;
public function definition(): array
{
return [
'user_id' => User::factory(),
'book_case_id' => BookCase::factory(),
'date' => fake()->dateTimeBetween('-1 year', 'now'),
'amount' => fake()->numberBetween(1, 21),
'comment' => fake()->boolean(60) ? fake()->sentence() : null,
'nostr_status' => NostrHelper::fakeNostrEventStatus(),
];
}
}
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace Database\Factories;
use App\Models\Participant;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<Participant>
*/
class ParticipantFactory extends Factory
{
protected $model = Participant::class;
public function definition(): array
{
return [
'first_name' => fake()->firstName(),
'last_name' => fake()->lastName(),
];
}
}
+35
View File
@@ -0,0 +1,35 @@
<?php
namespace Database\Factories;
use App\Models\Podcast;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends Factory<Podcast>
*/
class PodcastFactory extends Factory
{
protected $model = Podcast::class;
public function definition(): array
{
$name = 'Einundzwanzig Podcast '.fake()->unique()->numberBetween(1, 9999);
return [
'guid' => (string) Str::uuid(),
'locked' => true,
'title' => $name,
'link' => 'https://einundzwanzig.space/podcast/'.Str::slug($name),
'language_code' => 'de',
'data' => json_encode([
'description' => fake()->paragraph(),
'author' => 'Einundzwanzig',
'image' => null,
]),
'created_by' => User::factory(),
];
}
}
@@ -0,0 +1,39 @@
<?php
namespace Database\Factories;
use App\Models\ProjectProposal;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends Factory<ProjectProposal>
*/
class ProjectProposalFactory extends Factory
{
protected $model = ProjectProposal::class;
public function definition(): array
{
$name = fake()->randomElement([
'Bitcoin Beginners Workshop',
'Self Custody Tour',
'Nostr Relay Infrastructure',
'Lightning Educational Content',
'Open-Source Wallet Translation',
'Community Hardware Wallet Distribution',
'Sound Money Documentary',
'Plebs Education Initiative',
]).' '.fake()->unique()->numberBetween(1, 99999);
return [
'user_id' => User::factory(),
'name' => $name,
'slug' => Str::slug($name),
'support_in_sats' => fake()->randomElement([21_000, 100_000, 210_000, 1_000_000, 21_000_000]),
'description' => fake()->paragraphs(3, true),
'created_by' => User::factory(),
];
}
}
@@ -0,0 +1,25 @@
<?php
namespace Database\Factories;
use App\Models\CourseEvent;
use App\Models\Participant;
use App\Models\Registration;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<Registration>
*/
class RegistrationFactory extends Factory
{
protected $model = Registration::class;
public function definition(): array
{
return [
'course_event_id' => CourseEvent::factory(),
'participant_id' => Participant::factory(),
'active' => true,
];
}
}
@@ -6,6 +6,7 @@ use App\Enums\SelfHostedServiceType;
use App\Models\SelfHostedService;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends Factory<SelfHostedService>
@@ -19,17 +20,26 @@ class SelfHostedServiceFactory extends Factory
$name = $this->faker->unique()->company();
return [
// 'created_by' => $this->faker->optional()->numberBetween(1,9),
'created_by' => 750,
'created_by' => User::factory(),
'name' => $name,
'slug' => str($name)->slug(),
'intro' => $this->faker->optional()->paragraph(),
'url_clearnet' => $this->faker->optional()->url(),
'url_onion' => $this->faker->optional()->url(),
'url_i2p' => $this->faker->optional()->url(),
'url_pkdns' => $this->faker->optional()->url(),
'slug' => Str::slug($name).'-'.$this->faker->unique()->numberBetween(1000, 99999),
'intro' => $this->faker->paragraph(),
'url_clearnet' => $this->faker->boolean(80) ? $this->faker->url() : null,
'url_onion' => $this->faker->boolean(20) ? Str::random(56).'.onion' : null,
'url_i2p' => null,
'url_pkdns' => null,
'type' => $this->faker->randomElement(SelfHostedServiceType::cases())->value,
'contact' => $this->faker->optional()->url(),
'contact' => $this->faker->boolean(60) ? $this->faker->email() : null,
'ip' => $this->faker->boolean(50) ? $this->faker->ipv4() : null,
'anon' => false,
];
}
public function anonymous(): static
{
return $this->state(fn () => [
'anon' => true,
'created_by' => null,
]);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace Database\Factories;
use App\Models\Tag;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends Factory<Tag>
*/
class TagFactory extends Factory
{
protected $model = Tag::class;
public function definition(): array
{
$name = fake()->unique()->word().'-'.fake()->unique()->numberBetween(1, 9999);
$slug = Str::slug($name);
return [
'name' => json_encode(['en' => $name, 'de' => $name]),
'slug' => json_encode(['en' => $slug, 'de' => $slug]),
'type' => fake()->randomElement(['topic', 'category', null]),
'order_column' => null,
'icon' => 'tag',
];
}
}
@@ -0,0 +1,27 @@
<?php
namespace Database\Factories;
use App\Models\TwitterAccount;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends Factory<TwitterAccount>
*/
class TwitterAccountFactory extends Factory
{
protected $model = TwitterAccount::class;
public function definition(): array
{
return [
'twitter_id' => (string) fake()->unique()->numberBetween(100000, 999999999),
'nickname' => fake()->unique()->userName(),
'token' => Str::random(40),
'expires_in' => 7200,
'data' => json_encode(['scope' => ['tweet.read', 'tweet.write', 'users.read']]),
'refresh_token' => Str::random(40),
];
}
}
+35 -10
View File
@@ -2,43 +2,68 @@
namespace Database\Factories;
use App\Models\User;
use Database\Factories\Helpers\NostrHelper;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
* @extends Factory<User>
*/
class UserFactory extends Factory
{
/**
* The current password being used by the factory.
*/
protected static ?string $password;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$name = fake()->firstName().' '.fake()->lastName();
return [
'name' => fake()->name(),
'name' => $name,
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
'reputation' => fake()->numberBetween(0, 1000),
'current_language' => fake()->randomElement(['de', 'en']),
'timezone' => 'Europe/Berlin',
'is_lecturer' => fake()->boolean(20),
'nostr' => fake()->boolean(70) ? NostrHelper::randomNpub() : null,
'lightning_address' => fake()->boolean(40) ? NostrHelper::randomLightningAddress($name) : null,
'lnurl' => null,
'node_id' => null,
'paynym' => null,
'lnbits' => null,
'public_key' => null,
'change' => null,
'change_time' => null,
'profile_photo_path' => null,
];
}
/**
* Indicate that the model's email address should be unverified.
*/
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
public function lecturer(): static
{
return $this->state(fn (array $attributes) => [
'is_lecturer' => true,
]);
}
public function withNostr(): static
{
return $this->state(fn (array $attributes) => [
'nostr' => NostrHelper::randomNpub(),
'lightning_address' => NostrHelper::randomLightningAddress($attributes['name'] ?? null),
]);
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace Database\Factories;
use App\Models\City;
use App\Models\User;
use App\Models\Venue;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends Factory<Venue>
*/
class VenueFactory extends Factory
{
protected $model = Venue::class;
public function definition(): array
{
$name = fake()->randomElement(['Bitcoin Café', 'Sound Money Lounge', 'Hodl Hodl Bar', 'The Orange Pill', 'Satoshi\'s Place']).' '.fake()->unique()->numberBetween(1, 99999);
return [
'city_id' => City::factory(),
'name' => $name,
'slug' => Str::slug($name),
'street' => fake()->streetAddress(),
'created_by' => User::factory(),
];
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace Database\Factories;
use App\Models\ProjectProposal;
use App\Models\User;
use App\Models\Vote;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends Factory<Vote>
*/
class VoteFactory extends Factory
{
protected $model = Vote::class;
public function definition(): array
{
return [
'user_id' => User::factory(),
'project_proposal_id' => ProjectProposal::factory(),
'value' => fake()->randomElement([0, 1]),
'reason' => fake()->boolean(40) ? fake()->sentence() : null,
'created_by' => User::factory(),
];
}
}