Package ru.org.linux.topic

Source Code of ru.org.linux.topic.TopicService

/*
* Copyright 1998-2014 Linux.org.ru
*    Licensed under the Apache License, Version 2.0 (the "License");
*    you may not use this file except in compliance with the License.
*    You may obtain a copy of the License at
*
*        http://www.apache.org/licenses/LICENSE-2.0
*
*    Unless required by applicable law or agreed to in writing, software
*    distributed under the License is distributed on an "AS IS" BASIS,
*    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*    See the License for the specific language governing permissions and
*    limitations under the License.
*/

package ru.org.linux.topic;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import ru.org.linux.gallery.ImageDao;
import ru.org.linux.gallery.Screenshot;
import ru.org.linux.group.Group;
import ru.org.linux.poll.PollDao;
import ru.org.linux.poll.PollNotFoundException;
import ru.org.linux.poll.PollVariant;
import ru.org.linux.section.Section;
import ru.org.linux.section.SectionService;
import ru.org.linux.site.ScriptErrorException;
import ru.org.linux.spring.SiteConfig;
import ru.org.linux.spring.dao.DeleteInfoDao;
import ru.org.linux.tag.TagModificationService;
import ru.org.linux.tag.TagName;
import ru.org.linux.user.*;
import ru.org.linux.util.LorHttpUtils;
import ru.org.linux.util.bbcode.LorCodeService;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.*;

import static com.google.common.base.Predicates.*;

@Service
public class TopicService {
  private static final Logger logger = LoggerFactory.getLogger(TopicService.class);

  @Autowired
  private TopicDao topicDao;

  @Autowired
  private SectionService sectionService;

  @Autowired
  private SiteConfig siteConfig;

  @Autowired
  private ImageDao imageDao;

  @Autowired
  private PollDao pollDao;

  @Autowired
  private UserEventService userEventService;

  @Autowired
  private TagModificationService tagService;

  @Autowired
  private TopicTagService topicTagService;

  @Autowired
  private UserTagService userTagService;

  @Autowired
  private UserDao userDao;

  @Autowired
  private DeleteInfoDao deleteInfoDao;

  @Autowired
  private LorCodeService lorCodeService;

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
  public int addMessage(
          HttpServletRequest request,
          AddTopicRequest form,
          String message,
          Group group,
          User user,
          Screenshot scrn,
          Topic previewMsg
  ) throws IOException, ScriptErrorException {
    final int msgid = topicDao.saveNewMessage(
            previewMsg,
            user,
            message,
            request.getHeader("User-Agent"),
            group
    );

    Section section = sectionService.getSection(group.getSectionId());

    if (section.isImagepost() && scrn == null) {
      throw new ScriptErrorException("scrn==null!?");
    }

    if (scrn!=null) {
      Screenshot screenShot = scrn.moveTo(siteConfig.getHTMLPathPrefix() + "/gallery", Integer.toString(msgid));

      imageDao.saveImage(
              msgid,
              "gallery/" + screenShot.getMainFile().getName(),
              "gallery/" + screenShot.getIconFile().getName()
      );
    }

    if (section.isPollPostAllowed()) {
      pollDao.createPoll(Arrays.asList(form.getPoll()), form.isMultiSelect(), msgid);
    }

    List<String> tags = TagName.parseAndSanitizeTags(form.getTags());

    topicTagService.updateTags(msgid, ImmutableList.<String>of(), tags);

    if (!previewMsg.isDraft()) {
      if (section.isPremoderated()) {
        sendEvents(message, msgid, ImmutableList.<String>of(), user.getId());
      } else {
        sendEvents(message, msgid, tags, user.getId());
      }
    }

    String logmessage = "Написана тема " + msgid + ' ' + LorHttpUtils.getRequestIP(request);
    logger.info(logmessage);

    return msgid;
  }

  /**
   * Отправляет уведомления типа REF (ссылка на пользователя) и TAG (уведомление по тегу)
   *
   * @param message текст сообщения
   * @param msgid идентификатор сообщения
   * @param author автор сообщения (ему не будет отправлено уведомление)
   */
  private void sendEvents(String message, int msgid, List<String> tags, int author) {
    Set<Integer> notifiedUsers = userEventService.getNotifiedUsers(msgid);

    Set<User> userRefs = lorCodeService.getReplierFromMessage(message);

    // оповещение пользователей по тегам
    List<Integer> userIdListByTags = userTagService.getUserIdListByTags(author, tags);

    final Set<Integer> userRefIds = new HashSet<>();
    for (User userRef : userRefs) {
      if (!notifiedUsers.contains(userRef.getId())) {
        userRefIds.add(userRef.getId());
      }
    }

    // не оповещать пользователей. которые ранее были оповещены через упоминание
    Iterable<Integer> tagUsers = Iterables.filter(
            userIdListByTags,
            not(or(in(userRefIds), in(notifiedUsers)))
    );

    userEventService.addUserRefEvent(userRefIds, msgid);
    userEventService.addUserTagEvent(tagUsers, msgid);
  }

