001/*
002 *  Copyright 2024 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.rocket.chat;
017
018import java.time.ZonedDateTime;
019import java.util.List;
020import java.util.Set;
021
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.commons.lang3.StringUtils;
025import org.quartz.JobExecutionContext;
026
027import org.ametys.core.schedule.progression.ContainerProgressionTracker;
028import org.ametys.core.ui.mail.StandardMailBodyHelper;
029import org.ametys.core.ui.mail.StandardMailBodyHelper.MailBodyBuilder;
030import org.ametys.core.ui.mail.StandardMailBodyHelper.MailBodyBuilder.UserInput;
031import org.ametys.core.user.User;
032import org.ametys.core.user.UserIdentity;
033import org.ametys.core.util.I18nUtils;
034import org.ametys.core.util.mail.SendMailHelper;
035import org.ametys.plugins.core.impl.schedule.AbstractStaticSchedulable;
036import org.ametys.plugins.rocket.chat.RocketChatHelper.Message;
037import org.ametys.plugins.rocket.chat.RocketChatHelper.RoomInfo;
038import org.ametys.runtime.config.Config;
039import org.ametys.runtime.i18n.I18nizableText;
040import org.ametys.web.repository.site.Site;
041import org.ametys.web.repository.site.SiteManager;
042
043/**
044 * Send a mail to every user that was not connected since the last execution
045 */
046public class OfflineMessagesSchedulable extends AbstractStaticSchedulable
047{
048    private RocketChatHelper _rocketChatHelper;
049    private I18nUtils _i18nUtils;
050    private SiteManager _siteManager;
051
052    @Override
053    public void service(ServiceManager manager) throws ServiceException
054    {
055        super.service(manager);
056        
057        _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE);
058        _rocketChatHelper = (RocketChatHelper) manager.lookup(RocketChatHelper.ROLE);
059        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
060    }
061    
062    public void execute(JobExecutionContext context, ContainerProgressionTracker progressionTracker) throws Exception
063    {
064        String hour = Config.getInstance().getValue("rocket.chat.rocket.offlinemails.hour");
065        if (StringUtils.isBlank(hour))
066        {
067            throw new IllegalStateException("The schedulable cannot work without a valued config parameter 'rocket.chat.rocket.offlinemails.hour'");
068        }
069        
070        // Working since yesterday at conf time
071        ZonedDateTime since = ZonedDateTime.now()
072                .minusDays(1)
073                .withHour(Integer.parseInt(StringUtils.substringBefore(hour, ":")))
074                .withMinute(Integer.parseInt(StringUtils.substringAfter(hour, ":")))
075                .withSecond(0)
076                .withNano(0);
077        
078        // Listing users with unread message
079        Set<UserIdentity> usersWithRecentMessages = _rocketChatHelper.getUsersWithRecentMessages(since);
080        
081        for (UserIdentity userWithRecentMessages : usersWithRecentMessages)
082        {
083            User user = _userManager.getUser(userWithRecentMessages);
084            if (user != null && StringUtils.isNotBlank(user.getEmail()))
085            {
086                // For each user, compare the last message date, with its last connection time
087                ZonedDateTime lastConnectionDate = user.getLastConnectionDate();
088                
089                ZonedDateTime userSince = lastConnectionDate != null && lastConnectionDate.compareTo(since) > 0 ? lastConnectionDate : since;
090                
091                int total = 0;
092                
093                
094                MailBodyBuilder bodyBuilder = StandardMailBodyHelper.newHTMLBody();
095                
096                Set<RoomInfo> threadsWithUnreadMessages = _rocketChatHelper.getThreadsWithUnreadMessages(userWithRecentMessages, userSince);
097                for (RoomInfo threadWithUnreadMessages : threadsWithUnreadMessages)
098                {
099                    // get the content of the messages in this room
100                    List<Message> lastMessages = _rocketChatHelper.getLastMessages(userWithRecentMessages, threadWithUnreadMessages.roomId(), threadWithUnreadMessages.unread(), userSince);
101                    if (lastMessages.size() > 0)
102                    {
103                        bodyBuilder.addUserInputs(lastMessages.stream().map(message -> new UserInput(_userManager.getUser(message.author()), message.date(), message.text())).toList(),
104                                new I18nizableText(threadWithUnreadMessages.roomLabel()));
105                    }
106                    
107                    total += lastMessages.size();
108                }
109                
110                if (total > 0)
111                {
112                    bodyBuilder.withTitle(new I18nizableText("plugin.rocket.chat", "PLUGINS_ROCKETCHAT_MAIL_BODY_TITLE"));
113                    
114                    String siteName = Config.getInstance().getValue("rocket.chat.rocket.offlinemails.link", false, "").trim();
115                    if (StringUtils.isNotBlank(siteName))
116                    {
117                        Site site = _siteManager.getSite(siteName);
118                        if (site == null)
119                        {
120                            getLogger().warn("The configuration parameter 'rocket.chat.rocket.offlinemails.link' leads to an unexisting site");
121                        }
122                        else
123                        {
124                            bodyBuilder.withLink(site.getUrl(), new I18nizableText("plugin.rocket.chat", "PLUGINS_ROCKETCHAT_MAIL_BODY_FOOTER"));
125                        }
126                    }
127                    
128                    
129                    String subject = _i18nUtils.translate(new I18nizableText("plugin.rocket.chat", "PLUGINS_ROCKETCHAT_MAIL_TITLE_" + (total == 1 ? "ONE" : "MANY"), List.of(Integer.toString(total))));
130                    SendMailHelper.newMail()
131                        .withSubject(subject)
132                        .withRecipient(user.getEmail())
133                        .withHTMLBody(bodyBuilder.build())
134                        .sendMail();
135                }
136            }
137        }
138    }
139
140}