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}