diff --git a/django/thunderstore/core/management/commands/content/dependencies.py b/django/thunderstore/core/management/commands/content/dependencies.py index b8fe4644f..06156b0d6 100644 --- a/django/thunderstore/core/management/commands/content/dependencies.py +++ b/django/thunderstore/core/management/commands/content/dependencies.py @@ -10,10 +10,21 @@ class DependencyPopulator(ContentPopulator): def populate(self, context: ContentPopulatorContext) -> None: print("Linking dependencies...") PackageVersion.dependencies.through.objects.all().delete() + + # Ensure we have at least one dependency and one dependant + package_count = len(context.packages) + if package_count < 2: + print("Not enough packages to create dependencies.") + return + + dependency_count = min(context.dependency_count, package_count - 1) + if dependency_count < 1: + dependency_count = 1 + dependencies = [ - x.latest.id for x in context.packages[: context.dependency_count] + x.latest.id for x in context.packages[:dependency_count] ] - dependants = context.packages[context.dependency_count :] + dependants = context.packages[dependency_count:] for package in print_progress(dependants, len(dependants)): package.latest.dependencies.set(dependencies) diff --git a/django/thunderstore/core/management/commands/content/package_categories.py b/django/thunderstore/core/management/commands/content/package_categories.py new file mode 100644 index 000000000..147d1945c --- /dev/null +++ b/django/thunderstore/core/management/commands/content/package_categories.py @@ -0,0 +1,58 @@ +from typing import List + +from thunderstore.community.models import PackageCategory +from thunderstore.core.management.commands.content.base import ( + ContentPopulator, + ContentPopulatorContext, +) +from thunderstore.utils.iterators import print_progress + + +class CategoryPopulator(ContentPopulator): + categories = [ + "Mods", + "Modpacks", + "Tools", + "Libraries", + "Misc", + "Audio", + "BepInEx", + "MelonLoader", + "Suits", + "Boombox Music", + "TV Videos", + "Posters", + "Equipment", + "Items", + "Monsters", + "Moons", + "Interiors", + "Furniture", + "Vehicles", + "Client-side", + "Server-side", + "Cosmetics", + "Asset Replacements", + "Translations", + "Emotes", + "Weather", + "Hazards", + "Bug Fixes", + "Performance", + "Tweaks & Quality Of Life", + ] + + def populate(self, context: ContentPopulatorContext) -> None: + print("Populating package categories...") + for community in print_progress(context.communities, len(context.communities)): + for name in self.categories: + slug = name.lower().replace(" ", "-").replace("&", "").replace("--", "-") + PackageCategory.objects.get_or_create( + community=community, + name=name, + defaults={"slug": slug}, + ) + + def clear(self) -> None: + print("Deleting existing package categories...") + PackageCategory.objects.all().delete() diff --git a/django/thunderstore/core/management/commands/content/package_listing.py b/django/thunderstore/core/management/commands/content/package_listing.py index 00cd80f9c..882ef1226 100644 --- a/django/thunderstore/core/management/commands/content/package_listing.py +++ b/django/thunderstore/core/management/commands/content/package_listing.py @@ -1,6 +1,7 @@ +import random from django.db.models import signals -from thunderstore.community.models import PackageListing +from thunderstore.community.models import PackageCategory, PackageListing from thunderstore.core.management.commands.content.base import ( ContentPopulator, ContentPopulatorContext, @@ -19,11 +20,23 @@ def populate(self, context: ContentPopulatorContext) -> None: PackageListing.post_delete, sender=PackageListing ) + community_categories = {} + for community in context.communities: + community_categories[community.id] = list( + PackageCategory.objects.filter(community=community) + ) + for i, package in print_progress( enumerate(context.packages), len(context.packages) ): for community in context.communities: - package.get_or_create_package_listing(community) + listing = package.get_or_create_package_listing(community) + + cats = community_categories.get(community.id, []) + if cats: + count = random.choices([1, 2, 3, 4, 5], weights=[40, 30, 15, 10, 5])[0] + chosen = random.sample(cats, min(count, len(cats))) + listing.categories.set(chosen) # Re-enabling previously disabled signals signals.post_save.connect(PackageListing.post_save, sender=PackageListing) diff --git a/django/thunderstore/core/management/commands/content/package_sections.py b/django/thunderstore/core/management/commands/content/package_sections.py new file mode 100644 index 000000000..2fc25be07 --- /dev/null +++ b/django/thunderstore/core/management/commands/content/package_sections.py @@ -0,0 +1,84 @@ +from thunderstore.community.models import PackageCategory, PackageListingSection +from thunderstore.core.management.commands.content.base import ( + ContentPopulator, + ContentPopulatorContext, +) +from thunderstore.utils.iterators import print_progress + + +class SectionPopulator(ContentPopulator): + def populate(self, context: ContentPopulatorContext) -> None: + print("Populating package listing sections...") + for community in print_progress(context.communities, len(context.communities)): + + def get_cat(slug): + return PackageCategory.objects.get(community=community, slug=slug) + + # Define sections + # Note: Higher priority value means the section is shown first (descending sort). + sections_data = [ + { + "name": "Mods", + "slug": "mods", + "priority": 100, + "exclude": ["modpacks", "asset-replacements"], + "require": [], + }, + { + "name": "Asset Replacements", + "slug": "asset-replacements", + "priority": 90, + "exclude": ["modpacks"], + "require": ["asset-replacements"], + }, + { + "name": "Tools", + "slug": "tools", + "priority": 85, + "exclude": ["modpacks"], + "require": ["tools"], + }, + { + "name": "APIs & Libraries", + "slug": "libraries", + "priority": 80, + "exclude": ["modpacks"], + "require": ["libraries"], + }, + { + "name": "Modpacks", + "slug": "modpacks", + "priority": 70, + "exclude": [], + "require": ["modpacks"], + }, + ] + + for s_data in sections_data: + section, created = PackageListingSection.objects.get_or_create( + community=community, + slug=s_data["slug"], + defaults={ + "name": s_data["name"], + "priority": s_data["priority"], + }, + ) + + if created: + for ex_slug in s_data["exclude"]: + try: + cat = get_cat(ex_slug) + section.exclude_categories.add(cat) + except PackageCategory.DoesNotExist: + print(f"Warning: Category {ex_slug} not found for section {s_data['slug']}") + + for req_slug in s_data["require"]: + try: + cat = get_cat(req_slug) + section.require_categories.add(cat) + except PackageCategory.DoesNotExist: + print(f"Warning: Category {req_slug} not found for section {s_data['slug']}") + + def clear(self) -> None: + print("Deleting existing package listing sections...") + PackageListingSection.objects.all().delete() diff --git a/django/thunderstore/core/management/commands/create_test_data.py b/django/thunderstore/core/management/commands/create_test_data.py index f0955098c..94755eb86 100644 --- a/django/thunderstore/core/management/commands/create_test_data.py +++ b/django/thunderstore/core/management/commands/create_test_data.py @@ -21,9 +21,15 @@ DependencyPopulator, ) from thunderstore.core.management.commands.content.package import PackagePopulator +from thunderstore.core.management.commands.content.package_categories import ( + CategoryPopulator, +) from thunderstore.core.management.commands.content.package_listing import ( ListingPopulator, ) +from thunderstore.core.management.commands.content.package_sections import ( + SectionPopulator, +) from thunderstore.core.management.commands.content.package_version import ( PackageVersionPopulator, ) @@ -42,6 +48,8 @@ [ ("community", CommunityPopulator), ("community_site", CommunitySitePopulator), + ("category", CategoryPopulator), + ("section", SectionPopulator), ("team", TeamPopulator), ("package", PackagePopulator), ("version", PackageVersionPopulator),