-
ان تمام گروپس میں ڈھونڈتا ہے جو ہمارے ڈیٹابیس میں پچھلی کارروائی کے بعد شائع ہونے والے نئے مضامین میں ہیں۔
یہ اسکیم گروپوں کی ایک چھوٹی تعداد کی وضاحت کرتی ہے - صرف وہ لوگ جو فعال صارفین کے ساتھ ہیں۔ اس وقت یہ مجھے منطقی معلوم ہوتا تھا، لیکن اب میں سمجھتا ہوں کہ اس بات سے قطع نظر کہ فعال صارفین نے کسی مخصوص گروپ کو سبسکرائب کیا ہے یا نہیں، آپ کو اب بھی تازہ ترین مضمون کو برقرار رکھنے کی ضرورت ہے جس پر بوٹ نے کارروائی کی ہے۔ ایسی صورت حال پیدا ہو سکتی ہے جب کسی نئے صارف کو اس گروپ کے غیر فعال ہونے کے بعد سے شائع ہونے والے مضامین کی پوری تعداد فوری طور پر موصول ہو جاتی ہے۔ یہ متوقع رویہ نہیں ہے، اور اس سے بچنے کے لیے، ہمیں اپنے ڈیٹا بیس سے ان گروپس کو رکھنے کی ضرورت ہے جن کے پاس فی الحال فعال صارفین اپ ٹو ڈیٹ نہیں ہیں۔ -
اگر نئے مضامین ہیں تو ان تمام صارفین کے لیے پیغامات تیار کریں جنہوں نے اس گروپ کو فعال طور پر سبسکرائب کیا ہے۔ اگر کوئی نئے مضامین نہیں ہیں، تو ہم صرف کام مکمل کرتے ہیں۔
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);
}
}
یہاں ہم ہر چیز کے ساتھ ترتیب سے نمٹیں گے:
-
گروپ سروس کا استعمال کرتے ہوئے ہم ڈیٹا بیس میں موجود تمام گروپس کو تلاش کرتے ہیں۔
-
پھر ہم تمام گروپس میں منتشر ہو جاتے ہیں اور ہر ایک کے لیے ہم آخری مضمون میں تخلیق کردہ کلائنٹ کو کال کرتے ہیں - javaRushPostClient.findNewPosts ۔
-
اس کے بعد، setNewArticleId طریقہ استعمال کرتے ہوئے ، ہم اپنے تازہ ترین نئے مضمون کی مضمون ID کو اپ ڈیٹ کرتے ہیں تاکہ ہمارے ڈیٹا بیس کو معلوم ہو کہ ہم نے پہلے ہی نئے پر کارروائی کر لی ہے۔
-
اور اس حقیقت کو استعمال کرتے ہوئے کہ GroupSub کے پاس صارفین کا مجموعہ ہے، ہم فعال صارفین سے گزرتے ہیں اور نئے مضامین کے بارے میں اطلاعات بھیجتے ہیں۔
FindNewArticleJob بنائیں
ہم پہلے ہی اس کے بارے میں بات کر چکے ہیں کہ اسپرنگ شیڈیولر کیا ہے، لیکن آئیے اسے جلدی سے دہراتے ہیں: یہ پس منظر کے عمل کو بنانے کے لیے بہار کے فریم ورک میں ایک طریقہ کار ہے جو ہمارے مقرر کردہ مخصوص وقت پر چلے گا۔ آپ کو اس کے لیے کیا چاہیے؟ پہلا قدم ہماری بہار ان پٹ کلاس میں @EnableScheduling تشریح شامل کرنا ہے۔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 میں شامل کرنا اور اس میں ایک طریقہ بنانا ہے جو وقتاً فوقتاً چلایا جائے گا۔ ہم اسی سطح پر ایک جاب پیکج بناتے ہیں جیسے کہ مخزن، سروس وغیرہ، اور وہاں ہم 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 تشریح کا استعمال کیا ۔ اور اس لیے کہ کلاس کے اندر کا طریقہ جانتا ہے کہ اسے وقتاً فوقتاً چلانے کی ضرورت ہے، میں نے طریقہ کار میں ایک تشریح شامل کی: @Scheduled(fixedRateString = "${bot.recountNewArticleFixedRate}") ۔ لیکن ہم نے اسے application.properties فائل میں سیٹ کیا ہے۔
bot.recountNewArticleFixedRate = 900000
یہاں قدر ملی سیکنڈ میں ہے۔ 15 منٹ ہوں گے۔ اس طریقے میں، سب کچھ آسان ہے: میں نے نئے مضامین کی تلاش کا حساب لگانے کے لیے لاگز میں اپنے لیے ایک انتہائی سادہ میٹرک شامل کیا، تاکہ کم از کم یہ سمجھ سکیں کہ یہ کتنی تیزی سے کام کرتا ہے۔
نئی فعالیت کی جانچ
اب ہم اپنے ٹیسٹ بوٹ پر ٹیسٹ کریں گے۔ لیکن کس طرح؟ میں ہر بار یہ ظاہر کرنے کے لیے مضامین کو حذف نہیں کروں گا کہ اطلاعات آچکی ہیں؟ ہرگز نہیں۔ ہم صرف ڈیٹا بیس میں ڈیٹا میں ترمیم کریں گے اور ایپلیکیشن لانچ کریں گے۔ میں اسے اپنے ٹیسٹ سرور پر آزماؤں گا۔ ایسا کرنے کے لیے، آئیے کسی گروپ کو سبسکرائب کریں۔ سبسکرپشن مکمل ہونے پر، گروپ کو تازہ ترین مضمون کی موجودہ ID دی جائے گی۔ آئیے ڈیٹا بیس پر جائیں اور قدر دو آرٹیکلز کو واپس تبدیل کریں۔ نتیجے کے طور پر، ہم توقع کرتے ہیں کہ اتنے ہی مضامین ہوں گے جتنے کہ ہم نے lastArticleId کو پہلے سیٹ کیا تھا ۔ اس کے بعد، ہم سائٹ پر جاتے ہیں، جاوا پروجیکٹس گروپ میں مضامین کو ترتیب دیتے ہیں - پہلے نئے - اور فہرست سے تیسرے مضمون پر جائیں: آئیے نیچے والے مضمون پر جائیں اور ایڈریس بار سے ہمیں آرٹیکل آئی ڈی - 3313: اگلا ملتا ہے۔ ، MySQL Workbench پر جائیں اور lastArticleId ویلیو کو 3313 میں تبدیل کریں۔ آئیے دیکھتے ہیں کہ ایسا گروپ ڈیٹا بیس میں ہے: اور اس کے لیے ہم کمانڈ پر عمل کریں گے: اور بس، اب آپ کو جاب کے اگلے آغاز تک انتظار کرنا ہوگا۔ نئے مضامین تلاش کریں۔ ہمیں جاوا پروجیکٹس گروپ سے ایک نئے مضمون کے بارے میں دو پیغامات موصول ہونے کی توقع ہے۔ جیسا کہ وہ کہتے ہیں، نتیجہ آنے میں زیادہ دیر نہیں تھی: یہ پتہ چلتا ہے کہ بوٹ نے ہماری توقع کے مطابق کام کیا۔ختم ہونے والا
ہمیشہ کی طرح، ہم ورژن کو pom.xml میں اپ ڈیٹ کرتے ہیں اور RELEASE_NOTES میں ایک اندراج شامل کرتے ہیں تاکہ کام کی تاریخ محفوظ ہو جائے اور آپ ہمیشہ واپس جا کر سمجھ سکیں کہ کیا تبدیلی آئی ہے۔ لہذا، ہم ورژن کو ایک یونٹ سے بڑھاتے ہیں:<version>0.7.0-SNAPSHOT</version>
اور RELEASE_NOTES کو اپ ڈیٹ کریں:
GO TO FULL VERSION