-
Temokake ing kabeh klompok sing ana ing database kita artikel anyar sing diterbitake sawise eksekusi sadurunge.
Skema iki nemtokake klompok sing luwih cilik - mung sing nganggo pangguna aktif. Ing wektu iku katon logis kanggo kula, nanging saiki aku ngerti manawa ana pangguna aktif sing langganan grup tartamtu utawa ora, sampeyan isih kudu nyimpen artikel paling anyar sing diproses bot. Kahanan bisa kedadeyan nalika pangguna anyar langsung nampa kabeh artikel sing diterbitake wiwit grup iki dipateni. Iki ora samesthine prilaku, lan kanggo ngindhari iku, kita kudu njaga grup kasebut saka database kita sing saiki ora duwe panganggo aktif up-to-date. -
Yen ana artikel anyar, gawe pesen kanggo kabeh pangguna sing aktif langganan grup iki. Yen ora ana artikel anyar, kita mung ngrampungake karya kasebut.
FindNewArticleService:
package com.github.javarushcommunity.jrtb.service;
/**
* Service for finding new articles.
*/
public interface FindNewArticleService {
/**
* Find new articles and notify subscribers about it.
*/
void findNewArticles();
}
Prasaja banget, bener? Iki minangka inti, lan kabeh kesulitan bakal ana ing implementasine:
package com.github.javarushcommunity.jrtb.service;
import com.github.javarushcommunity.jrtb.javarushclient.JavaRushPostClient;
import com.github.javarushcommunity.jrtb.javarushclient.dto.PostInfo;
import com.github.javarushcommunity.jrtb.repository.entity.GroupSub;
import com.github.javarushcommunity.jrtb.repository.entity.TelegramUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class FindNewArticleServiceImpl implements FindNewArticleService {
public static final String JAVARUSH_WEB_POST_FORMAT = "https://javarush.com/groups/posts/%s";
private final GroupSubService groupSubService;
private final JavaRushPostClient javaRushPostClient;
private final SendBotMessageService sendMessageService;
@Autowired
public FindNewArticleServiceImpl(GroupSubService groupSubService,
JavaRushPostClient javaRushPostClient,
SendBotMessageService sendMessageService) {
this.groupSubService = groupSubService;
this.javaRushPostClient = javaRushPostClient;
this.sendMessageService = sendMessageService;
}
@Override
public void findNewArticles() {
groupSubService.findAll().forEach(gSub -> {
List<PostInfo> newPosts = javaRushPostClient.findNewPosts(gSub.getId(), gSub.getLastArticleId());
setNewLastArticleId(gSub, newPosts);
notifySubscribersAboutNewArticles(gSub, newPosts);
});
}
private void notifySubscribersAboutNewArticles(GroupSub gSub, List<PostInfo> newPosts) {
Collections.reverse(newPosts);
List<String> messagesWithNewArticles = newPosts.stream()
.map(post -> String.format("✨Вышла новая статья <b>%s</b> в группе <b>%s</b>.✨\n\n" +
"<b>Описание:</b> %s\n\n" +
"<b>Ссылка:</b> %s\n",
post.getTitle(), gSub.getTitle(), post.getDescription(), getPostUrl(post.getKey())))
.collect(Collectors.toList());
gSub.getUsers().stream()
.filter(TelegramUser::isActive)
.forEach(it -> sendMessageService.sendMessage(it.getChatId(), messagesWithNewArticles));
}
private void setNewLastArticleId(GroupSub gSub, List<PostInfo> newPosts) {
newPosts.stream().mapToInt(PostInfo::getId).max()
.ifPresent(id -> {
gSub.setLastArticleId(id);
groupSubService.save(gSub);
});
}
private String getPostUrl(String key) {
return String.format(JAVARUSH_WEB_POST_FORMAT, key);
}
}
Ing kene kita bakal ngrampungake kabeh kanthi urutan:
-
Nggunakake groupService kita nemokake kabeh grup sing ana ing database.
-
Banjur kita nyebar menyang kabeh kelompok lan saben kita nelpon klien digawe ing artikel pungkasan - javaRushPostClient.findNewPosts .
-
Sabanjure, nggunakake metode setNewArticleId , kita nganyari ID artikel artikel anyar sing paling anyar supaya database ngerti yen kita wis ngolah sing anyar.
-
Lan nggunakake kasunyatan manawa GroupSub duwe koleksi pangguna, kita ngliwati sing aktif lan ngirim kabar babagan artikel anyar.
Nggawe FindNewArticleJob
Kita wis ngomong babagan apa SpringScheduler, nanging ayo mbaleni kanthi cepet: minangka mekanisme ing kerangka Spring kanggo nggawe proses latar mburi sing bakal ditindakake ing wektu tartamtu sing kita setel. Apa sing sampeyan butuhake kanggo iki? Langkah pisanan yaiku nambah anotasi @EnableScheduling menyang kelas input musim semi:package com.github.javarushcommunity.jrtb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@SpringBootApplication
public class JavarushTelegramBotApplication {
public static void main(String[] args) {
SpringApplication.run(JavarushTelegramBotApplication.class, args);
}
}
Langkah kapindho yaiku nggawe kelas, nambah menyang ApplicationContext lan nggawe metode sing bakal ditindakake kanthi periodik. Kita nggawe paket proyek ing tingkat sing padha karo repositori, layanan, lan liya-liyane, lan ing kana kita nggawe kelas FindNewArticleJob :
package com.github.javarushcommunity.jrtb.job;
import com.github.javarushcommunity.jrtb.service.FindNewArticleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
/**
* Job for finding new articles.
*/
@Slf4j
@Component
public class FindNewArticlesJob {
private final FindNewArticleService findNewArticleService;
@Autowired
public FindNewArticlesJob(FindNewArticleService findNewArticleService) {
this.findNewArticleService = findNewArticleService;
}
@Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}")
public void findNewArticles() {
LocalDateTime start = LocalDateTime.now();
log.info("Find new article job started.");
findNewArticleService.findNewArticles();
LocalDateTime end = LocalDateTime.now();
log.info("Find new articles job finished. Took seconds: {}",
end.toEpochSecond(ZoneOffset.UTC) - start.toEpochSecond(ZoneOffset.UTC));
}
}
Kanggo nambah kelas iki menyang Konteks Aplikasi aku nggunakake @Component anotasi . Lan supaya metode ing kelas ngerti yen kudu ditindakake sacara periodik, aku nambahake anotasi kanggo metode: @Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}") . Nanging kita nyetel ing file application.properties:
bot.recountNewArticleFixedRate = 900000
Ing kene regane ing milliseconds. Iku bakal 15 menit. Ing cara iki, kabeh iku prasaja: Aku nambah metrik super prasaja kanggo aku ing log kanggo ngetung panelusuran kanggo artikel anyar, supaya ing paling kira-kira ngerti carane cepet iku bisa.
Nguji fungsi anyar
Saiki kita bakal nyoba ing test bot kita. Nanging carane? Aku ora bakal mbusak artikel saben wektu kanggo nuduhake yen kabar wis teka? Mesthi ora. Kita mung bakal ngowahi data ing database lan miwiti aplikasi kasebut. Aku bakal nyoba ing server test. Kanggo nindakake iki, ayo langganan sawetara grup. Nalika langganan rampung, grup bakal diwenehi ID saiki saka artikel paling anyar. Ayo menyang database lan ngganti nilai loro artikel bali. Akibaté, kita ngarepake bakal ana akeh artikel kaya sing kita setel lastArticleId sadurunge . Sabanjure, pindhah menyang situs kasebut, urutake artikel ing grup proyek Java - sing anyar dhisik - lan pindhah menyang artikel katelu saka dhaptar: Ayo menyang artikel ngisor lan saka baris alamat entuk artikel Id - 3313: Sabanjure , pindhah menyang MySQL Workbench lan ganti nilai lastArticleId dadi 3313. Ayo ndeleng manawa klompok kasebut ana ing basis data: Lan kanggo iki, kita bakal nglakokake prentah kasebut: Lan iku, saiki sampeyan kudu ngenteni nganti peluncuran proyek sabanjure. goleki artikel anyar. Kita ngarepake nampa rong pesen babagan artikel anyar saka grup proyek Java. Kaya sing dikandhakake, asile ora suwe: Pranyata bot kasebut kerja kaya sing dikarepake.Ending
Kaya biasane, kita nganyari versi ing pom.xml lan nambah entri menyang RELEASE_NOTES supaya riwayat karya disimpen lan sampeyan bisa tansah bali lan ngerti apa sing wis diganti. Mulane, kita nambah versi kanthi siji unit:<version>0.7.0-SNAPSHOT</version>
Lan nganyari RELEASE_NOTES:
GO TO FULL VERSION