  /**
   * Удаление топика и если удаляет модератор изменить автору score
   * @param message удаляемый топик
   * @param user удаляющий пользователь
   * @param reason причина удаления
   * @param bonus дельта изменения score автора топика
   */
  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
  public void deleteWithBonus(Topic message, User user, String reason, int bonus) {
    if (bonus>20 || bonus<0) {
      throw new IllegalArgumentException("Некорректное значение bonus");
    }

    if (user.isModerator() && bonus!=0 && user.getId()!=message.getUid() && !message.isDraft()) {
      boolean deleted = deleteTopic(message.getId(), user, reason, -bonus);

      if (deleted) {
        userDao.changeScore(message.getUid(), -bonus);
      }
    } else {
      deleteTopic(message.getId(), user, reason, 0);
    }
  }

  private boolean deleteTopic(int mid, User moderator, String reason, int bonus) {
    boolean deleted = topicDao.delete(mid);

    if (deleted) {
      deleteInfoDao.insert(mid, moderator, reason, bonus);
      userEventService.processTopicDeleted(ImmutableList.of(mid));
    }

    return deleted;
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
  public List<Integer> deleteByIPAddress(String ip, Timestamp startTime, User moderator, String reason) {
    List<Integer> topicIds = topicDao.getAllByIPForUpdate(ip, startTime);

    return massDelete(moderator, topicIds, reason);
  }

  /**
   * Массовое удаление всех топиков пользователя.
   *
   * @param user      пользователь для экзекуции
   * @param moderator экзекутор-модератор
   * @return список удаленных топиков
   * @throws UserNotFoundException генерирует исключение если пользователь отсутствует
   */
  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
  public List<Integer> deleteAllByUser(User user, User moderator) {
    List<Integer> topics = topicDao.getUserTopicForUpdate(user);

    return massDelete(moderator, topics, "Блокировка пользователя с удалением сообщений");
  }

  private List<Integer> massDelete(User moderator, Iterable<Integer> topics, String reason) {
    List<Integer> deletedTopics = new ArrayList<>();

    for (int mid : topics) {
      boolean deleted = topicDao.delete(mid);

      if (deleted) {
        deleteInfoDao.insert(mid, moderator, reason, 0);
        deletedTopics.add(mid);
      }
    }

    userEventService.processTopicDeleted(deletedTopics);

    return deletedTopics;
  }

  private static boolean sendTagEventsNeeded(Section section, Topic oldMsg, boolean commit) {
    boolean needCommit = section.isPremoderated() && !oldMsg.isCommited();
    boolean fresh = oldMsg.getEffectiveDate().isAfter(DateTime.now().minusMonths(1));

    return commit || (!needCommit && fresh);
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
  public boolean updateAndCommit(
          Topic newMsg,
          Topic oldMsg,
          User user,
          List<String> newTags,
          String newText,
          boolean commit,
          Integer changeGroupId,
          int bonus,
          List<PollVariant> pollVariants,
          boolean multiselect,
          Map<Integer, Integer> editorBonus
  )  {
    boolean modified = topicDao.updateMessage(oldMsg, newMsg, user, newTags, newText);

    if (!newMsg.isDraft() && !newMsg.isExpired()) {
      Section section = sectionService.getSection(oldMsg.getSectionId());

      if (sendTagEventsNeeded(section, oldMsg, commit)) {
        sendEvents(newText, oldMsg.getId(), newTags, oldMsg.getUid());
      } else {
        sendEvents(newText, oldMsg.getId(), ImmutableList.<String>of(), oldMsg.getUid());
      }
    }

    try {
      if (pollVariants!=null && pollDao.updatePoll(oldMsg, pollVariants, multiselect)) {
        modified = true;
      }
    } catch (PollNotFoundException e) {
      throw new RuntimeException(e);
    }

    if (oldMsg.isDraft() && !newMsg.isDraft()) {
      topicDao.publish(newMsg);
    }

    if (commit) {
      if (changeGroupId != null) {
        if (oldMsg.getGroupId() != changeGroupId) {
          topicDao.changeGroup(oldMsg, changeGroupId);
        }
      }

      commit(oldMsg, user, bonus, editorBonus);
    }

    if (modified) {
      logger.info("сообщение " + oldMsg.getId() + " исправлено " + user.getNick());
    }

    return modified;
  }

  private void commit(Topic msg, User commiter, int bonus, Map<Integer, Integer> editorBonus) {
    if (bonus < 0 || bonus > 20) {
      throw new IllegalStateException("Неверное значение bonus");
    }

    if (msg.isDraft()) {
      topicDao.publish(msg);
    }

    topicDao.commit(msg, commiter);

    userDao.changeScore(msg.getUid(), bonus);

    if (editorBonus!=null) {
      for (Map.Entry<Integer, Integer> entry : editorBonus.entrySet()) {
        userDao.changeScore(entry.getKey(), entry.getValue());
      }
    }
  }
}
TOP

Related Classes of ru.org.linux.topic.TopicService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.