aboutsummaryrefslogblamecommitdiff
path: root/src/main/java/com/juick/www/api/Messages.java
blob: 969bef4f7ef972db2c5caee3355d927581a5af05 (plain) (tree)
1
2
  
                                 













                                                                           
                          
 

                               
                                                
                            
                                     
                                              
                                             

                                         
                                               
                                               
                                     
                                                          
                                                             
                                            
                                          
                                            
                                                 
                           
                           
                   


                 
               
                                                            
                       





                                            
                                                                
                          
                                       
                             

                                 
                              
                                                                        
                                                               
                                                                               
                                                                     
                                                                                   
     
                                
                                                                            
                                                         
                                                                                  
                                                                                 
                                                                                                                   
                                                          
                                                                             
                                                                                                       
                           
                                         
                                                         
                                         
                                                        



                                                                                 
                                                          
                                                 
                                                                                         
                                                      
                                                                  
                                                                                                             
                            
                                                          
                     
                                                                  
                                                                                                          
                                          
                                                                                              
                                                         
                                                                                                 
                                  
                        
                                                                                       
                    
                                                  
                
                                               
                                                                                                       
                                                    
                                                                           
                                                  
                                                              
                                                                                                   
                        
                                                      
                 
                                                     
                                                                        
                    
                                                                        
             
                                                                                 
                                                                                   
                    
     
 
                                   
                                                                                                     
                                                                          








                                                                          
 
                                            
                                                                               
                                                                          
                                                                                                                                 
                                                                                   
                    
     
 
                              
                                                                                                                     
                                                                       
                                                                                      
                                        
                                                                        
                                                   
                    
                                                                            
                                                                                           



                                                                                     

                                                                  






                                                                                                        
                 
             
                                          
     
 
                                                                                                      
                                                                                                                      
                                
                                     
                                                                  
                                                                                                  
                                                
                                                                                                             
                                                                        

                                            
                                                                                                  
                                                       
                                                                                              
                                                                      

                                                                                          


                                                
 
/*
 * Copyright (C) 2008-2023, Juick
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.juick.www.api;

import com.juick.model.Message;
import com.juick.model.Tag;
import com.juick.model.User;
import com.juick.service.activities.UpdateEvent;
import com.juick.www.WebApp;
import com.juick.model.CommandResult;
import com.juick.util.HttpBadRequestException;
import com.juick.util.HttpForbiddenException;
import com.juick.util.HttpNotFoundException;
import com.juick.service.MessagesService;
import com.juick.service.TagService;
import com.juick.service.UserService;
import com.juick.service.component.SystemEvent;
import io.swagger.v3.oas.annotations.Parameter;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.inject.Inject;
import java.io.IOException;
import java.util.*;

/**
 * @author ugnich
 */
