Skip to content

Commit

Permalink
extended bot statistics for admins.
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanLiVa committed Dec 26, 2023
1 parent cb89988 commit ab8cf89
Show file tree
Hide file tree
Showing 21 changed files with 383 additions and 41 deletions.
4 changes: 4 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ JRTB-0: added SpringBoot skeleton project
* JRTB-4: added ability to send notifications about new articles
* JRTB-8: added ability to set inactive telegram user
* JRTB-9: added ability to set active user and/or start using it.
* # Release Notes

## 0.8.0-SNAPSHOT
* JRTB-10: extended bot statistics for admins.

6 changes: 6 additions & 0 deletions SET_UP_COMMANDS_BOT_FATHER
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
start - начать/восстановить работу с ботом
stop - приостановить работу с ботом
addgroupsub - подписаться на группу статей
deletegroupsub - отписаться от группы статей
listgroupsub - список групп, на которые подписан
help - получить помощь в работе со мной
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>
<groupId>com.github.JBolivarLi</groupId>
<artifactId>javarush-telegrambot</artifactId>
<version>0.7.0-SNAPSHOT</version>
<version>0.8.0-SNAPSHOT</version>
<name>javarush-telegrambot</name>
<description>Telegram bot for Javarush from community to community</description>
<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.github.JBolivarLi.javarushtelegrambot.bot.javarushclient.JavaRushGroupClient;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.GroupSubService;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.SendBotMessageServiceImpl;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.StatisticsService;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.TelegramUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand All @@ -12,6 +13,9 @@
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

import javax.annotation.PostConstruct;
import java.util.List;

import static com.github.JBolivarLi.javarushtelegrambot.bot.command.CommandName.NO;

