from datetime import datetime from zoneinfo import ZoneInfo from django.core.management import call_command from django.core.management.base import BaseCommand from core.models import Assembly, Conference, StaticPage, StaticPageNamespace NS_INTRO = '_intro_' INTRO_PAGES = { 'assemblies': { 'title': { 'de': 'Was ist das hier?', 'en': 'What is this place?', }, 'text': { 'de': 'Hier findest du alle Assemblies, die dieses Jahr dabei sind.', 'en': 'Here you can find all the assemblies taking part this year.', }, }, 'assemblies_events': { 'title': { 'de': 'Assembly Vorträge', 'en': 'Assembly Events', }, 'text': { 'de': 'Schau dir an, was die Assemblies vorhaben!', 'en': 'See what the assemblies are up to!', }, }, 'badges': { 'title': { 'de': 'Was sind Badges?', 'en': 'What are badges?', }, 'text': { 'de': 'Hier findest du eine Liste der Badges, die von Assemblies erstellt wurden und die du während dieser Veranstaltung finden könntest.\r\nAssemblies können neue Badges im Backoffice erstellen!', # noqa: E501 'en': 'Here you can find a list of badges that assemblies have created and that you may find during this event.\r\nAssemblies can create new badges in the backoffice!', # noqa: E501 }, }, 'projects': { 'title': { 'de': 'Was sind Projekte?', 'en': 'What are projects?', }, 'text': { 'de': 'Assemblies und auch Einzelpersonen stellen hier Projekte vor, an denen sie arbeiten. Schau dir die Liste an und füge vielleicht selbst eines hinzu?', # noqa: E501 'en': "Assemblies and individual people like to highlight projects they are working on. Here you'll find a list, consider adding your fancy project?", # noqa: E501 }, }, 'reportcontent': { 'title': { 'de': 'DIES IST KEIN KONTAKTFORMULAR', 'en': 'THIS IS NOT A CONTACT FORM', }, 'text': { 'de': 'Diese Funktion ist dafür gedacht, bösartigen und/oder illegalen Inhalt zu melden. Sie ist nicht dafür gedacht, Änderungen im Wiki zu beantragen oder allgemeine Fragen zu beantworten. Dafür kontaktiere bitte die Orga. Danke!', # noqa: E501 'en': 'This function is intended to report malicious and/or illegal contents. It is not meant to request changes in wiki pages or ask questions. For that please contact the orga. Thanks!', # noqa: E501 }, }, 'sos': { 'title': { 'de': 'Was ist das hier?', 'en': 'What ist das hier?', }, 'text': { 'de': 'Hier kannst du selbst organisierte Vorträge und Workshops sehen. Vielleicht möchtest du selbst etwas anbieten?', # noqa: E501 'en': 'Here you can find sessions and workshops which are hosted by individuals. You might host your own?', }, }, } def seed_conference(conf: Conference, year: int = 0, force: bool = False): if Assembly.objects.filter(conference=conf).exists(): raise ValueError('Conference already has assemblies?!') # create info block namespace and texts StaticPageNamespace.objects.create(conference=conf, prefix=NS_INTRO, groups=['hubteam']) for page_slug, page_data in INTRO_PAGES.items(): for lang in ['de', 'en']: title = page_data['title'][lang] text = page_data['text'][lang] page = StaticPage.objects.create( conference=conf, slug=f'{NS_INTRO}{page_slug}', language=lang, title=title, protection=StaticPage.Protection.PERM, privacy=StaticPage.Privacy.NONE, ) rev = page.revisions.create(body=text, title=title) rev.set_public() # create SoS assembly conf.self_organized_sessions_assembly = Assembly.objects.create( conference=conf, slug='sos', name='Self Organized Sessions', is_official=True, state_assembly=Assembly.State.HIDDEN, state_channel=Assembly.State.NONE, ) # create navigation (top level) nav_conf = conf.nav_items.create( label_de='Konferenz', title_de='Offizielle Informationen, Tipps & Tricks zur Veranstaltung', label_en='Conference', title_en='official information, tips & tricks for the event', index=10, ) nav_visitors = conf.nav_items.create( label_de='Besucher', title_de='Nützliche Links', label_en='visitors', title_en='helpful links', index=15, ) nav_my = conf.nav_items.create( label_de='Mein Congress', title_de='personalisiertes Erlebnis', label_en='my congress', title_en='personalized experience', index=100, ) entries = [ # (parent, index, icon, label_de, label_en, title_de, title_en, url) ( nav_conf, 10, 'rocket-takeoff', 'Willkommen', 'Welcome', 'Startseite', 'start page', 'conference://index', ), ( nav_conf, 19, 'calendar-event', 'Events (Jetzt)', 'events (now)', 'das Vortragsprogramm als Liste', 'talks, workshops and other events in list view', 'conference://fahrplan?mode=list#now', ), ( nav_conf, 20, 'calendar-week', 'Fahrplan', 'Schedule', 'das Vortragsprogramm', 'talks, workshops and other events', 'conference://fahrplan', ), ( nav_conf, 21, 'person-video3', 'Self-organized Sessions', 'Self-organized Sessions', 'Workshops oder Diskussionsrunden in Assemblies oder den Workshopräumen', 'workshops or discussions in Assemblies or workshop rooms', 'conference://sos', ), ( nav_conf, 22, 'lightning', 'Lightning Talks', 'lightning talks', 'Deine fünf Minuten des Ruhms!', 'Give a short introduction on a topic', 'https://c3lt.de/', ), ( nav_conf, 50, 'camera-reels', 'Streams', 'Streams', 'Live-Streams der Vorträge', 'live streaming of talks', 'https://streaming.media.ccc.de/%SLUG%/', ), ( nav_conf, 110, 'book', 'Wiki', 'Wiki', 'gemeinsames Wissen', 'shared knowledge', 'wiki://start', ), ( nav_conf, 111, 'book', 'Letzte Änderungen (Wiki)', 'Recent changes (Wiki)', 'gemeinsames Wissen', 'shared knowledge', 'conference://static_page_global_history', ), ( nav_conf, 120, 'person-arms-up', 'Assemblies', 'Assemblies', 'Gruppen von Personen die dabei sind', 'groups of people you can meet', 'conference://assemblies', ), ( nav_conf, 300, 'lightbulb', 'Projekte', 'Projects', None, None, 'conference://projects', ), ( nav_conf, 400, 'award', 'Badges', 'Badges', "Schnapp' sie dir alle!", 'Gotta find them all!', 'conference://badges', ), ( nav_conf, 9001, 'wrench', 'Maschinenraum', 'Backoffice', 'Assemblies, Events, etc. verwalten', 'Manage Assemblies, Events, etc.', 'conference://backoffice', ), ( nav_my, 10, 'shield', 'Meine Badges', 'My Badges', 'entdecke den Congress', 'explore the congress', 'conference://manage_badges', ), ( nav_my, 200, 'stars', 'Mein Fahrplan', 'My Schedule', 'favorisierte Vorträge', 'your favorite events', 'conference://fahrplan?mode=list&my=y&kind=all', ), ( nav_visitors, 10, 'ticket-perforated', 'Tickets', 'Tickets', 'Wie? Wann? Wo?', 'how? when? where?', 'https://events.ccc.de/congress/%YEAR%/infos/tickets.html', ), ( nav_visitors, 15, 'buildings', 'Gebäude', 'Venue', 'Wie benutzen wir das Gebäude', 'How we use the venue', 'wiki://venue', ), ( nav_visitors, 20, 'clipboard-fill', 'Bulletin Board', 'Bulletin Board', 'ein digitales schwarzes Brett: suche und finde Dinge', 'a digital board: search & find stuff', 'conference://board', ), ( nav_visitors, 30, 'patch-question', 'FAQ', 'FAQ', 'häufig gestellte Fragen', 'frequently asked questions', 'https://events.ccc.de/congress/%YEAR%/infos/fundamentals-and-faq.html', ), ] def customize(s): return (s or '').replace('%SLUG%', conf.slug).replace('%YEAR%', str(year)) for parent, index, icon, label_de, label_en, title_de, title_en, url in entries: if not year and '%YEAR%' in url: continue parent.children.create( conference=conf, index=index, icon=icon, label_de=customize(label_de), label_en=customize(label_en), title_de=customize(title_de), title_en=customize(title_en), url=customize(url), ) class Command(BaseCommand): def add_arguments(self, parser): parser.add_argument('slug', type=str, nargs='?') parser.add_argument('--name', type=str) parser.add_argument('--year', type=int) parser.add_argument('--bootstrap', action='store_true') def handle(self, *args, **options): if not (slug := options.get('slug')): slug = input('SLUG of the new conference, e.g. "42c3": ') if not (name := options.get('name')): name = input('NAME of the new conference (long title): ') if not (year := options.get('year')): year = input("YEAR of the CCC congress (leave empty if it's something else): ") year = int(year or '0') print(f'Creating conference {slug} ({name}) for year {year}') # load our bootstrap fixtures if options.get('bootstrap'): call_command('loaddata', 'bootstrap_auth_groups.json') # create the new conference conf = Conference.objects.create( slug=slug, name=name, is_public=True, ) # for CCC Jahresendveranstaltung we can guess some timestamps from the current year alone if year > 1970: conf.start = datetime(year, 12, 27, 10, 0, 0, tzinfo=ZoneInfo('Europe/Berlin')) conf.end = datetime(year, 12, 30, 18, 0, 0, tzinfo=ZoneInfo('Europe/Berlin')) conf.registration_deadline = datetime(year, 12, 1, 0, 0, 0, tzinfo=ZoneInfo('Europe/Berlin')) # save everything conf.save() self.stdout.write(self.style.SUCCESS(f'Created conference {conf.pk}')) # fill in initial data seed_conference(conf, year=year) self.stdout.write(self.style.SUCCESS(f'Initial data set up for "{conf.slug}"'))