1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-06-23 01:58:24 +02:00

Add notifications from Google Drive to automatically get updates from Google Sheets

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello
2024-04-06 21:55:46 +02:00
parent aac4fc59e6
commit c45071c038
6 changed files with 97 additions and 6 deletions

View File

@ -1,7 +1,9 @@
# Copyright (C) 2020 by Animath
# SPDX-License-Identifier: GPL-3.0-or-later
import asyncio
import csv
from concurrent.futures import ThreadPoolExecutor
from hashlib import sha1
from io import BytesIO
import os
import subprocess
@ -9,6 +11,7 @@ from tempfile import mkdtemp
from typing import Any, Dict
from zipfile import ZipFile
from asgiref.sync import sync_to_async
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
@ -23,7 +26,9 @@ from django.template.loader import render_to_string
from django.urls import reverse_lazy
from django.utils import timezone
from django.utils.crypto import get_random_string
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import CreateView, DetailView, FormView, RedirectView, TemplateView, UpdateView, View
from django.views.generic.detail import SingleObjectMixin
from django.views.generic.edit import FormMixin, ProcessFormView
@ -1874,6 +1879,29 @@ class NotationSheetsArchiveView(VolunteerMixin, DetailView):
return response
@method_decorator(csrf_exempt, name='dispatch')
class GSheetNotificationsView(View):
async def post(self, request, *args, **kwargs):
if not await Tournament.objects.filter(pk=kwargs['pk']).aexists():
return HttpResponse(status=404)
tournament = await Tournament.objects.prefetch_related('participations', 'pools').aget(pk=kwargs['pk'])
request.site.domain = "test.ynerant.fr"
expected_channel_id = sha1(f"{tournament.name}{timezone.now().date()}{request.site.domain}".encode()) \
.hexdigest()
if request.headers['X-Goog-Channel-ID'] != expected_channel_id:
raise ValueError(f"Invalid channel ID: {request.headers['X-Goog-Channel-ID']}")
# Run the parsing in dedicated executors since it takes time
executor = ThreadPoolExecutor()
async for pool in tournament.pools.prefetch_related('participations', 'passages__notes', 'juries').all():
asyncio.get_event_loop().run_in_executor(executor, pool.parse_spreadsheet)
asyncio.get_event_loop().run_in_executor(executor, tournament.parse_tweaks_spreadsheets)
return HttpResponse(status=204)
class PassageDetailView(LoginRequiredMixin, DetailView):
model = Passage