from typing import Literal from django.http import HttpResponse from ninja import Query from ninja_extra import ControllerBase, api_controller, paginate, route from ninja_extra.pagination import PageNumberPaginationExtra from ninja_extra.permissions import IsAuthenticated from ninja_extra.schemas import PaginatedResponseSchema from com.ics_calendar import IcsCalendar from com.models import News, NewsDate from com.schemas import NewsDateFilterSchema, NewsDateSchema from core.auth.api_permissions import HasPerm from core.views.files import send_raw_file @api_controller("/calendar") class CalendarController(ControllerBase): @route.get("/internal.ics", url_name="calendar_internal") def calendar_internal(self): return send_raw_file(IcsCalendar.get_internal()) @route.get( "/unpublished.ics", permissions=[IsAuthenticated], url_name="calendar_unpublished", ) def calendar_unpublished(self): return HttpResponse( IcsCalendar.get_unpublished(self.context.request.user), content_type="text/calendar", ) @api_controller("/news") class NewsController(ControllerBase): @route.patch( "/{int:news_id}/publish", permissions=[HasPerm("com.moderate_news")], url_name="moderate_news", ) def publish_news(self, news_id: int): news = self.get_object_or_exception(News, id=news_id) if not news.is_published: news.is_published = True news.moderator = self.context.request.user news.save() @route.patch( "/{int:news_id}/unpublish", permissions=[HasPerm("com.moderate_news")], url_name="unpublish_news", ) def unpublish_news(self, news_id: int): news = self.get_object_or_exception(News, id=news_id) if news.is_published: news.is_published = False news.moderator = self.context.request.user news.save() @route.delete( "/{int:news_id}", permissions=[HasPerm("com.delete_news")], url_name="delete_news", ) def delete_news(self, news_id: int): news = self.get_object_or_exception(News, id=news_id) news.delete() @route.get( "/date", url_name="fetch_news_dates", response=PaginatedResponseSchema[NewsDateSchema], ) @paginate(PageNumberPaginationExtra, page_size=50) def fetch_news_dates( self, filters: Query[NewsDateFilterSchema], text_format: Literal["md", "html"] = "md", ): return filters.filter( NewsDate.objects.viewable_by(self.context.request.user) .order_by("start_date") .select_related("news", "news__club") )