@Component
Expand All @@ -33,20 +37,28 @@ public String getBotToken() {
private final CommandContainer commandContainer;


@Autowired

public JavarushTelegramBot(TelegramUserService telegramUserService, JavaRushGroupClient groupClient, GroupSubService groupSubService) {
this.commandContainer = new CommandContainer(new SendBotMessageServiceImpl(this), telegramUserService,groupClient,groupSubService);
public JavarushTelegramBot(TelegramUserService telegramUserService, JavaRushGroupClient groupClient, GroupSubService groupSubService,
@Value("#{'${bot.admins}'.split(',')}") List<String> admins, StatisticsService statisticsService) {
this.commandContainer = new CommandContainer(new SendBotMessageServiceImpl(this),
telegramUserService, groupClient, groupSubService, admins,statisticsService);

}



public void onUpdateReceived(Update update) {
if(update.hasMessage() && update.getMessage().hasText()) {
String message = update.getMessage().getText().trim();
String username = update.getMessage().getFrom().getUserName();
if (message.startsWith(COMMAND_PREFIX)){
String commandIdentifier = message.split(" ")[0].toLowerCase();
commandContainer.retrieveCommand(commandIdentifier).execute(update);
commandContainer.retrieveCommand(commandIdentifier,username).execute(update);
} else {
commandContainer.retrieveCommand(NO.getCommandName()).execute(update);
commandContainer.retrieveCommand(NO.getCommandName(),username).execute(update);
System.out.println(username);


}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.github.JBolivarLi.javarushtelegrambot.bot.command;

import com.github.JBolivarLi.javarushtelegrambot.bot.service.SendBotMessageService;
import org.telegram.telegrambots.meta.api.objects.Update;

import static com.github.JBolivarLi.javarushtelegrambot.bot.command.CommandName.STAT;
import static java.lang.String.format;

/**
* Admin Help {@link Command}.
*/
public class AdminHelpCommand implements Command {

public static final String ADMIN_HELP_MESSAGE = format("✨<b>Доступные команды админа</b>✨\n\n"
+ "<b>Получить статистику</b>\n"
+ "%s - статистика бота\n",
STAT.getCommandName());

private final SendBotMessageService sendBotMessageService;

public AdminHelpCommand(SendBotMessageService sendBotMessageService) {
this.sendBotMessageService = sendBotMessageService;
}

@Override
public void execute(Update update) {
sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), ADMIN_HELP_MESSAGE);

}
}
Original file line number Diff line number Diff line change
@@ -1,37 +1,58 @@
package com.github.JBolivarLi.javarushtelegrambot.bot.command;

import com.github.JBolivarLi.javarushtelegrambot.bot.command.annotation.AdminCommand;
import com.github.JBolivarLi.javarushtelegrambot.bot.javarushclient.JavaRushGroupClient;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.GroupSubService;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.SendBotMessageService;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.SendBotMessageServiceImpl;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.TelegramUserService;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.*;

import java.util.List;
import java.util.Map;


import static com.github.JBolivarLi.javarushtelegrambot.bot.command.CommandName.*;
import static java.util.Objects.nonNull;

public class CommandContainer {
private final Map<String, Command> commandMap;
private final Command unknownCommand;
private final List<String> admins;


public CommandContainer(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService, JavaRushGroupClient javaRushGroupClient, GroupSubService groupSubService) {

public CommandContainer(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService,
JavaRushGroupClient javaRushGroupClient, GroupSubService groupSubService, List<String> admins, StatisticsService statisticsService) {
this.admins = admins;
commandMap =
Map.ofEntries(Map.entry(START.getCommandName(), new StartCommand(sendBotMessageService, telegramUserService)),
Map.entry(STOP.getCommandName(), new StopCommand(sendBotMessageService, telegramUserService)),
Map.entry(HELP.getCommandName(), new HelpCommand(sendBotMessageService)),
Map.entry(NO.getCommandName(), new NoCommand(sendBotMessageService)),
Map.entry(STAT.getCommandName(), new StatCommand(sendBotMessageService, telegramUserService)),
Map.entry(STAT.getCommandName(), new StatCommand(sendBotMessageService, statisticsService)),
Map.entry(ADD_GROUP_SUB.getCommandName(), new AddGroupSubCommand(sendBotMessageService, javaRushGroupClient, groupSubService)),
Map.entry(LIST_GROUP_SUB.getCommandName(), new ListGroupSubCommand(sendBotMessageService, telegramUserService)),
Map.entry(DELETE_GROUP_SUB.getCommandName(), new DeleteGroupSubCommand(sendBotMessageService, groupSubService, telegramUserService)));
Map.entry(DELETE_GROUP_SUB.getCommandName(), new DeleteGroupSubCommand(sendBotMessageService, groupSubService, telegramUserService)),
Map.entry(ADMIN_HELP.getCommandName(), new AdminHelpCommand(sendBotMessageService)));


unknownCommand = new UnknownCommand(sendBotMessageService);
}


public Command retrieveCommand(String commandIdentifier, String username) {
Command orDefault = commandMap.getOrDefault(commandIdentifier, unknownCommand);

unknownCommand = new UnknownCommand(sendBotMessageService);
if (isAdminCommand(orDefault)) {
if (admins.contains(username)) {
return orDefault;
} else {
return unknownCommand;
}
}
return orDefault;
}

public Command retrieveCommand(String commandIdentifier) {
return commandMap.getOrDefault(commandIdentifier, unknownCommand);
private boolean isAdminCommand(Command command) {
AdminCommand adminCommandAnnotation = command.getClass().getAnnotation(AdminCommand.class);
return adminCommandAnnotation != null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ public enum CommandName {
STAT("/stat"),
ADD_GROUP_SUB("/addgroupsub"),
LIST_GROUP_SUB("/listgroupsub"),
DELETE_GROUP_SUB("/deletegroupsub");
DELETE_GROUP_SUB("/deletegroupsub"),
ADMIN_HELP("/ahelp");


private final String commandName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ public class HelpCommand implements Command {
+ "%s - отписаться от группы статей\n"
+ "%s - получить список групп, на которые подписан\n\n"

+ "%s - получить помощь в работе со мной\n"
+ "Работа с данными группы:\n"
+ "%s - получить статистику \"\\u263A\"подписчиков бота:\n",
+ "%s - получить помощь в работе со мной\n",
START.getCommandName(), STOP.getCommandName(), ADD_GROUP_SUB.getCommandName(),
DELETE_GROUP_SUB.getCommandName(), LIST_GROUP_SUB.getCommandName(), HELP.getCommandName(), STAT.getCommandName());
DELETE_GROUP_SUB.getCommandName(), LIST_GROUP_SUB.getCommandName(), HELP.getCommandName());


public HelpCommand(SendBotMessageService sendBotMessageService) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,49 @@
package com.github.JBolivarLi.javarushtelegrambot.bot.command;

import com.github.JBolivarLi.javarushtelegrambot.bot.command.annotation.AdminCommand;
import com.github.JBolivarLi.javarushtelegrambot.bot.dto.StatisticDTO;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.SendBotMessageService;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.StatisticsService;
import com.github.JBolivarLi.javarushtelegrambot.bot.service.TelegramUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.telegram.telegrambots.meta.api.objects.Update;

import java.util.stream.Collectors;

/**
* Statistics {@link Command}.
*/
@AdminCommand
public class StatCommand implements Command {

private final TelegramUserService telegramUserService;
private final StatisticsService statisticsService;
private final SendBotMessageService sendBotMessageService;

public final static String STAT_MESSAGE = "Javarush Telegram Bot использует %s человек.";
public final static String STAT_MESSAGE = "✨<b>Подготовил статистику</b>✨\n" +
"- Количество активных пользователей: %s\n" +
"- Количество неактивных пользователей: %s\n" +
"- Среднее количество групп на одного пользователя: %s\n\n" +
"<b>Информация по активным группам</b>:\n" +
"%s";

@Autowired
public StatCommand(SendBotMessageService sendBotMessageService, TelegramUserService telegramUserService) {
public StatCommand(SendBotMessageService sendBotMessageService, StatisticsService statisticsService) {
this.sendBotMessageService = sendBotMessageService;
this.telegramUserService = telegramUserService;
this.statisticsService = statisticsService;
}

@Override
public void execute(Update update) {
int activeUserCount = telegramUserService.retrieveAllActiveUsers().size();
sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), String.format(STAT_MESSAGE, activeUserCount));
StatisticDTO statisticDTO = statisticsService.countBotStatistic();

String collectedGroups = statisticDTO.getGroupStatDTOs().stream()
.map(it -> String.format("%s (id = %s) - %s подписчиков", it.getTitle(), it.getId(), it.getActiveUserCount()))
.collect(Collectors.joining("\n"));

sendBotMessageService.sendMessage(update.getMessage().getChatId().toString(), String.format(STAT_MESSAGE,
statisticDTO.getActiveUserCount(),
statisticDTO.getInactiveUserCount(),
statisticDTO.getAverageGroupCountByUser(),
collectedGroups));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.github.JBolivarLi.javarushtelegrambot.bot.command.annotation;


import com.github.JBolivarLi.javarushtelegrambot.bot.command.Command;

import java.lang.annotation.Retention;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Mark if {@link Command} can be viewed only by admins.
*/
@Retention(RUNTIME)
public @interface AdminCommand {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.github.JBolivarLi.javarushtelegrambot.bot.dto;

import lombok.Data;
import lombok.EqualsAndHashCode;

/**
* DTO for showing group id and title without data
*/
@Data

@EqualsAndHashCode(exclude = {"title", "activeUserCount"})
public class GroupStatDTO {

private final Integer id;
private final String title;
private final Integer activeUserCount;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.github.JBolivarLi.javarushtelegrambot.bot.dto;

import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.List;

/**
* DTO for getting bot statistics.
*/
@Data
@EqualsAndHashCode
public class StatisticDTO {
private final int activeUserCount;
private final int inactiveUserCount;
private final List<GroupStatDTO> groupStatDTOs;
private final double averageGroupCountByUser;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.github.JBolivarLi.javarushtelegrambot.bot.service;


import com.github.JBolivarLi.javarushtelegrambot.bot.dto.StatisticDTO;

/**
* Service for getting bot statistics.
*/
public interface StatisticsService {
StatisticDTO countBotStatistic();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.github.JBolivarLi.javarushtelegrambot.bot.service;

import com.github.JBolivarLi.javarushtelegrambot.bot.dto.GroupStatDTO;
import com.github.JBolivarLi.javarushtelegrambot.bot.dto.StatisticDTO;
import com.github.JBolivarLi.javarushtelegrambot.bot.repository.entity.TelegramUser;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

import static org.springframework.util.CollectionUtils.isEmpty;


@Service
public class StatisticsServiceImpl implements StatisticsService {

private final GroupSubService groupSubService;
private final TelegramUserService telegramUserService;

public StatisticsServiceImpl(GroupSubService groupSubService, TelegramUserService telegramUserService) {
this.groupSubService = groupSubService;
this.telegramUserService = telegramUserService;
}

@Override
public StatisticDTO countBotStatistic() {
List<GroupStatDTO> groupStatDTOS = groupSubService.findAll().stream()
.filter(it -> !isEmpty(it.getUsers()))
.map(groupSub -> new GroupStatDTO(groupSub.getId(), groupSub.getTitle(), groupSub.getUsers().size()))
.collect(Collectors.toList());
List<TelegramUser> allInActiveUsers = telegramUserService.findAllInActiveUsers();
List<TelegramUser> allActiveUsers = telegramUserService.findAllActiveUsers();

double groupsPerUser = getGroupsPerUser(allActiveUsers);
return new StatisticDTO(allActiveUsers.size(), allInActiveUsers.size(), groupStatDTOS, groupsPerUser);
}

private double getGroupsPerUser(List<TelegramUser> allActiveUsers) {
return (double) allActiveUsers.stream().mapToInt(it -> it.getGroupSubs().size()).sum() / allActiveUsers.size();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,17 @@ public interface TelegramUserService {
* @return {@link TelegramUser} with provided chat ID or null otherwise.
*/
Optional<TelegramUser> findByChatId(String chatId);
/**
* Retrieve all inactive {@link TelegramUser}
*
* @return the collection of the inactive {@link TelegramUser} objects.
*/
List<TelegramUser> findAllInActiveUsers();
/**
* Find all active {@link TelegramUser}.
*
* @return the collection of the active {@link TelegramUser} objects.
*/
List<TelegramUser> findAllActiveUsers();

}
Loading

0 comments on commit ab8cf89

Please sign in to comment.