Рабочий вариант с ответами
This commit is contained in:
parent
03aadeb72b
commit
adb5c6124f
@ -5,7 +5,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.sadtech.bot.gitlab.context.service.CleanService;
|
||||
import org.sadtech.bot.gitlab.core.service.parser.DiscussionParser;
|
||||
import org.sadtech.bot.gitlab.core.service.parser.MergeRequestParser;
|
||||
import org.sadtech.bot.gitlab.core.service.parser.NoteParser;
|
||||
import org.sadtech.bot.gitlab.core.service.parser.PipelineParser;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -22,7 +21,6 @@ public class SchedulerService {
|
||||
|
||||
private final PipelineParser pipelineParser;
|
||||
private final MergeRequestParser mergeRequestParser;
|
||||
private final NoteParser noteParser;
|
||||
private final CleanService cleanService;
|
||||
private final DiscussionParser discussionParser;
|
||||
|
||||
|
@ -122,6 +122,10 @@
|
||||
<column name="id" type="varchar(200)">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="responsible_id" type="int">
|
||||
<constraints nullable="false" foreignKeyName="discussion_responsible_id_person_id"
|
||||
references="person(id)"/>
|
||||
</column>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
|
||||
@ -132,7 +136,8 @@
|
||||
references="discussion(id)" deleteCascade="true"/>
|
||||
</column>
|
||||
<column name="merge_request_id" type="int">
|
||||
<constraints nullable="false"/>
|
||||
<constraints foreignKeyName="discussion_merge_request_merge_request_id" references="merge_request(id)"
|
||||
deleteCascade="true" nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
|
||||
|
@ -32,6 +32,10 @@ public class Discussion implements BasicEntity<String> {
|
||||
@Column(name = "id")
|
||||
private String id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "responsible_id")
|
||||
private Person responsible;
|
||||
|
||||
@ManyToOne()
|
||||
@JoinTable(
|
||||
name = "discussion_merge_request",
|
||||
|
@ -62,10 +62,6 @@ public class Note implements BasicEntity<Long> {
|
||||
@JoinColumn(name = "resolved_id")
|
||||
private Person resolvedBy;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "responsible_id")
|
||||
private Person responsible;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "discussion_id")
|
||||
private Discussion discussion;
|
||||
|
@ -6,8 +6,6 @@ import org.sadtech.haiti.context.page.Pagination;
|
||||
import org.sadtech.haiti.context.page.Sheet;
|
||||
import org.sadtech.haiti.context.repository.SimpleManagerRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* // TODO: 08.09.2020 Добавить описание.
|
||||
*
|
||||
@ -17,6 +15,4 @@ public interface NoteRepository extends SimpleManagerRepository<Note, Long> {
|
||||
|
||||
Sheet<Note> findAllByResolved(boolean resolved, @NonNull Pagination pagination);
|
||||
|
||||
List<Note> findAllByResponsibleIdAndResolved(@NonNull Long userId, boolean resolved);
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,4 @@ public interface DiscussionService extends SimpleManagerService<Discussion, Stri
|
||||
|
||||
void answer(@NonNull String discussionId, @NonNull String text);
|
||||
|
||||
void linkMergeRequest(@NonNull String discussionId, @NonNull Long mergeRequestId);
|
||||
|
||||
}
|
||||
|
@ -6,12 +6,8 @@ import org.sadtech.haiti.context.page.Pagination;
|
||||
import org.sadtech.haiti.context.page.Sheet;
|
||||
import org.sadtech.haiti.context.service.SimpleManagerService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface NoteService extends SimpleManagerService<Note, Long> {
|
||||
|
||||
Sheet<Note> getAllByResolved(boolean resolved, @NonNull Pagination pagination);
|
||||
|
||||
List<Note> getAllPersonTask(@NonNull Long userId, boolean resolved);
|
||||
|
||||
}
|
||||
|
@ -2,8 +2,10 @@ package org.sadtech.bot.gitlab.core.service.impl;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import org.sadtech.bot.gitlab.context.domain.PersonInformation;
|
||||
import org.sadtech.bot.gitlab.context.domain.entity.Discussion;
|
||||
@ -89,13 +91,16 @@ public class DiscussionServiceImpl extends AbstractSimpleManagerService<Discussi
|
||||
@Override
|
||||
public void answer(@NonNull String discussionId, @NonNull String text) {
|
||||
final Discussion discussion = discussionRepository.findById(discussionId)
|
||||
.orElseThrow(() -> new org.sadtech.haiti.context.exception.NotFoundException("Note " + discussionId + " не найдена"));
|
||||
.orElseThrow(() -> new org.sadtech.haiti.context.exception.NotFoundException("Дисскусия " + discussionId + " не найдена"));
|
||||
final MergeRequest mergeRequest = discussion.getMergeRequest();
|
||||
final Long projectId = mergeRequest.getProjectId();
|
||||
|
||||
final String requestUrl = MessageFormat.format(gitlabProperty.getUrlNewNote(), projectId, mergeRequest.getTwoId(), discussion.getId(), text);
|
||||
|
||||
RequestBody formBody = new FormBody.Builder().build();
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.post(formBody)
|
||||
.header(AUTHORIZATION, BEARER + personProperty.getToken())
|
||||
.url(requestUrl)
|
||||
.build();
|
||||
@ -110,11 +115,6 @@ public class DiscussionServiceImpl extends AbstractSimpleManagerService<Discussi
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void linkMergeRequest(@NonNull String discussionId, @NonNull Long mergeRequestId) {
|
||||
|
||||
}
|
||||
|
||||
protected void notificationPersonal(@NonNull Note note) {
|
||||
Matcher matcher = PATTERN.matcher(note.getBody());
|
||||
Set<String> recipientsLogins = new HashSet<>();
|
||||
|
@ -2,70 +2,34 @@ package org.sadtech.bot.gitlab.core.service.impl.note;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.sadtech.bot.gitlab.context.domain.PersonInformation;
|
||||
import org.sadtech.bot.gitlab.context.domain.entity.Note;
|
||||
import org.sadtech.bot.gitlab.context.domain.notify.comment.CommentNotify;
|
||||
import org.sadtech.bot.gitlab.context.exception.NotFoundException;
|
||||
import org.sadtech.bot.gitlab.context.repository.NoteRepository;
|
||||
import org.sadtech.bot.gitlab.context.service.NoteService;
|
||||
import org.sadtech.bot.gitlab.context.service.NotifyService;
|
||||
import org.sadtech.bot.gitlab.context.service.PersonService;
|
||||
import org.sadtech.haiti.context.page.Pagination;
|
||||
import org.sadtech.haiti.context.page.Sheet;
|
||||
import org.sadtech.haiti.core.service.AbstractSimpleManagerService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class NoteServiceImpl extends AbstractSimpleManagerService<Note, Long> implements NoteService {
|
||||
|
||||
protected static final Pattern PATTERN = Pattern.compile("@[\\w]+");
|
||||
|
||||
private final NoteRepository noteRepository;
|
||||
private final PersonService personService;
|
||||
|
||||
private final NotifyService notifyService;
|
||||
private final PersonInformation personInformation;
|
||||
|
||||
public NoteServiceImpl(
|
||||
NoteRepository noteRepository,
|
||||
PersonService personService,
|
||||
NotifyService notifyService,
|
||||
PersonInformation personInformation
|
||||
) {
|
||||
public NoteServiceImpl(NoteRepository noteRepository) {
|
||||
super(noteRepository);
|
||||
this.noteRepository = noteRepository;
|
||||
this.personService = personService;
|
||||
this.notifyService = notifyService;
|
||||
this.personInformation = personInformation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Note create(@NonNull Note note) {
|
||||
personService.create(note.getAuthor());
|
||||
|
||||
final Note newNote = noteRepository.save(note);
|
||||
notificationPersonal(note);
|
||||
return newNote;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Note update(@NonNull Note note) {
|
||||
final Note oldNote = noteRepository.findById(note.getId())
|
||||
.orElseThrow(() -> new NotFoundException("Комментарий не найден"));
|
||||
|
||||
if (!oldNote.getUpdated().equals(note.getUpdated())) {
|
||||
note.setWebUrl(oldNote.getWebUrl());
|
||||
return noteRepository.save(note);
|
||||
}
|
||||
|
||||
return oldNote;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -73,27 +37,4 @@ public class NoteServiceImpl extends AbstractSimpleManagerService<Note, Long> im
|
||||
return noteRepository.findAllByResolved(resolved, pagination);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Note> getAllPersonTask(@NonNull Long userId, boolean resolved) {
|
||||
return noteRepository.findAllByResponsibleIdAndResolved(userId, resolved);
|
||||
}
|
||||
|
||||
protected void notificationPersonal(@NonNull Note note) {
|
||||
Matcher matcher = PATTERN.matcher(note.getBody());
|
||||
Set<String> recipientsLogins = new HashSet<>();
|
||||
while (matcher.find()) {
|
||||
final String login = matcher.group(0).replace("@", "");
|
||||
recipientsLogins.add(login);
|
||||
}
|
||||
if (recipientsLogins.contains(personInformation.getUsername())) {
|
||||
notifyService.send(
|
||||
CommentNotify.builder()
|
||||
.authorName(note.getAuthor().getName())
|
||||
.message(note.getBody())
|
||||
.url(note.getWebUrl())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ public class DiscussionParser {
|
||||
.map(json -> {
|
||||
final Discussion discussion = conversionService.convert(json, Discussion.class);
|
||||
discussion.setMergeRequest(mergeRequest);
|
||||
discussion.setResponsible(mergeRequest.getAuthor());
|
||||
discussion.getNotes().forEach(
|
||||
note -> {
|
||||
final String url = MessageFormat.format(gitlabProperty.getUrlNote(), mergeRequest.getWebUrl(), note.getId());
|
||||
@ -92,7 +93,7 @@ public class DiscussionParser {
|
||||
return discussion;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
final List<Discussion> discussions = discussionService.createAll(newDiscussions);
|
||||
discussionService.createAll(newDiscussions);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,169 +0,0 @@
|
||||
package org.sadtech.bot.gitlab.core.service.parser;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* <p>Поиск новых комментариев и задач.</p>
|
||||
* <p>К несчастью, у битбакета не очень удобный API, и у них таска это то же самое что и комментарий, только с флагом</p>
|
||||
*/
|
||||
@Component
|
||||
public class NoteParser {
|
||||
|
||||
// public static final int COUNT = 100;
|
||||
//
|
||||
// private final MergeRequestsService mergeRequestsService;
|
||||
// private final ConversionService conversionService;
|
||||
//
|
||||
// private final GitlabProperty gitlabProperty;
|
||||
// private final PersonProperty personProperty;
|
||||
// private final NoteService noteService;
|
||||
//
|
||||
// public NoteParser(
|
||||
// MergeRequestsService mergeRequestsService,
|
||||
// ConversionService conversionService,
|
||||
// GitlabProperty gitlabProperty,
|
||||
// PersonProperty personProperty,
|
||||
// NoteService noteService
|
||||
// ) {
|
||||
// this.mergeRequestsService = mergeRequestsService;
|
||||
// this.conversionService = conversionService;
|
||||
// this.gitlabProperty = gitlabProperty;
|
||||
// this.personProperty = personProperty;
|
||||
// this.noteService = noteService;
|
||||
// }
|
||||
//
|
||||
// public void scanNewCommentAndTask() {
|
||||
// int page = 0;
|
||||
// Sheet<MergeRequest> mergeRequestSheet = mergeRequestsService.getAll(PaginationImpl.of(page, COUNT));
|
||||
//
|
||||
// while (mergeRequestSheet.hasContent()) {
|
||||
//
|
||||
// final List<MergeRequest> mergeRequests = mergeRequestSheet.getContent();
|
||||
// for (MergeRequest mergeRequest : mergeRequests) {
|
||||
//
|
||||
// processingMergeRequest(mergeRequest);
|
||||
//
|
||||
// }
|
||||
//
|
||||
// mergeRequestSheet = mergeRequestsService.getAll(PaginationImpl.of(++page, COUNT));
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// private void processingMergeRequest(MergeRequest mergeRequest) {
|
||||
// int page = 1;
|
||||
// List<NoteJson> noteJsons = getNoteJson(mergeRequest, page);
|
||||
//
|
||||
// while (!noteJsons.isEmpty()) {
|
||||
//
|
||||
// createNewComment(noteJsons, mergeRequest);
|
||||
//
|
||||
// noteJsons = getNoteJson(mergeRequest, ++page);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private List<NoteJson> getNoteJson(MergeRequest mergeRequest, int page) {
|
||||
// return HttpParse.request(MessageFormat.format(gitlabProperty.getUrlPullRequestComment(), mergeRequest.getProjectId(), mergeRequest.getTwoId(), page))
|
||||
// .header(ACCEPT)
|
||||
// .header(AUTHORIZATION, BEARER + personProperty.getToken())
|
||||
// .executeList(NoteJson.class)
|
||||
// .stream()
|
||||
// .filter(noteJson -> !noteJson.isSystem())
|
||||
// .collect(Collectors.toList());
|
||||
// }
|
||||
|
||||
// private void createNewTask(List<NoteJson> noteJsons, MergeRequest mergeRequest) {
|
||||
// final List<NoteJson> newJsons = noteJsons.stream()
|
||||
// .filter(json -> json.getType() != null)
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// final Set<Long> jsonIds = newJsons.stream()
|
||||
// .map(NoteJson::getId)
|
||||
// .collect(Collectors.toSet());
|
||||
//
|
||||
// final ExistsContainer<Task, Long> existsContainer = taskService.existsById(jsonIds);
|
||||
//
|
||||
// if (!existsContainer.isAllFound()) {
|
||||
// final List<Task> newNotes = newJsons.stream()
|
||||
// .filter(json -> existsContainer.getIdNoFound().contains(json.getId()))
|
||||
// .map(json -> conversionService.convert(json, Task.class))
|
||||
// .peek(task -> {
|
||||
// task.setWebUrl(MessageFormat.format(gitlabProperty.getUrlNote(), mergeRequest.getWebUrl(), task.getId()));
|
||||
// task.setResponsible(mergeRequest.getAuthor());
|
||||
// }
|
||||
// )
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// final Set<Long> newNoteIds = newNotes.stream().map(Task::getId).collect(Collectors.toSet());
|
||||
//
|
||||
// final ExistsContainer<Note, Long> existsNoteContainer = noteService.existsById(newNoteIds);
|
||||
//
|
||||
// if (existsContainer.getContainer() != null && !existsContainer.getContainer().isEmpty()) {
|
||||
// noteService.deleteAllById(existsNoteContainer.getContainer().stream().map(Note::getId).collect(Collectors.toSet()));
|
||||
// }
|
||||
//
|
||||
// final List<Task> newTasks = taskService.createAll(newNotes);
|
||||
// newTasks.forEach(task -> noteService.link(task.getId(), mergeRequest.getId()));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private void createNewComment(List<NoteJson> noteJsons, MergeRequest mergeRequest) {
|
||||
// final List<NoteJson> newJsons = noteJsons.stream()
|
||||
// .filter(json -> json.getType() == null)
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// final Set<Long> jsonIds = newJsons.stream()
|
||||
// .map(NoteJson::getId)
|
||||
// .collect(Collectors.toSet());
|
||||
//
|
||||
// final ExistsContainer<Note, Long> existsContainer = noteService.existsById(jsonIds);
|
||||
//
|
||||
// if (!existsContainer.isAllFound()) {
|
||||
// final List<Note> notes = newJsons.stream()
|
||||
// .filter(json -> existsContainer.getIdNoFound().contains(json.getId()))
|
||||
// .map(json -> conversionService.convert(json, Note.class))
|
||||
// .peek(note -> note.setWebUrl(
|
||||
// MessageFormat.format(gitlabProperty.getUrlNote(), mergeRequest.getWebUrl(), note.getId()))
|
||||
// )
|
||||
// .collect(Collectors.toList());
|
||||
//
|
||||
// final List<Note> newNotes = noteService.createAll(notes);
|
||||
// newNotes.forEach(note -> noteService.link(note.getId(), mergeRequest.getId()));
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// public void scanOldTask() {
|
||||
// int page = 0;
|
||||
// Sheet<Task> taskSheet = taskService.getAllByResolved(false, PaginationImpl.of(page, COUNT));
|
||||
//
|
||||
// while (taskSheet.hasContent()) {
|
||||
// final List<Task> tasks = taskSheet.getContent();
|
||||
//
|
||||
// for (Task task : tasks) {
|
||||
// final MergeRequest mergeRequest = task.getMergeRequest();
|
||||
// // FIXME: 11.02.2021 Костыль, исправить в будущем
|
||||
// if (mergeRequest!=null) {
|
||||
// final Task newTask = HttpParse.request(MessageFormat.format(
|
||||
// gitlabProperty.getUrlNoteApi(),
|
||||
// mergeRequest.getProjectId(),
|
||||
// mergeRequest.getTwoId(),
|
||||
// task.getId())
|
||||
// )
|
||||
// .header(ACCEPT)
|
||||
// .header(AUTHORIZATION, BEARER + personProperty.getToken())
|
||||
// .execute(NoteJson.class)
|
||||
// .map(json -> conversionService.convert(json, Task.class))
|
||||
// .orElseThrow(() -> new ConvertException("Ошибка обработки задачи id: " + task.getId()));
|
||||
// taskService.update(newTask);
|
||||
// } else {
|
||||
// taskService.deleteById(task.getId());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// taskSheet = taskService.getAllByResolved(false, PaginationImpl.of(++page, COUNT));
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
@ -10,8 +10,6 @@ import org.sadtech.haiti.database.repository.manager.AbstractSimpleManagerReposi
|
||||
import org.sadtech.haiti.database.util.Converter;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* // TODO: 08.09.2020 Добавить описание.
|
||||
*
|
||||
@ -34,9 +32,4 @@ public class NoteRepositoryImpl extends AbstractSimpleManagerRepository<Note, Lo
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Note> findAllByResponsibleIdAndResolved(@NonNull Long userId, boolean resolved) {
|
||||
return repositoryJpa.findAllByResponsibleIdAndResolved(userId, resolved);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,12 +5,8 @@ import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface NoteRepositoryJpa extends JpaRepository<Note, Long> {
|
||||
|
||||
Page<Note> findAllByResolved(boolean resolved, Pageable pageable);
|
||||
|
||||
List<Note> findAllByResponsibleIdAndResolved(Long responsibleId, boolean resolved);
|
||||
|
||||
}
|
||||
|
@ -2,9 +2,12 @@ package org.sadtech.bot.gitlab.telegram.unit;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.sadtech.bot.gitlab.context.domain.AppLocale;
|
||||
import org.sadtech.bot.gitlab.context.domain.entity.Note;
|
||||
import org.sadtech.bot.gitlab.context.service.AppSettingService;
|
||||
import org.sadtech.bot.gitlab.context.service.DiscussionService;
|
||||
import org.sadtech.bot.gitlab.context.service.NoteService;
|
||||
import org.sadtech.bot.gitlab.core.service.parser.ProjectParser;
|
||||
import org.sadtech.haiti.context.exception.NotFoundException;
|
||||
import org.sadtech.social.bot.domain.unit.AnswerCheck;
|
||||
import org.sadtech.social.bot.domain.unit.AnswerProcessing;
|
||||
import org.sadtech.social.bot.domain.unit.AnswerText;
|
||||
@ -18,6 +21,7 @@ import org.sadtech.social.core.utils.KeyBoards;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@ -73,7 +77,8 @@ public class UnitConfig {
|
||||
|
||||
@Bean
|
||||
public AnswerText answerNote(
|
||||
NoteService noteService
|
||||
NoteService noteService,
|
||||
DiscussionService discussionService
|
||||
) {
|
||||
return AnswerText.builder()
|
||||
.boxAnswer(
|
||||
@ -84,9 +89,11 @@ public class UnitConfig {
|
||||
final String url = ((Link) attachment).getUrl();
|
||||
Matcher matcher = NOTE_LINK.matcher(url);
|
||||
if (matcher.find()) {
|
||||
final String note = url.substring(matcher.start(), matcher.end());
|
||||
Long noteId = Long.valueOf(note.replaceAll("#note_", ""));
|
||||
// noteService.answer(noteId, message.getText());
|
||||
final String noteText = url.substring(matcher.start(), matcher.end());
|
||||
Long noteId = Long.valueOf(noteText.replaceAll("#note_", ""));
|
||||
final Note note = noteService.getById(noteId).orElseThrow(() -> new NotFoundException("Note не найдено"));
|
||||
final String discussionId = note.getDiscussion().getId();
|
||||
discussionService.answer(discussionId, MessageFormat.format("@{0}, {1}", note.getAuthor().getUserName(), message.getText()));
|
||||
}
|
||||
return BoxAnswer.of("Победа");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user