@RestController
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public class Messages {

    @Inject
    private MessagesService messagesService;
    @Inject
    private UserService userService;
    @Inject
    private TagService tagService;
    @Inject
    private ApplicationEventPublisher applicationEventPublisher;
    @Inject
    private WebApp webApp;
    @Value("classpath:Transparent.gif")
    private Resource invisiblePixel;
    @Inject
    private User serviceUser;

    // TODO: serialize image urls

    @GetMapping({"/api/home"})
    public List<Message> getHome(@Parameter(hidden = true) User visitor,
            @RequestParam(defaultValue = "0") int before_mid) {
        int vuid = visitor.getUid();
        List<Integer> mids = messagesService.getMyFeed(vuid, before_mid, true);
        List<Message> msgs = messagesService.getMessages(vuid, mids);
        msgs.forEach(m -> m.getUser().setAvatar(webApp.getAvatarUrl(m.getUser())));
        return msgs;
    }

    @GetMapping("/api/messages")
    public List<Message> getMessages(@Parameter(hidden = true) User visitor,
            @RequestParam(required = false) String uname,
            @RequestParam(name = "before_mid", defaultValue = "0") Integer before,
            @RequestParam(required = false, defaultValue = "0") Integer daysback,
            @RequestParam(required = false) String withrecommended, @RequestParam(required = false) String popular,
            @RequestParam(required = false) String search,
            @RequestParam(required = false, defaultValue = "0") Integer page,
            @RequestParam(required = false) String media, @RequestParam(required = false) String tag) {
        List<Integer> mids;
        if (StringUtils.hasText(uname)) {
            User user = userService.getUserByName(uname);
            int privacy = 0;
            if (!visitor.isAnonymous()) {
                if (user.getUid() == visitor.getUid()) {
                    privacy = -3;
                } else if (userService.isInWL(user.getUid(), visitor.getUid())) {
                    privacy = -2;
                }
            }
            if (!user.isAnonymous() && !user.isBanned()) {
                if (StringUtils.hasText(media)) {
                    mids = messagesService.getUserPhotos(user.getUid(), privacy, before);
                } else if (StringUtils.hasText(tag)) {
                    Tag tagObject = tagService.getTag(tag, false);
                    if (tagObject != null) {
                        mids = messagesService.getUserTag(user.getUid(), tagObject.getId(), privacy, before);
                    } else {
                        throw new HttpNotFoundException();
                    }
                } else if (StringUtils.hasText(withrecommended)) {
                    mids = messagesService.getUserBlogWithRecommendations(user, visitor, privacy, before);
                } else if (daysback > 0) {
                    mids = messagesService.getUserBlogAtDay(user.getUid(), privacy, daysback);
                } else if (StringUtils.hasText(search)) {
                    mids = messagesService.getUserSearch(visitor, user.getUid(), search, privacy,
                            page);
                } else {
                    mids = messagesService.getUserBlog(user.getUid(), privacy, before);
                }
            } else {
                throw new HttpNotFoundException();
            }
        } else {
            if (StringUtils.hasText(popular)) {
                mids = messagesService.getUserBlogWithRecommendations(serviceUser, visitor, 0, before);
            } else if (StringUtils.hasText(media)) {
                mids = messagesService.getPhotos(visitor.getUid(), before);
            } else if (StringUtils.hasText(tag)) {
                Tag tagObject = tagService.getTag(tag, false);
                if (tagObject != null) {
                    mids = messagesService.getTag(tagObject.getId(), visitor.getUid(), before, 20);
                } else {
                    throw new HttpNotFoundException();
                }
            } else if (StringUtils.hasText(search)) {
                mids = messagesService.getSearch(visitor, search, page);
            } else {
                mids = messagesService.getAll(visitor.getUid(), before);
            }
        }
        List<Message> msgs = messagesService.getMessages(visitor.getUid(), mids);
        msgs.forEach(m -> m.getUser().setAvatar(webApp.getAvatarUrl(m.getUser())));
        return msgs;
    }

    @DeleteMapping("/api/messages")
    public CommandResult deleteMessage(@Parameter(hidden = true) User visitor, @RequestParam int mid,
            @RequestParam(required = false, defaultValue = "0") int rid) {
        if (rid > 0) {
            if (messagesService.deleteReply(visitor.getUid(), mid, rid)) {
                return CommandResult.fromString("Reply deleted");
            }
        }
        if (messagesService.deleteMessage(visitor.getUid(), mid)) {
            return CommandResult.fromString("Message deleted");
        }
        throw new HttpBadRequestException();
    }

    @GetMapping("/api/messages/discussions")
    public List<Message> getDiscussions(@Parameter(hidden = true) User visitor,
            @RequestParam(required = false, defaultValue = "0") Long to) {
        List<Message> msgs = messagesService.getMessages(visitor.getUid(), messagesService.getDiscussions(visitor.getUid(), to));
        msgs.forEach(m -> m.getUser().setAvatar(webApp.getAvatarUrl(m.getUser())));
        return msgs;
    }

    @GetMapping("/api/thread")
    public List<Message> getThread(@Parameter(hidden = true) User visitor, @RequestParam(defaultValue = "0") int mid,
            @RequestParam(defaultValue = "true") boolean showReplies) {
        Optional<Message> message = messagesService.getMessage(visitor.getUid(), mid);
        if (message.isPresent()) {
            Message msg = message.get();
            if (!messagesService.canViewThread(mid, visitor.getUid())) {
                throw new HttpForbiddenException();
            } else {
                msg.getUser().setAvatar(webApp.getAvatarUrl(msg.getUser()));
                msg.getRecommendations().forEach(r -> r.setAvatar(webApp.getAvatarUrl(r)));
                if (showReplies) {
                    List<Message> replies = messagesService.getReplies(visitor, mid);
                    // update replies counter to exclude banned replies
                    msg.setReplies(replies.size());
                    if (!visitor.isAnonymous()) {
                        if (replies.size() > 0) {
                            messagesService.setRead(visitor, mid);
                        }
                        userService.updateLastSeen(visitor);
                        applicationEventPublisher
                                .publishEvent(new SystemEvent(this, SystemActivity.read(visitor, msg)));
                    }
                    replies.add(0, msg);
                    return replies;
                } else {
                    return List.of(msg);
                }
            }
        }
        throw new HttpNotFoundException();
    }

    @GetMapping(value = "/api/thread/mark_read/{mid}-{rid}.gif", produces = MediaType.IMAGE_GIF_VALUE)
    public byte[] markThreadRead(@Parameter(hidden = true) User visitor, @PathVariable int mid, @PathVariable int rid)
            throws IOException {
        if (!visitor.isAnonymous()) {
            messagesService.setLastReadComment(visitor, mid, rid);
            Message msg = messagesService.getMessage(mid).orElseThrow(HttpNotFoundException::new);
            userService.updateLastSeen(visitor);
            applicationEventPublisher.publishEvent(new SystemEvent(this, SystemActivity.read(visitor, msg)));
            return IOUtils.toByteArray(invisiblePixel.getInputStream());
        }
        throw new HttpBadRequestException();
    }
    @PostMapping("/api/messages/set_privacy")
    public void togglePrivacy(@Parameter(hidden = true) User visitor, @RequestParam Integer mid) {
        if (visitor.isPremium() || visitor.isAdmin()) {
            var msg = messagesService.getMessage(mid).orElseThrow(HttpNotFoundException::new);
            messagesService.setFriendsOnly(mid, !msg.isFriendsOnly());
            msg = messagesService.getMessage(mid).orElseThrow(HttpNotFoundException::new);
            applicationEventPublisher.publishEvent(
                    new UpdateEvent(this, visitor, msg));
        } else {
            throw new HttpBadRequestException();
        }
    }
}