Задать вопрос

Push уведомления на сайте?

Всем доброго утра, хочу сделать push уведомления на новостном сайте (проект написан на ASP .NET MVC). Хочу, чтобы когда зарегистрированный пользователь добавлял новость, админу сайта или модератору, подавался звуковой сигнал и всплывало уведомление, что добавлена новая новость и ее следует проверить и одобрить.
  • Как лучше это сделать?

Пока смотрю в сторону SignalR.
  • Может ли эта библиотека справится с моей хотелкой?
  • Мое недопонимание заключается в следующем, как мне определить именно тех людей которым я должен отправить это уведомление? Потому что в примерах с которыми я работал, ничего такого я не нашел.
  • Вопрос задан
  • 2798 просмотров
Подписаться 1 Оценить Комментировать
Решения вопроса 1
rpe4a
@rpe4a Автор вопроса
Вообщем всем спасибо за советы, но ближе всего оказался amf1k. Посмотрев и изучив документацию на
ASP.NET SignalR у меня криво косо получилось сделать то, что я хочу. Хотел бы описать инструкцию, может кому пригодится:
  1. Вы должны работать на платформе .NET;
  2. Ознакомиться с документацией по ASP.NET Identity
  3. Ознакомиться с документацией по SignalR
  4. Дальше добавляем через Nuget собственно сам SignalR в ваш проект;
  5. Прицепляем его к проекту;
  6. Создаем клиентский скрипт (я вынес его в отдельный файл и сделал ссылку на него на странице):
    $(function () {
       //определяем наш хаб
        var hub = $.connection.notificationHub;
        //метод хаба на клиенте, который будет вызван у всех подключенных клиентов, когда ему будет дана команда с сервера
        hub.client.sendNotification = function (message) {
            //выводим сообщение подключенным клиентам(в моем случае это будут только админы)
            $("#hubMessageConteiner")
                .append("<li>" + message + "<i title='Закрыть' class='fa fa-close fa-lg cursor-pointer'></i></li>")
                .find("li").show(200);
        };
        //создаем подключение к хабу, это метод start, если пользователь смог подключится к хабу, то вызывается функция done, если нет то будет вызываться функция fail
        $.connection.hub.start().done(function () {
            $('#Hub').click(function () {
                hub.server.send("Это push уведомление");
            });
        });
    });


  7. Создаем на бэкенд собственно наш Hub-class который будет обрабатывать эти уведомления, для хранения информации о подключивщихся к хабу, я использовал подход Хранение в памяти:
    public class NotificationHub:Hub
        {
    //хранилище подключений(тут я храню только администраторов)
            private readonly static ConnectionMapping<string> _connections = new ConnectionMapping<string>();
    
    //сейчас я вызываю этот метод с клиента, но его легко можно и вызвать на сервере, 
    //допустим в каком-нибудь методе контроллера, что я в последствии и собираюсь сделать,
    //потому что мне надо, чтобы при добавлении новости уведомления получал только администратор или модератор
            public void Send(string message)
            {
    
                var user = Context.User;
    //получаем всех подключенных админов и каждому отправляем уведомление
                foreach (var connectionId in _connections.GetConnections())
                {
    //если это сам админ то не надо отправлять
                    if (!user.IsAdmin())
                    {
    //тут мы вызываем метод на клиенте, который и отобразит наше уведомление
                        Clients.Client(connectionId).sendNotification(message);
                    }
                }
            }
    
            public override Task OnConnected()
            {
    //Хаб имеет доступ к контексту + я использую Identity (ссылку дал выше читайте), следовательно могу получить доступ к информации о подключенном пользователе:
                var user = Context.User;
    
                if (user.IsAdmin())
                {
                    string userId = Context.User.GetUserId();
    //запихиваем нашего подключенного пользователя если он админ в хранилище подключений, кстати каждому подключившемуся выдается ConnectionId, который можно получить из контекста и да он уникален и выдается каждый раз новый при подключении
                    _connections.Add(userId, Context.ConnectionId);
                }
                return base.OnConnected();
            }
    
            public override Task OnDisconnected(bool stopCalled)
            {
                var user = Context.User;
    
                if (user.IsAdmin())
                {
                    string userId = user.GetUserId();
    //если пользователь(админ) отключился, то убираем его из хранилища
                    _connections.Remove(userId, Context.ConnectionId);
                }
    
                return base.OnDisconnected(stopCalled);
            }
    
            public override Task OnReconnected()
            {
                var user = Context.User;
    
                if (user.IsAdmin())
                {
                    string userId = user.GetUserId();
    
                    if (!_connections.GetConnections(userId).Contains(Context.ConnectionId))
                    {
                        _connections.Add(userId, Context.ConnectionId);
                    }
                }
    
                return base.OnReconnected();
            }
        }
    
    //на всякий случай добавлю класс хранилища подключений, но он такой же как в документации
    public class ConnectionMapping<T>
        {
            private readonly Dictionary<T, HashSet<string>> _connections = new Dictionary<T, HashSet<string>>();
    
            public int Count
            {
                get
                {
                    return _connections.Count;
                }
            }
    
            public void Add(T key, string connectionId)
            {
                lock (_connections)
                {
                    HashSet<string> connections;
                    if (!_connections.TryGetValue(key, out connections))
                    {
                        connections = new HashSet<string>();
                        _connections.Add(key, connections);
                    }
    
                    lock (connections)
                    {
                        connections.Add(connectionId);
                    }
                }
            }
    
            public IEnumerable<string> GetConnections(T key)
            {
                HashSet<string> connections;
                if (_connections.TryGetValue(key, out connections))
                {
                    return connections;
                }
    
                return Enumerable.Empty<string>();
            }
    //добавил только вот этот метод для получения всех подключивщихся администраторов
            public IEnumerable<string> GetConnections()
            {
                HashSet<string> connections = new HashSet<string>();
    
                if (_connections.Any())
                {
                    foreach (var connection in _connections)
                    {
                        foreach (var connectionId in connection.Value)
                        {
                            connections.Add(connectionId);
                        }
                    }
                }
    
                return connections;
            }
    
            public void Remove(T key, string connectionId)
            {
                lock (_connections)
                {
                    HashSet<string> connections;
                    if (!_connections.TryGetValue(key, out connections))
                    {
                        return;
                    }
    
                    lock (connections)
                    {
                        connections.Remove(connectionId);
    
                        if (connections.Count == 0)
                        {
                            _connections.Remove(key);
                        }
                    }
                }
            }
        }


  8. Ну и собственно все. У меня работает, при клике на тестовую кнопку всем админам высылается уведомление. Всем добра и хорошего дня;
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
amf1k
@amf1k
1)Да может.
2) Вот тут можете посмотреть, может найдете что нибудь. А так в целом зависит все от того как у вас все устроено
Ответ написан
BupycNet
@BupycNet
Основатель PushAll
Можете использовать PushAll. Есть поддержка компьютеров смартфонов, есть уведомления на телеграм, можно дублировать на почту.
Можно отправлять отдельным пользователям уведомления при этом вкладки сайта могут быть закрыты.

Для андроид есть настройки звука и вибрации. В хром есть пропущенные уведомления и виджет для просмотра истории
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
22 дек. 2024, в 20:40
10000 руб./за проект
22 дек. 2024, в 20:34
3000 руб./за проект
22 дек. 2024, в 20:12
10000 руб./за проект