Por que outro guia?
Quando fui encarregado de fazer um rascunho de notificações por push, uma pesquisa rápida mostrou que já havia muitos artigos sobre a configuração de notificações por push no hub. Aqui estão os mais adequados, na minha opinião:
Como o JS funciona: notificações por push da WebNotificações de IMPULSO na Web Rápido e Fácil 924 /Trabalhadores de serviço. Web push e onde eles moramEstá tudo bem, mas pessoalmente eu realmente não tinha um guia simples e compreensível que me permitisse imediatamente, praticamente copiar e colar, fazer tudo funcionar imediatamente. Além disso, entre os manuais, não há python adaptado para suporte.
A configuração de notificações no final levou três dias e parece-me que isso é um pouco demais. Espero que meu artigo ajude alguém a configurar notificações push em três horas, em vez de três dias.
O projeto em que estou trabalhando é implementado no Django e descreverei o andamento do trabalho em relação a essa estrutura, mas aqueles que desejam podem facilmente adaptá-lo ao Flask ou a qualquer outra coisa.
Então vamos lá.
Nós pegamos as chaves
Sem chaves, naturalmente, elas não nos deixam em lugar nenhum, então vamos começar com elas. Para gerar as chaves, usei
py_vapid . Ele é instalado automaticamente junto com o
pywebpush , que ainda será necessário mais tarde; portanto, para não se levantar duas vezes, começaremos com o pywebpush:
> bin/pip install pywebpush < > > bin/vapid --applicationServerKey No private_key.pem file found. Do you want me to create one for you? (Y/n)Y Generating private_key.pem Generating public_key.pem Application Server Key = < Server Key>
O valor resultante da Chave do servidor de aplicativos é adicionado ao arquivo settings.py.
NOTIFICATION_KEY = < Server Key>
Além disso, precisaremos passar NOTIFICATION_KEY para o contexto. A maneira mais fácil de fazer isso é escrever
seu context_processor .
Fazendo um trabalhador de serviço
Trabalhador de serviço, que não sabe - este é um arquivo especial que é executado em segundo plano. Precisamos que ele mostre nossas notificações.
O código do operador de serviço mais simples seria assim:
self.addEventListener('push', function(event) { var message = JSON.parse(event.data.text());
E agora precisamos registrar nosso técnico de serviço. O processo é, em princípio, descrito
aqui . Portanto, brevemente:
function checkWorkerAndPushManager () { if (!('serviceWorker' in navigator)) { console.log('Workers are not supported.'); return; } if (!('PushManager' in window)) { console.log('Push notifications are not supported.'); return; } } function registerWorker () { window.addEventListener('load', function () { navigator.serviceWorker.register('/static/js/sw.js').then(function (registration) { console.log('ServiceWorker registration successful'); }, function (err) { console.log('ServiceWorker registration failed: ', err); return; }); }); return true; } var supported = checkWorkerAndPushManager(); if (supported){ var worker = registerWorker (); }
Ótimo, você pode verificar o trabalho do nosso profissional de serviço. Para fazer isso, acesse Ferramentas do desenvolvedor em um navegador, verifique se aparece uma mensagem no console sobre o registro bem-sucedido do woker e vá para a guia Aplicativo e selecione Operador de serviço à esquerda.

Se a notificação não aparecer, verifique se as notificações estão ativadas no seu navegador.
Bem, já sabemos como enviar notificações para nós mesmos. Legal, vamos seguir em frente.
Obter permissão do usuário para mostrar notificações
Após o registro do woker, peça permissão ao usuário para mostrar notificações.
function requestPermission() { return new Promise(function(resolve, reject) { const permissionResult = Notification.requestPermission(function(result) {
Não são necessários comentários para este código, ele simplesmente funciona.
Assine e salve sua assinatura
A assinatura também está na frente.
Você pode encontrar o código de inscrição aqui , mas não há nenhuma função urlBase64ToUint8Array usada, então eu codifico com ele.
NOTIFICATION_KEY = '{{ NOTIFICATION_KEY }}; function urlBase64ToUint8Array(base64String) { const padding = '='.repeat((4 - base64String.length % 4) % 4); const base64 = (base64String + padding) .replace(/\-/g, '+') .replace(/_/g, '/') ; const rawData = window.atob(base64); return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0))); } function subscribeUserToPush(key) { return navigator.serviceWorker.register('/static/path/to/js/sw.js') .then(function(registration) { var subscribeOptions = { userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(key), }; return registration.pushManager.subscribe(subscribeOptions) }) .then(function(pushSubscription) { sendSubscriptionToBackEnd(pushSubscription); }); }
(O urlBase64ToUint8Array usado aqui provavelmente é da categoria muletas e bicicletas, mas a tentativa de transcodificar os dados usando btoa não foi bem-sucedida, não sei por quê. Talvez alguém lhe diga).
Em seguida, enviamos os dados recebidos para o servidor. Eu tenho implementado assim:
function sendSubscriptionToBackEnd(subscription) { $.post( SAVE_REGISTRATION_URL, { 'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
Bem, então salvamos isso no servidor. Você pode seguir pela linha. Sim, não tente estabelecer um relacionamento de assinatura de usuário individual. Parece ser óbvio, mas de repente alguém gostaria.
Eu usei um modelo tão simples para salvar, ele será usado mais tarde, então darei a ele:
class UserSubscription(models.Model): subscription = models.CharField(max_length=500) user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='subscriptions')
O último passo. Enviando uma mensagem usando pywebpush
Tudo está no tutorial, sem sutilezas especiais. Bem, exceto que a mensagem é feita em uma estrutura que nosso técnico de serviço pode analisá-la.
import json from pywebpush import webpush, WebPushException from django.conf import settings from .models import UserSubscription def push_notification(user_id): user_subscriptions = UserSubscription.objects.filter(user_id=notification.user_id) for subscription in user_subscriptions: data = json.dumps({ 'title': 'Hello', 'body': 'there', }) try: webpush( subscription_info=json.loads(subscription.subscription), data=data, vapid_private_key='./private_key.pem', vapid_claims={ 'sub': 'mailto:{}'.format(settings.ADMIN_EMAIL), } ) notification.sent = True notification.save() except WebPushException as ex: print('I\'m sorry, Dave, but I can\'t do that: {}'.format(repr(ex))) print(ex)
Na verdade, você já pode chamar push_notification no shell do django e tentar iniciar.
Nesse código, seria bom interceptar a resposta com o status 410. Essa resposta diz que a assinatura foi cancelada e que seria bom excluir essas assinaturas do banco de dados.
Em conclusão
De fato, existe outra grande
biblioteca django-webpush . Talvez aqueles que trabalham com o Django devam começar com ele.
PS Feliz dia do programador!