Сильно переделанная версия, добавлены избранные контакты, отправка фото и т.п.

This commit is contained in:
V1RTUOZ
2025-04-30 02:34:18 +03:00
parent 608c79d3de
commit a205f274b5
7 changed files with 529 additions and 132 deletions
+12 -8
View File
@@ -3,6 +3,7 @@
public class EmployeeContact public class EmployeeContact
{ {
public static string GeneralPhoneNumber => "+78123352577"; public static string GeneralPhoneNumber => "+78123352577";
public EmployeeContact(Employee employee) public EmployeeContact(Employee employee)
{ {
FullName = employee.FullName; FullName = employee.FullName;
@@ -20,7 +21,9 @@ public class EmployeeContact
Department = employee.Department; Department = employee.Department;
Position = employee.Position; Position = employee.Position;
ExtensionNumber = employee.Phone ?? null; //string.IsNullOrEmpty(employee.Phone) ? null : employee.Phone; ExtensionNumber = employee.Phone ?? null; //string.IsNullOrEmpty(employee.Phone) ? null : employee.Phone;
Phone = string.IsNullOrEmpty(ExtensionNumber) ? GeneralPhoneNumber : $"{GeneralPhoneNumber},{ExtensionNumber}"; Phone = string.IsNullOrEmpty(ExtensionNumber)
? GeneralPhoneNumber
: $"{GeneralPhoneNumber},{ExtensionNumber}";
if (!string.IsNullOrEmpty(employee.Mobile)) if (!string.IsNullOrEmpty(employee.Mobile))
{ {
Mobile = employee.Mobile; Mobile = employee.Mobile;
@@ -34,13 +37,14 @@ public class EmployeeContact
{ {
get get
{ {
string text = "BEGIN:VCARD\n" string text =
+ "VERSION:2.1\n" "BEGIN:VCARD\n"
+ $"N:{LastName};{FirstName}\n" + "VERSION:2.1\n"
+ $"FN:{FullName}\n" + $"N:{LastName};{FirstName}\n"
+ "ORG:NSSZ\n" + $"FN:{FullName}\n"
+ $"ROLE:{Department}\n" + "ORG:NSSZ\n"
+ $"TITLE:{Position}\n"; + $"ROLE:{Department}\n"
+ $"TITLE:{Position}\n";
if (!string.IsNullOrEmpty(Mobile)) if (!string.IsNullOrEmpty(Mobile))
text += $"TEL;CELL:{Mobile}\n"; text += $"TEL;CELL:{Mobile}\n";
+56
View File
@@ -0,0 +1,56 @@
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace nsszcontactbot;
public class FavoriteContactsManager
{
private readonly IDatabase _redisDb;
private const string KeyPrefix = "user:favorites:";
public FavoriteContactsManager(ConnectionMultiplexer redis)
{
_redisDb = redis.GetDatabase();
}
/// <summary>
/// Добавить контакт в избранное.
/// </summary>
public async Task AddFavoriteAsync(long userId, string contactId)
{
string key = GetRedisKey(userId);
await _redisDb.SetAddAsync(key, contactId);
}
/// <summary>
/// Удалить контакт из избранного.
/// </summary>
public async Task RemoveFavoriteAsync(long userId, string contactId)
{
string key = GetRedisKey(userId);
await _redisDb.SetRemoveAsync(key, contactId);
}
/// <summary>
/// Проверить, является ли контакт избранным.
/// </summary>
public async Task<bool> IsFavoriteAsync(long userId, string contactId)
{
string key = GetRedisKey(userId);
return await _redisDb.SetContainsAsync(key, contactId);
}
/// <summary>
/// Получить список всех избранных контактов пользователя.
/// </summary>
public async Task<List<string>> GetAllFavoritesAsync(long userId)
{
string key = GetRedisKey(userId);
var members = await _redisDb.SetMembersAsync(key);
return members.Select(m => m.ToString()).ToList();
}
private string GetRedisKey(long userId) => $"{KeyPrefix}{userId}";
}
+18
View File
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types.ReplyMarkups;
namespace nsszcontactbot
{
internal static class InlineKeyboardMarkupExtensions
{
internal static InlineKeyboardMarkup AddCloseButton(this InlineKeyboardMarkup markup, bool newRow = true)
{
var buttonRow = newRow ? markup.AddNewRow() : markup;
return buttonRow.AddButton("❌ Закрыть", "close");
}
}
}
+402 -122
View File
@@ -4,6 +4,16 @@ using Telegram.Bot.Polling;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums; using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.ReplyMarkups; using Telegram.Bot.Types.ReplyMarkups;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Serilog;
using System.Timers;
using Serilog.Core;
using NRedisStack;
using NRedisStack.RedisStackCommands;
using Timer = System.Timers.Timer;
using StackExchange.Redis;
namespace nsszcontactbot; namespace nsszcontactbot;
@@ -12,48 +22,87 @@ public class Program
private static ITelegramBotClient Bot; private static ITelegramBotClient Bot;
private static List<Employee> Employees = new(); private static List<Employee> Employees = new();
private static List<string> Departments = new(); private static List<string> Departments = new();
private static int CurrentPage = 0; // Текущая страница для пагинации private static IConfigurationRoot config;
private static int PageSize = 5; // Количество подразделений на странице private static FavoriteContactsManager FavoritesManager;
//private static ILogger<Program> Logger;
public static async Task Main(string[] args) public static async Task<int> Main(string[] args)
{ {
Bot = new TelegramBotClient("6237449447:AAEGMmpx-1hUEApFZZS_ySAMZErseKJ8dHo"); // Укажите ваш токен config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(config).CreateLogger();
var botToken = config["Telegram:BotToken"];
if (botToken == null)
{
Log.Error("Токен Telegram-бота не указан в конфигурации.");
return 1;
}
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(config["Redis:Configuration"]!, (conf) =>
{
conf.User = config["Redis:User"];
conf.Password = config["Redis:Password"];
});
FavoritesManager = new FavoriteContactsManager(redis);
Bot = new TelegramBotClient(botToken);
List<BotCommand> cmds = new(); List<BotCommand> cmds = new();
await Bot.SetMyCommandsAsync(cmds); await Bot.SetMyCommands(cmds);
LoadEmployees(); if(!LoadEmployees())
var me = await Bot.GetMeAsync(); {
Console.WriteLine($"Бот запущен: @{me.Username}"); return 1;
}
StartUpdatingEmployeesData();
var me = await Bot.GetMe();
Log.Information($"Бот запущен: @{me.Username}");
// Запуск обработки обновлений // Запуск обработки обновлений
var cancellationToken = new CancellationTokenSource().Token; var cancellationToken = new CancellationTokenSource().Token;
ReceiverOptions receiverOptions = ReceiverOptions receiverOptions =
new() new()
{ {
AllowedUpdates = Array.Empty<UpdateType>() // receive all update types except ChatMember related updates AllowedUpdates = Array.Empty<UpdateType>() // receive all update types except ChatMember related updates
}; };
Bot.StartReceiving(HandleUpdateAsync, HandleErrorAsync, receiverOptions: receiverOptions, cancellationToken: cancellationToken); Bot.StartReceiving(
HandleUpdateAsync,
HandleErrorAsync,
receiverOptions: receiverOptions,
cancellationToken: cancellationToken
);
Console.WriteLine("Нажмите Enter для выхода..."); Console.WriteLine("Нажмите Enter для выхода...");
Console.ReadLine(); Console.ReadLine();
return 0;
} }
private static async Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken) private static async Task HandleUpdateAsync(
ITelegramBotClient botClient,
Update update,
CancellationToken cancellationToken
)
{ {
if (update.Type == UpdateType.Message && update.Message?.Text != null) if (update.Type == UpdateType.Message && update.Message?.Text != null)
{ {
var message = update.Message; var message = update.Message;
Log.Debug($"INPUT: from={message.From?.Username} text={message.Text}");
if (message.Text.StartsWith("/start")) if (message.Text.StartsWith("/start"))
{ {
await StartCommand(message); await StartCommand(message);
} }
else if (message.Text.StartsWith("/choose_department")) else if (message.Text.EndsWith("Список подразделений"))
{ {
await ChooseDepartment(message); await ChooseDepartment(message);
} }
else if (message.ReplyToMessage != null && message.ReplyToMessage.Text!.StartsWith("Выберите подразделение")) else if (message.Text.EndsWith("Избранные контакты"))
{ {
await HandleDepartmentSelection(message); await HandleShowFavorites(message);
} }
else else
{ {
@@ -74,57 +123,82 @@ public class Program
await HandleAddContact(update.CallbackQuery, dataParts[1]); await HandleAddContact(update.CallbackQuery, dataParts[1]);
break; break;
} }
case "addfavorite":
{
if (dataParts.Length != 2)
break;
await HandleAddFavorite(update.CallbackQuery, dataParts[1]);
break;
}
case "delfavorite":
{
if (dataParts.Length != 2)
break;
await HandleDelFavorite(update.CallbackQuery, dataParts[1]);
break;
}
case "showdepartment":
{
if (dataParts.Length != 2)
break;
await HandleShowDepartment(update.CallbackQuery, int.Parse(dataParts[1]));
break;
}
case "showemployee":
{
if (dataParts.Length != 2)
break;
await HandleShowEmployee(update.CallbackQuery, dataParts[1]);
break;
}
case "close":
{
await HandleClose(
update.CallbackQuery,
dataParts.Length > 1 ? dataParts[1] : null
);
break;
}
default: default:
break; break;
} }
} }
} }
} }
private static async Task StartCommand(Message message) private static async Task StartCommand(Message message)
{ {
string text = "Привет! Я бот для поиска контактов сотрудников. Введите запрос.\n"; string text = "Привет! Я бот для поиска контактов сотрудников. Введите критерии поиска или воспользуйтесь кнопками внизу.\n";
//text += "/choose_department - Выбрать подразделение\n"; await Bot.SendMessage(message.Chat.Id, text, replyMarkup: new string[] { "⭐️ Избранные контакты", "🏢 Список подразделений" });
await Bot.SendTextMessageAsync(message.Chat.Id, text);
} }
private static async Task ChooseDepartment(Message message) private static async Task ChooseDepartment(Message message)
{ {
Departments = Employees.Select(e => e.Department).Distinct().ToList(); Departments = Employees.Select(e => e.Department).Distinct().ToList();
CurrentPage = 0; // Сброс страницы
await ShowDepartments(message.Chat.Id); await ShowDepartments(message.Chat.Id);
} }
private static async Task ShowDepartments(long chatId) private static async Task ShowDepartments(long chatId)
{ {
var totalDepartments = Departments.Count; string text = "Выберите подразделение:";
var totalPages = (int)Math.Ceiling((double)totalDepartments / PageSize); var keyboardMarkup = new InlineKeyboardMarkup();
var departmentsToShow = Departments.Skip(CurrentPage * PageSize).Take(PageSize).ToList();
string text = "Выберите подразделение:\n"; var departmentIndex = 0;
text += string.Join("\n", departmentsToShow.Select((d, i) => $"{i + 1 + CurrentPage * PageSize}. {d}")); foreach (var department in Departments)
// Создание кнопок
var inlineKeyboard = new List<List<InlineKeyboardButton>>();
if (CurrentPage > 0)
{ {
inlineKeyboard.Add(new List<InlineKeyboardButton> keyboardMarkup
{ .AddNewRow()
InlineKeyboardButton.WithCallbackData("◀️ Назад", "prev") .AddButton($"{department}", $"showdepartment/{departmentIndex++}");
});
} }
if (CurrentPage < totalPages - 1) //keyboardMarkup.AddCloseButton();
{ await Bot.SendMessage(chatId, text, replyMarkup: keyboardMarkup);
inlineKeyboard.Add(new List<InlineKeyboardButton> await Task.Delay(999);
{
InlineKeyboardButton.WithCallbackData("Вперед ▶️", "next")
});
}
var keyboardMarkup = new InlineKeyboardMarkup(inlineKeyboard);
await Bot.SendTextMessageAsync(chatId, text, replyMarkup: keyboardMarkup);
} }
private static async Task HandleSearchInput(Message message) private static async Task HandleSearchInput(Message message)
@@ -132,23 +206,48 @@ public class Program
if (!string.IsNullOrEmpty(message.Text)) if (!string.IsNullOrEmpty(message.Text))
{ {
string query = message.Text.Trim().ToLower(); string query = message.Text.Trim().ToLower();
if (query.Length < 3) if (query.Length < 4)
{ {
await Bot.SendTextMessageAsync(message.Chat.Id, "Минимальная длина строки поиска - 3 символа."); await Bot.SendMessage(
message.Chat.Id,
"Минимальная длина строки поиска - 4 символа."
);
return; return;
} }
// Поиск сотрудников по полям // Поиск сотрудников по полям
var results = Employees.Where(e => var results = Employees
e.FullName.ToLower().Contains(query) || .Where(
(e.Mail != null && e.Mail.ToLower().Contains(query)) || e =>
(e.Phone != null && e.Phone.Contains(query)) || e.FullName.ToLower().Contains(query)
(e.Mobile != null && e.Mobile.Contains(query)) || || (e.Mail != null && e.Mail.ToLower().Contains(query))
(e.IP != null && e.IP.Contains(query)) || (e.Phone != null && e.Phone.Contains(query))
).OrderBy(e => e.FullName.ToLower().IndexOf(query)).ToList(); || (e.Mobile != null && e.Mobile.Contains(query))
|| (e.IP != null && e.IP.Contains(query))
)
.OrderBy(e => e.FullName.ToLower().IndexOf(query))
.ToList();
// Отправка результатов поиска // Отправка результатов поиска
await ShowEmployeeResults(message.Chat.Id, results); await ShowEmployeeResults(message, results, null);
}
}
private static async Task HandleShowFavorites(Message message)
{
if (!string.IsNullOrEmpty(message.Text))
{
var ids = await FavoritesManager.GetAllFavoritesAsync(message.From.Id);
// Поиск сотрудников по полям
var results = Employees
.Where(
e => ids.Contains(e.Id)
)
.OrderBy(e => e.FullName)
.ToList();
// Отправка результатов поиска
await ShowEmployeeResults(message, results, true);
} }
} }
@@ -160,79 +259,223 @@ public class Program
if (employee != null) if (employee != null)
{ {
EmployeeContact contact = new(employee); EmployeeContact contact = new(employee);
string phoneNumber = !string.IsNullOrEmpty(contact.Mobile) ? contact.Mobile : contact.Phone; string phoneNumber = !string.IsNullOrEmpty(contact.Mobile)
var replyParameters = new ReplyParameters() { MessageId = callbackQuery.Message.MessageId, QuoteParseMode = ParseMode.Html, Quote = $"<b>{contact.FullName}</b>" }; ? contact.Mobile
await Bot.SendContactAsync(callbackQuery.Message.Chat.Id, phoneNumber, contact.FirstName, lastName: contact.LastName, vcard: contact.VCard, replyParameters: replyParameters); : contact.Phone;
var replyParameters = new ReplyParameters()
{
MessageId = callbackQuery.Message.MessageId,
QuoteParseMode = ParseMode.Html,
Quote = $"<b>{contact.FullName}</b>"
};
var keyboardMarkup = new InlineKeyboardMarkup()
//.AddNewRow()
.AddCloseButton();
await Bot.SendContact(
callbackQuery.Message.Chat.Id,
phoneNumber,
contact.FirstName,
lastName: contact.LastName,
vcard: contact.VCard,
replyParameters: replyParameters,
replyMarkup: keyboardMarkup,
protectContent: true
);
await Task.Delay(999); await Task.Delay(999);
} }
} }
await Bot.AnswerCallbackQueryAsync(callbackQuery.Id); await Bot.AnswerCallbackQuery(callbackQuery.Id);
} }
private static async Task HandleDepartmentSelection(Message message) private static async Task HandleAddFavorite(CallbackQuery callbackQuery, string contactId)
{ {
if (message.Text.StartsWith("◀️ Назад")) if (callbackQuery.Message != null)
{ {
if (CurrentPage > 0) var employee = Employees.Where(e => e.Id == contactId).First();
if (employee != null)
{ {
CurrentPage--; await FavoritesManager.AddFavoriteAsync(callbackQuery.From.Id, contactId);
await ShowDepartments(message.Chat.Id); foreach (var row in callbackQuery.Message.ReplyMarkup.InlineKeyboard)
} foreach (var cell in row)
} {
else if (message.Text.StartsWith("Вперед ▶️")) if (cell.CallbackData.Contains("addfavorite"))
{ {
CurrentPage++; cell.CallbackData = $"delfavorite/{contactId}";
await ShowDepartments(message.Chat.Id); cell.Text = "💔 Не избранный";
} }
else
{ }
int selectedIndex = int.Parse(message.Text) - 1; await Bot.EditMessageReplyMarkup(callbackQuery.Message.Chat.Id, callbackQuery.Message.MessageId, callbackQuery.Message.ReplyMarkup);
if (selectedIndex >= 0 && selectedIndex < Departments.Count) await Bot.AnswerCallbackQuery(callbackQuery.Id, "✔️ Контакт добавлен в избранные");
{
string selectedDepartment = Departments[selectedIndex];
var results = Employees.Where(e => e.Department == selectedDepartment).ToList();
await ShowEmployeeResults(message.Chat.Id, results);
}
else
{
await Bot.SendTextMessageAsync(message.Chat.Id, "Некорректный выбор.");
} }
} }
} }
private static async Task ShowEmployeeResults(long chatId, List<Employee> results) private static async Task HandleDelFavorite(CallbackQuery callbackQuery, string contactId)
{
if (callbackQuery.Message != null)
{
var employee = Employees.Where(e => e.Id == contactId).First();
if (employee != null)
{
await FavoritesManager.RemoveFavoriteAsync(callbackQuery.From.Id, contactId);
foreach (var row in callbackQuery.Message.ReplyMarkup.InlineKeyboard)
foreach (var cell in row)
{
if (cell.CallbackData.Contains("delfavorite"))
{
cell.CallbackData = $"addfavorite/{contactId}";
cell.Text = "❤️ В избранные";
}
}
await Bot.EditMessageReplyMarkup(callbackQuery.Message.Chat.Id, callbackQuery.Message.MessageId, callbackQuery.Message.ReplyMarkup);
await Bot.AnswerCallbackQuery(callbackQuery.Id, "✔️ Контакт удален из избранных");
}
}
}
private static async Task HandleShowDepartment(CallbackQuery callbackQuery, int departmentIndex)
{
await Bot.AnswerCallbackQuery(callbackQuery.Id);
if (callbackQuery.Message != null)
{
await Bot.DeleteMessage(
callbackQuery.Message.Chat.Id,
callbackQuery.Message.MessageId
);
var employees = Employees
.Where(e => e.Department == Departments[departmentIndex])
.OrderBy(e => e.FullName)
.ToList();
if (employees != null)
{
await ShowEmployeeResults(callbackQuery.Message, employees, null);
}
}
//await Bot.AnswerCallbackQueryAsync(callbackQuery.Id);
}
private static async Task HandleShowEmployee(CallbackQuery callbackQuery, string id)
{
if (callbackQuery.Message != null)
{
var employee = Employees.Where(e => e.Id == id).First();
if (employee != null)
{
var isFavorite = await FavoritesManager.IsFavoriteAsync(callbackQuery.From.Id, id);
await ShowEmployeeCard(callbackQuery.Message.Chat.Id, employee, isFavorite, closeButton: true);
}
}
await Bot.AnswerCallbackQuery(callbackQuery.Id);
}
private static async Task HandleClose(CallbackQuery callbackQuery, string? nextAction)
{
if (callbackQuery.Message != null)
{
await Bot.DeleteMessage(
callbackQuery.Message.Chat.Id,
callbackQuery.Message.MessageId
);
await Task.Delay(500);
}
await Bot.AnswerCallbackQuery(callbackQuery.Id);
}
private static async Task ShowEmployeeCard(long chatId, Employee employee, bool isFavorite = false, bool contactButton = true, bool favoriteButton = true, bool closeButton = false)
{
{
var keyboardMarkup = new InlineKeyboardMarkup();
var keyboardRow = keyboardMarkup.AddNewRow();
if (contactButton)
keyboardRow.AddButton("👤 Контакт", $"addcontact/{employee.Id}");
if (favoriteButton)
{
if (isFavorite)
{
keyboardRow.AddButton("💔 Не избранный", $"delfavorite/{employee.Id}");
}
else
{
keyboardRow.AddButton("❤️ В избранные", $"addfavorite/{employee.Id}");
}
}
if (closeButton)
keyboardRow.AddCloseButton();
var card = CreateEmployeeCard(employee);
string photoPath = Path.Combine(config["Paths:PhotoBasePath"]!, $"{employee.FullName}.jpg");
try
{
await using var fileStream = new FileStream(
photoPath,
FileMode.Open,
FileAccess.Read
);
await Bot.SendPhoto(
chatId,
fileStream,
caption: card,
parseMode: ParseMode.Html,
replyMarkup: keyboardMarkup
);
}
catch (FileNotFoundException)
{
await Bot.SendMessage(
chatId,
card,
ParseMode.Html,
replyMarkup: keyboardMarkup,
protectContent: true
);
}
finally
{
await Task.Delay(999);
}
}
}
private static async Task ShowEmployeeResults(Message message, List<Employee> results, bool? isFavorite = false)
{ {
if (results.Any()) if (results.Any())
{ {
foreach (var employee in results) if (results.Count < 10)
{ {
var keyboardMarkup = new InlineKeyboardMarkup() foreach (var employee in results)
//.AddNewRow("1.1", "1.2", "1.3") {
.AddNewRow() bool bFavorite = isFavorite.HasValue ? isFavorite == true : await FavoritesManager.IsFavoriteAsync(message.From.Id, employee.Id);
.AddButton("👤 Контакт", $"addcontact/{employee.Id}"); await ShowEmployeeCard(message.Chat.Id, employee, bFavorite);
//.AddButton("В избранные", $"addfavorite/{employee.Id}"); }
//.AddButton(InlineKeyboardButton.WithUrl("Написать письмо", $"mailto:{employee.Mail}")); }
else
{
string text = "Вот, что удалось найти:";
var keyboardMarkup = new InlineKeyboardMarkup();
var card = CreateEmployeeCard(employee); foreach (var employee in results)
string photoPath = $"data/photos/{employee.FullName}.jpg";
try
{ {
await using var fileStream = new FileStream(photoPath, FileMode.Open, FileAccess.Read); keyboardMarkup
await Bot.SendPhotoAsync(chatId, fileStream, caption: card, parseMode: ParseMode.Html, replyMarkup: keyboardMarkup); .AddNewRow()
} .AddButton(employee.FullName, $"showemployee/{employee.Id}");
catch (FileNotFoundException)
{
await Bot.SendTextMessageAsync(chatId, card, null, ParseMode.Html, replyMarkup: keyboardMarkup);
}
finally
{
await Task.Delay(999);
} }
await Bot.SendMessage(message.Chat.Id, text, replyMarkup: keyboardMarkup, protectContent: true);
await Task.Delay(999);
} }
} }
else else
{ {
await Bot.SendTextMessageAsync(chatId, "Сотрудники не найдены."); await Bot.SendMessage(message.Chat.Id, "🔍 Извините, мы ничего не нашли.");
await Task.Delay(999);
} }
} }
@@ -263,9 +506,10 @@ public class Program
private static string CreateEmployeeCard(Employee employee) private static string CreateEmployeeCard(Employee employee)
{ {
EmployeeContact contact = new(employee); EmployeeContact contact = new(employee);
string card = $"👤 <b>{contact.FullName}</b>\n" + string card =
$"🏢 {contact.Department}\n" + $"👤 <b>{contact.FullName}</b>\n"
$"🎓 {contact.Position}\n"; + $"🏢 {contact.Department}\n"
+ $"🎓 {contact.Position}\n";
if (!string.IsNullOrEmpty(contact.Mail)) if (!string.IsNullOrEmpty(contact.Mail))
card += $"✉️ {contact.Mail}\n"; card += $"✉️ {contact.Mail}\n";
@@ -275,8 +519,8 @@ public class Program
if (!string.IsNullOrEmpty(contact.ExtensionNumber)) if (!string.IsNullOrEmpty(contact.ExtensionNumber))
card += $"📞 {contact.ExtensionNumber}\n"; card += $"📞 {contact.ExtensionNumber}\n";
//if (!string.IsNullOrEmpty(employee.IP)) if (!string.IsNullOrEmpty(employee.IP))
// card += $"🌐 {employee.IP}\n"; card += $"🌐 {employee.IP}\n";
card += GetEventStatus(employee); card += GetEventStatus(employee);
@@ -285,12 +529,14 @@ public class Program
private static string CreateEmployeeCard2(Employee employee) private static string CreateEmployeeCard2(Employee employee)
{ {
string photoUrl = $"https://contacts.int.nssz.ru/data/photos/{employee.FullName.Replace(" ", "%20")}.jpg"; // Формирование пути к фотографии string photoUrl =
$"https://contacts.int.nssz.ru/data/photos/{employee.FullName.Replace(" ", "%20")}.jpg"; // Формирование пути к фотографии
string card = $"👤 <b>{employee.FullName}</b>\n" + string card =
$"🏢 Отдел: {employee.Department}\n" + $"👤 <b>{employee.FullName}</b>\n"
$"🎓 Должность: {employee.Position}\n" + + $"🏢 Отдел: {employee.Department}\n"
$"📸 Фото: <a href='{photoUrl}'>Посмотреть фото</a>\n"; // Добавление ссылки на фото + $"🎓 Должность: {employee.Position}\n"
+ $"📸 Фото: <a href='{photoUrl}'>Посмотреть фото</a>\n"; // Добавление ссылки на фото
if (!string.IsNullOrEmpty(employee.Mail)) if (!string.IsNullOrEmpty(employee.Mail))
card += $"✉️ Почта: {employee.Mail}\n"; card += $"✉️ Почта: {employee.Mail}\n";
@@ -306,16 +552,50 @@ public class Program
return card; return card;
} }
private static void LoadEmployees() private static Timer? updateTimer = null;
private static void StartUpdatingEmployeesData(int intervalMs = 1 * 60 * 60 * 1000)
{ {
// Загрузка данных сотрудников из JSON файла if (updateTimer != null) return;
var json = System.IO.File.ReadAllText("data/contacts.json"); updateTimer = new Timer(intervalMs);
Employees = JsonConvert.DeserializeObject<List<Employee>>(json)!; updateTimer.Elapsed += UpdateTimer_Elapsed;
updateTimer.AutoReset = true; // Запускать снова после завершения
updateTimer.Enabled = true;
} }
private static Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, CancellationToken cancellationToken) private static void UpdateTimer_Elapsed(object? sender, ElapsedEventArgs e)
{ {
Console.WriteLine($"Произошла ошибка: {exception.Message}"); LoadEmployees();
}
private static int prevHash = 0;
private static bool LoadEmployees()
{
try
{
// Загрузка данных сотрудников из JSON файла при наличии изменений
var json = System.IO.File.ReadAllText(config["Paths:ContactsJsonPath"]!);
int newHash = json.GetHashCode();
if (prevHash == newHash)
{
return true;
}
prevHash = newHash;
Employees = JsonConvert.DeserializeObject<List<Employee>>(json)!;
Log.Information("Загружены данные о {Count} сотрудниках", Employees.Count);
return true;
} catch (Exception ex) {
Log.Error(ex, "Ошибка при загрузке списка сотрудников");
return false;
}
}
private static Task HandleErrorAsync(
ITelegramBotClient botClient,
Exception exception,
CancellationToken cancellationToken
)
{
Log.Error(exception, "Произошла ошибка");
return Task.CompletedTask; return Task.CompletedTask;
} }
} }
+28
View File
@@ -0,0 +1,28 @@
{
"Paths": {
"ContactsJsonPath": "data/contacts.json",
"PhotoBasePath": "data/photos"
},
"Telegram": {
"BotToken": "8155021946:AAGbfJnLa0sTWxqFB9yjbXhbTedBw4wvcQE"
},
"Redis": {
"Configuration": "redis-15840.crce198.eu-central-1-3.ec2.redns.redis-cloud.com:15840",
"User": "tgbot",
"Password": "0aCKMee9Ocq88KzfjWyC9AmB25tLiY93%"
},
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "nsszcontactbot.log",
"rollingInterval": "Day"
}
}
]
}
}
+12 -1
View File
@@ -7,8 +7,19 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Telegram.Bot" Version="21.11.0" /> <PackageReference Include="NRedisStack" Version="0.13.2" />
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Telegram.Bot" Version="22.4.4" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>