-
Биздин базадагы бардык топтордо мурунку аткарылгандан кийин жарыяланган жаңы макалаларды табат.
Бул схема топтордун азыраак санын көрсөтөт - активдүү колдонуучулары барлар гана. Ошол учурда бул мага логикалык көрүнгөн, бирок азыр мен түшүндүм, белгилүү бир топко жазылган активдүү колдонуучулар барбы же жокпу, сиз дагы эле бот иштеткен акыркы макаланы жаңыртуу керек. Жаңы колдонуучу бул топту өчүргөндөн бери жарыяланган макалалардын толук санын дароо алганда, кырдаал келип чыгышы мүмкүн. Бул күтүлбөгөн жүрүм-турум жана аны болтурбоо үчүн азыркы учурда активдүү колдонуучулары жок топторду биздин базадан сактап турушубуз керек. -
Жаңы макалалар бар болсо, бул топко активдүү жазылган бардык колдонуучулар үчүн билдирүүлөрдү түзүңүз. Эгерде жаңы макалалар жок болсо, биз жөн гана ишти бүтүрөбүз.
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();
}
Абдан жөнөкөй, туурабы? Бул анын маңызы жана бардык кыйынчылык ишке ашырууда болот:
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);
}
}
Бул жерде биз бардыгын ирети менен чечебиз:
-
groupService аркылуу биз маалымат базасындагы бардык топторду табабыз.
-
Андан кийин биз бардык топторго тарайбыз жана ар бири үчүн биз акыркы макалада түзүлгөн кардарды чакырабыз - javaRushPostClient.findNewPosts .
-
Андан кийин, setNewArticleId ыкмасын колдонуп , биз акыркы жаңы макалабыздын макала идентификаторун жаңыртабыз, андыктан биздин маалымат базабыз жаңыларын иштетип койгонубузду билет.
-
Ал эми GroupSub колдонуучулардын коллекциясына ээ экенин пайдаланып, биз активдүү колдонуучуларды аралап, жаңы макалалар тууралуу эскертмелерди жөнөтөбүз.
FindNewArticleJob түзүңүз
SpringScheduler деген эмне экени тууралуу биз буга чейин эле айтканбыз, бирок аны тезинен кайталап көрөлү: бул жазгы рамкадагы фондо процессти түзүү механизми, ал биз белгилеген белгилүү бир убакытта иштей турган. Бул үчүн сага эмне керек? Биринчи кадам биздин жазгы киргизүү классыбызга @EnableScheduling annotationсын кошуу :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);
}
}
Экинчи кадам класс түзүү, аны ApplicationContext'ке кошуу жана анда мезгил-мезгor менен иштей турган ыкманы түзүү. Биз репозиторий, кызмат жана башкалар менен бирдей деңгээлде жумуш пакетин түзөбүз жана ал жерден 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));
}
}
Бул классты Колдонмо контекстине кошуу үчүн мен @Component annotationсын колдондум . Класстын ичиндеги метод аны мезгил-мезгor менен иштетүү керек экенин бorши үчүн, мен методго annotation коштум: @Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}") . Бирок биз аны application.properties файлына койдук:
bot.recountNewArticleFixedRate = 900000
Бул жерде маани миллисекундда. 15 мүнөт болот. Бул ыкмада бардыгы жөнөкөй: мен анын канчалык тез иштээрин түшүнүү үчүн, жаңы макалаларды издөөнү эсептөө үчүн журналдарга өзүм үчүн супер жөнөкөй метрика коштум.
Жаңы функцияларды текшерүү
Эми биз сыноо ботубузда сынап көрөбүз. Бирок кантип? Билдирүүлөр келгенин көрсөтүү үчүн макалаларды өчүрбөймбү? Албетте жок. Биз жөн гана маалымат базасындагы маалыматтарды түзөтүп, тиркемени ишке киргизебиз. Мен аны тесттик serverимде сынап көрөм. Бул үчүн, келгиле, кандайдыр бир группага жазылалы. Жазылуу аяктагандан кийин, топко акыркы макаланын учурдагы ID берилет. Келгиле, маалымат базасына барып, эки макаланын маанисин өзгөртөлү. Жыйынтыгында, биз lastArticleId дегенге мурункуга койгондой көп макалалар болот деп күтөбүз . Андан кийин, биз сайтка барабыз, Java долбоорлорунун тобундагы макалаларды иреттейбиз - биринчи кезекте жаңылары - жана тизмеден үчүнчү макалага барабыз: Төмөнкү макалага баралы жана дарек тилкесинде Id - 3313 макаласын алабыз: Кийинки , MySQL Workbenchке өтүп, lastArticleId маанисин 3313 деп өзгөртүңүз. Келгиле, мындай топтун маалымат базасында бар экенин карап көрөлү: Ал үчүн биз буйрукту аткарабыз: Болду, эми жумуштун кийинки ишке киришине чейин күтүш керек. жаңы макалаларды издөө. Биз Java долбоорлор тобунан жаңы макала тууралуу эки билдирүүнү күтөбүз. Алар айткандай, натыйжа көп күткөн жок: Көрсө, бот биз күткөндөй иштеген.Аяктоо
Адаттагыдай эле, биз pom.xml versionсын жаңыртабыз жана RELEASE_NOTESке жазууну кошобуз, андыктан жумуш тарыхы сакталып, сиз ар дайым артка кайтып, эмне өзгөргөнүн түшүнө аласыз. Ошондуктан, биз versionны бир бирдикке көбөйтөбүз:<version>0.7.0-SNAPSHOT</version>
Жана RELEASE_NOTES жаңыртуу:
GO TO FULL VERSION