-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: mail notify and app link to (#706)
* feat: 添加剧集更新邮件通知 * feat: 添加app跳转页面 * docs: update CHANGELOG.MD
- Loading branch information
Showing
8 changed files
with
239 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
version=0.17.2 | ||
version=0.17.3 |
46 changes: 46 additions & 0 deletions
46
server/src/main/java/run/ikaros/server/controller/AppLinkController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package run.ikaros.server.controller; | ||
|
||
import org.springframework.stereotype.Controller; | ||
import org.springframework.ui.Model; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import reactor.core.publisher.Mono; | ||
import run.ikaros.api.infra.properties.IkarosProperties; | ||
import run.ikaros.api.infra.utils.StringUtils; | ||
import run.ikaros.server.core.subject.service.SubjectService; | ||
|
||
@Controller | ||
@RequestMapping("/app/link") | ||
public class AppLinkController { | ||
private final SubjectService subjectService; | ||
private final IkarosProperties ikarosProperties; | ||
|
||
public AppLinkController(SubjectService subjectService, IkarosProperties ikarosProperties) { | ||
this.subjectService = subjectService; | ||
this.ikarosProperties = ikarosProperties; | ||
} | ||
|
||
/** | ||
* app 链接跳转页面. | ||
*/ | ||
@GetMapping("/subject/{id}") | ||
public Mono<String> index(Model model, @PathVariable("id") Long subjectId) { | ||
return subjectService.findById(subjectId) | ||
.flatMap(subject -> { | ||
String name = StringUtils.isBlank(subject.getNameCn()) | ||
? subject.getName() : subject.getNameCn(); | ||
model.addAttribute("subject", subject); | ||
model.addAttribute("subjectName", name); | ||
String cover = subject.getCover(); | ||
if (StringUtils.isNotBlank(cover) && !cover.startsWith("http")) { | ||
cover = ikarosProperties.getExternalUrl() + cover; | ||
} | ||
subject.setCover(cover); | ||
model.addAttribute("subjectCover", cover); | ||
String subjectUrl = "ikaros://app/subject/" + subject.getId(); | ||
model.addAttribute("subjectUrl", subjectUrl); | ||
return Mono.just("temp/app-link-to"); | ||
}); | ||
} | ||
} |
125 changes: 125 additions & 0 deletions
125
server/src/main/java/run/ikaros/server/core/episode/EpisodeUpdateListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package run.ikaros.server.core.episode; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.context.event.EventListener; | ||
import org.springframework.stereotype.Component; | ||
import org.thymeleaf.context.Context; | ||
import reactor.core.publisher.Mono; | ||
import run.ikaros.api.infra.properties.IkarosProperties; | ||
import run.ikaros.api.infra.utils.StringUtils; | ||
import run.ikaros.server.core.attachment.event.EpisodeAttachmentUpdateEvent; | ||
import run.ikaros.server.core.notify.NotifyService; | ||
import run.ikaros.server.store.entity.AttachmentEntity; | ||
import run.ikaros.server.store.entity.EpisodeEntity; | ||
import run.ikaros.server.store.entity.SubjectEntity; | ||
import run.ikaros.server.store.repository.AttachmentRepository; | ||
import run.ikaros.server.store.repository.EpisodeRepository; | ||
import run.ikaros.server.store.repository.SubjectRepository; | ||
|
||
@Slf4j | ||
@Component | ||
public class EpisodeUpdateListener { | ||
private final AttachmentRepository attachmentRepository; | ||
private final EpisodeRepository episodeRepository; | ||
private final SubjectRepository subjectRepository; | ||
|
||
private final NotifyService notifyService; | ||
|
||
private final IkarosProperties ikarosProperties; | ||
|
||
/** | ||
* Construct. | ||
*/ | ||
public EpisodeUpdateListener(AttachmentRepository attachmentRepository, | ||
EpisodeRepository episodeRepository, | ||
SubjectRepository subjectRepository, | ||
NotifyService notifyService, IkarosProperties ikarosProperties) { | ||
this.attachmentRepository = attachmentRepository; | ||
this.episodeRepository = episodeRepository; | ||
this.subjectRepository = subjectRepository; | ||
this.notifyService = notifyService; | ||
this.ikarosProperties = ikarosProperties; | ||
} | ||
|
||
/** | ||
* 如果需要发送通知则进行发送. | ||
*/ | ||
@EventListener(EpisodeAttachmentUpdateEvent.class) | ||
public Mono<Void> onEpisodeAttachmentUpdateEvent(EpisodeAttachmentUpdateEvent event) { | ||
if (!event.getNotify()) { | ||
return Mono.empty(); | ||
} | ||
final Long attachmentId = event.getAttachmentId(); | ||
final Long episodeId = event.getEpisodeId(); | ||
return Mono.just(new Context()) | ||
.flatMap(context -> attachmentRepository.findById(attachmentId) | ||
.map(entity -> { | ||
context.setVariable("attachment", entity); | ||
return context; | ||
})) | ||
.flatMap(context -> episodeRepository.findById(episodeId) | ||
.map(entity -> { | ||
String name = StringUtils.isEmpty(entity.getNameCn()) | ||
? entity.getName() : entity.getNameCn(); | ||
context.setVariable("episodeName", name); | ||
context.setVariable("episode", entity); | ||
return context; | ||
})) | ||
.flatMap(context -> { | ||
Object episode = context.getVariable("episode"); | ||
|
||
if (!(episode instanceof EpisodeEntity episodeEntity)) { | ||
return Mono.empty(); | ||
} | ||
Long subjectId = episodeEntity.getSubjectId(); | ||
return subjectRepository.findById(subjectId) | ||
.map(entity -> { | ||
String cover = entity.getCover(); | ||
if (StringUtils.isNotBlank(cover) && !cover.startsWith("http")) { | ||
cover = ikarosProperties.getExternalUrl() + cover; | ||
} | ||
entity.setCover(cover); | ||
String name = StringUtils.isBlank(entity.getNameCn()) | ||
? entity.getName() : entity.getNameCn(); | ||
String subjectUrl = ikarosProperties.getExternalUrl() | ||
+ "/app/link/subject/" + subjectId; | ||
|
||
context.setVariable("subjectName", name); | ||
context.setVariable("subjectCover", cover); | ||
context.setVariable("subject", entity); | ||
context.setVariable("subjectUrl", subjectUrl); | ||
return context; | ||
}); | ||
}) | ||
.flatMap(context -> { | ||
Object episode = context.getVariable("episode"); | ||
|
||
if (!(episode instanceof EpisodeEntity episodeEntity)) { | ||
return Mono.empty(); | ||
} | ||
Object attachment = context.getVariable("attachment"); | ||
|
||
if (!(attachment instanceof AttachmentEntity attachmentEntity)) { | ||
return Mono.empty(); | ||
} | ||
|
||
Object subject = context.getVariable("subject"); | ||
|
||
if (!(subject instanceof SubjectEntity subjectEntity)) { | ||
return Mono.empty(); | ||
} | ||
|
||
StringBuilder sb = new StringBuilder("番剧《"); | ||
sb.append(StringUtils.isBlank(subjectEntity.getNameCn()) | ||
? subjectEntity.getName() : subjectEntity.getNameCn()) | ||
.append("》第") | ||
.append(episodeEntity.getSequence()) | ||
.append("集 [") | ||
.append(StringUtils.isBlank(episodeEntity.getNameCn()) | ||
? episodeEntity.getName() : episodeEntity.getNameCn()) | ||
.append("] 更新了"); | ||
|
||
return notifyService.send(sb.toString(), "mail/anime_update", context); | ||
}); | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
server/src/main/java/run/ikaros/server/core/notify/NotifyService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,12 @@ | ||
package run.ikaros.server.core.notify; | ||
|
||
import org.thymeleaf.context.Context; | ||
import reactor.core.publisher.Mono; | ||
|
||
public interface NotifyService { | ||
Mono<Void> sendMail(String title, String context); | ||
|
||
Mono<Void> send(String title, String template, Context context); | ||
|
||
Mono<Void> testMail(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 12 additions & 12 deletions
24
server/src/main/resources/templates/mail/anime_update.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<!DOCTYPE html> | ||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<title>Ikaros app link temp page</title> | ||
</head> | ||
<body> | ||
<div style="background: #fff;"> | ||
<div style="width:100%;max-width:720px;text-align: left;margin: 0 auto;padding-top: 20px;padding-bottom: 80px"> | ||
<div style="border-radius: 5px;border:1px solid #eee;overflow: hidden;"> | ||
<h1 style="color:#fff;background: #3798e8;font-size:24px;font-weight:normal;padding-left:40px;margin:0"> | ||
番剧: 《<strong th:text="${subjectName}"></strong>》 | ||
</h1> | ||
<div style="background:#fff;padding:20px 32px 40px;"> | ||
<strong>前往app观看:</strong> | ||
<p style="color: #6e6e6e;font-size:13px;line-height:24px;">点击 <a th:href="${subjectUrl}">跳转到app条目页面</a></p> | ||
|
||
<!-- <p style="color: #6e6e6e;font-size:13px;line-height:24px;">放送进度:<span th:text="${updateEpsCount}"></span>/<span th:text="${allEpsCount}"></span></p>--> | ||
<h2>番剧简介:</h2> | ||
<p th:text="${subject.summary}" style="color: #6e6e6e;font-size:13px;line-height:24px;padding:10px 20px;background:#f8f8f8;margin:0"> | ||
</p> | ||
|
||
<h2>封面:</h2> | ||
<div align="center"> | ||
<img style="border-radius:5px;width: 100%;" th:src="${subjectCover}" alt="URL无法访问"></img> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
</body> | ||
</html> |