Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
/.idea/
49 changes: 49 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ru.yandex.practicum</groupId>
<artifactId>catsgram</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>catsgram</name>
<description>Мини-версия популярной соцсети с фотографиями котов.</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.3</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ru.yandex.practicum.catsgram;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

//@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@SpringBootApplication
public class CatsgramApplication {
public static void main(String[] args) {
SpringApplication.run(CatsgramApplication.class, args);
}

}
10 changes: 10 additions & 0 deletions src/main/java/ru/yandex/practicum/catsgram/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ru.yandex.practicum.catsgram;

import java.util.Set;

public class Constants {
public static final String DESCENDING_ORDER = "desc";
public static final String ASCENDING_ORDER = "asc";

public static final Set<String> SORTS = Set.of(ASCENDING_ORDER, DESCENDING_ORDER);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package ru.yandex.practicum.catsgram.controller;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import ru.yandex.practicum.catsgram.exception.IncorrectParameterException;
import ru.yandex.practicum.catsgram.exception.InvalidEmailException;
import ru.yandex.practicum.catsgram.exception.PostNotFoundException;
import ru.yandex.practicum.catsgram.exception.UserAlreadyExistException;
import ru.yandex.practicum.catsgram.exception.UserNotFoundException;
import ru.yandex.practicum.catsgram.model.ErrorResponse;

@RestControllerAdvice
public class ErrorHandler {

@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleIncorrectParameterException(final IncorrectParameterException e) {
return new ErrorResponse(
String.format("Ошибка с полем \"%s\".", e.getParameter())
);
}

@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handleInvalidEmailException(final InvalidEmailException e) {
return new ErrorResponse(
e.getMessage()
);
}

@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handlePostNotFoundException(final PostNotFoundException e) {
return new ErrorResponse(
e.getMessage()
);
}

@ExceptionHandler
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleUserNotFoundException(final UserNotFoundException e) {
return new ErrorResponse(
e.getMessage()
);
}

@ExceptionHandler
@ResponseStatus(HttpStatus.CONFLICT)
public ErrorResponse handlePostNotFoundException(final UserAlreadyExistException e) {
return new ErrorResponse(
e.getMessage()
);
}

@ExceptionHandler
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorResponse handleThrowable(final Throwable e) {
return new ErrorResponse(
"Произошла непредвиденная ошибка."
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ru.yandex.practicum.catsgram.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import ru.yandex.practicum.catsgram.exception.IncorrectParameterException;
import ru.yandex.practicum.catsgram.model.Post;
import ru.yandex.practicum.catsgram.service.PostService;

import java.util.Collection;
import java.util.List;

import static ru.yandex.practicum.catsgram.Constants.DESCENDING_ORDER;
import static ru.yandex.practicum.catsgram.Constants.SORTS;

@RestController
public class PostController {
private final PostService postService;

public PostController(PostService postService) {
this.postService = postService;
}

@GetMapping("/posts")
public Collection<Post> findAll(@RequestParam String userId) {
return postService.findPostsByUser(userId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ru.yandex.practicum.catsgram.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import ru.yandex.practicum.catsgram.model.Post;
import ru.yandex.practicum.catsgram.service.FeedService;

import java.util.List;

@RestController()
@RequestMapping("/feed")
public class PostFeedController {

private final FeedService feedService;

public PostFeedController(FeedService feedService) {
this.feedService = feedService;
}

@GetMapping
List<Post> getFriendsFeed(@RequestParam("userId") String userId, @RequestParam(defaultValue = "10") int max) {
return feedService.getFeedFor(userId, max);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ru.yandex.practicum.catsgram.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.yandex.practicum.catsgram.service.HackCatService;

import java.util.Optional;

@RestController
public class SimpleController {
private final HackCatService hackCatService;
public SimpleController(HackCatService hackCatService) {
this.hackCatService = hackCatService;
}

@GetMapping("/do-hack")
public Optional<String> doHack(){
return hackCatService.doHackNow()
.map(password -> "Ура! Пароль подобран: " + password)
.or(() -> Optional.of("Не удалось подобрать пароль. "
+ " Проверьте состояние и настройки базы данных."));
}

@GetMapping("/home")
public String homePage() {
return "Котограм";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package ru.yandex.practicum.catsgram.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import ru.yandex.practicum.catsgram.model.User;
import ru.yandex.practicum.catsgram.service.UserService;

import java.util.Optional;

@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;

public UserController(UserService userService) {
this.userService = userService;
}

@GetMapping("/{login}")
public Optional<User> getUser(@PathVariable String login){
return userService.findUserById(login);
}
}
9 changes: 9 additions & 0 deletions src/main/java/ru/yandex/practicum/catsgram/dao/FollowDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ru.yandex.practicum.catsgram.dao;
import ru.yandex.practicum.catsgram.model.Post;

import java.util.List;

public interface FollowDao {
List<Post> getFollowFeed(String userId, int max);
}

10 changes: 10 additions & 0 deletions src/main/java/ru/yandex/practicum/catsgram/dao/PostDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ru.yandex.practicum.catsgram.dao;

import ru.yandex.practicum.catsgram.model.Post;
import ru.yandex.practicum.catsgram.model.User;

import java.util.Collection;

public interface PostDao {
Collection<Post> findPostsByUser(User user);
}
9 changes: 9 additions & 0 deletions src/main/java/ru/yandex/practicum/catsgram/dao/UserDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ru.yandex.practicum.catsgram.dao;

import ru.yandex.practicum.catsgram.model.User;

import java.util.Optional;

public interface UserDao {
Optional<User> findUserById(String id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package ru.yandex.practicum.catsgram.dao.impl;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import ru.yandex.practicum.catsgram.dao.FollowDao;
import ru.yandex.practicum.catsgram.dao.PostDao;
import ru.yandex.practicum.catsgram.dao.UserDao;
import ru.yandex.practicum.catsgram.model.Follow;
import ru.yandex.practicum.catsgram.model.Post;
import ru.yandex.practicum.catsgram.model.User;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class FollowDaoImpl implements FollowDao {

private final JdbcTemplate jdbcTemplate;
private final UserDao userDao;
private final PostDao postDao;

public FollowDaoImpl(JdbcTemplate jdbcTemplate, UserDao userDao, PostDao postDao) {
this.jdbcTemplate = jdbcTemplate;
this.userDao = userDao;
this.postDao = postDao;
}

@Override
public List<Post> getFollowFeed(String userId, int max) {
// получаем все подписки пользователя
String sql = "select * from cat_follow where follower_id = ?";
List<Follow> follows = jdbcTemplate.query(sql, (rs, rowNum) -> makeFollow(rs), userId);

// выгружаем авторов на которых подписан пользователь
Set<User> authors = follows.stream()
.map(Follow::getAuthor)
.map(userDao::findUserById)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toSet());

if(authors.isEmpty()) {
return Collections.emptyList();
}

// выгружаем посты полученных выше авторов
return authors.stream()
.map(postDao::findPostsByUser)
.flatMap(Collection::stream)
// сортируем от новых к старым
.sorted(Comparator.comparing(Post::getCreationDate).reversed())
// отбрасываем лишнее
.limit(max)
.collect(Collectors.toList());
}

private Follow makeFollow(ResultSet rs) throws SQLException {
return new Follow(rs.getString("author_id"), rs.getString("follower_id"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package ru.yandex.practicum.catsgram.dao.impl;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import ru.yandex.practicum.catsgram.dao.PostDao;
import ru.yandex.practicum.catsgram.model.Post;
import ru.yandex.practicum.catsgram.model.User;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.Collection;

@Component
public class PostDaoImpl implements PostDao {
private final JdbcTemplate jdbcTemplate;

public PostDaoImpl(JdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}

@Override
public Collection<Post> findPostsByUser(User user) {
// метод принимает в виде аргумента строку запроса, преобразователь и аргумент — id пользователя
String sql = "select * from cat_post where author_id = ? order by creation_date desc";

return jdbcTemplate.query(sql, (rs, rowNum) -> makePost(user, rs), user.getId());
}

private Post makePost(User user, ResultSet rs) throws SQLException {
// используем конструктор, методы ResultSet
// и готовое значение user
Integer id = rs.getInt("id");
String description = rs.getString("description");
String photoUrl = rs.getString("photo_url");

// Получаем дату и конвертируем её из sql.Date в time.LocalDate
LocalDate creationDate = rs.getDate("creation_date").toLocalDate();

return new Post(id, user, description, photoUrl, creationDate);
}
}
Loading