Repository: nextcloud/appstore

Issue:
If an app is registered an /c/apps/APP_ID category should be created on help.nextcloud.com
To do this there need to be 3 additional settings in base.py

```
DISCOURSE_URL = 'https://help.nextcloud.com'
DISCOURSE_USER = None
DISCOURSE_TOKEN = None
```

If DISCOURSE_TOKEN is None, no requests should be made to the API. If a token is given, a new subcategory should be created in https://help.nextcloud.com/c/apps based on the app id e.g. https://help.nextcloud.com/c/apps/mail once a user registers an app.

https://meta.discourse.org/t/discourse-api-documentation/22706



Discussion:

Resolving patch:
diff --git a/nextcloudappstore/core/api/v1/views.py b/nextcloudappstore/core/api/v1/views.py
--- a/nextcloudappstore/core/api/v1/views.py
+++ b/nextcloudappstore/core/api/v1/views.py
@@ -1,3 +1,4 @@
+import requests
 from django.db import transaction
 from django.http import Http404
 from django.conf import settings
@@ -93,10 +94,34 @@ def post(self, request):
         app.save()
 
         if created:
+            if settings.DISCOURSE_TOKEN:
+                self._create_discourse_category(app_id)
             return Response(status=201)
         else:
             return Response(status=204)
 
+    def _create_discourse_category(self, app_id: str) -> None:
+        url = '%s/categories?api_key=%s&api_username=%s' % (
+            settings.DISCOURSE_URL.rstrip('/'),
+            settings.DISCOURSE_TOKEN,
+            settings.DISCOURSE_USER
+        )
+        data = {
+            'name': app_id,
+            'color': '3c3945',
+            'text_color': 'ffffff'
+        }
+        if settings.DISCOURSE_PARENT_CATEGORY_ID:
+            data['parent_category_id'] = settings.DISCOURSE_PARENT_CATEGORY_ID
+
+        # ignore requests errors because there can be many issues and we do not
+        # want to abort app registration just because the forum is down or
+        # leak sensitive data like tokens or users
+        try:
+            requests.post(url, data=data)
+        except requests.HTTPError:
+            pass
+
 
 class AppReleaseView(DestroyAPIView):
     authentication_classes = (authentication.TokenAuthentication,
diff --git a/nextcloudappstore/core/views.py b/nextcloudappstore/core/views.py
--- a/nextcloudappstore/core/views.py
+++ b/nextcloudappstore/core/views.py
@@ -64,6 +64,7 @@ def post(self, request, id):
 
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
+        context['DISCOURSE_URL'] = settings.DISCOURSE_URL.rstrip('/')
         context['rating_form'] = AppRatingForm()
         context['user_has_rated_app'] = False
         if self.request.user.is_authenticated:
@@ -120,7 +121,6 @@ def get_context_data(self, **kwargs):
             versions))
         context['releases_by_platform_v'] = \
             self._sort_by_platform_v(all_releases)
-
         return context
 
     def _sort_by_platform_v(self, releases_by_platform, reverse=True):
diff --git a/nextcloudappstore/settings/base.py b/nextcloudappstore/settings/base.py
--- a/nextcloudappstore/settings/base.py
+++ b/nextcloudappstore/settings/base.py
@@ -283,3 +283,8 @@
     'iframe': ['width', 'height', 'frameborder', 'src', 'allowfullscreen'],
     'q': ['cite'],
 }
+
+DISCOURSE_URL = 'https://help.nextcloud.com'
+DISCOURSE_USER = None
+DISCOURSE_TOKEN = None
+DISCOURSE_PARENT_CATEGORY_ID = 26


Test patch: