|
using Microsoft.Playwright; |
|
using Newtonsoft.Json; |
|
using Telegram.Bot; |
|
using Telegram.Bot.Types.InputFiles; |
|
|
|
var eduPassOptions = JsonConvert.DeserializeObject<EduPassOptions>(File.ReadAllText("appsettings.json")); |
|
|
|
var telegramBot = new EduPassTelegramBot(eduPassOptions); |
|
var taxisnetClient = new EduPassTaxisnetClient(eduPassOptions); |
|
|
|
foreach (var student in eduPassOptions.Students) |
|
{ |
|
await telegramBot.SendProcessingStartedAsync(student); |
|
var output = await taxisnetClient.RunAsync(student); |
|
|
|
using (var screenshotStream = new MemoryStream(output.ScreenshotBytes)) |
|
{ |
|
await telegramBot.SendScreenshotAsync(student, screenshotStream, "png"); |
|
} |
|
|
|
using (var pdfStream = new MemoryStream(output.PdfBytes)) |
|
{ |
|
await telegramBot.SendScreenshotAsync(student, pdfStream, "pdf"); |
|
} |
|
} |
|
|
|
// The program ends here |
|
|
|
public class EduPassOptions |
|
{ |
|
public string TaxisnetUsername = string.Empty; |
|
public string TaxisnetPassword = string.Empty; |
|
public string TelegramBotToken = string.Empty; |
|
public string TelegramChatId = string.Empty; |
|
public DateTime RunningDate = DateTime.Now; |
|
public Student[] Students = new Student[0]; |
|
|
|
public class Student |
|
{ |
|
public string SchoolCounty = String.Empty; |
|
public string SchoolRegion = String.Empty; |
|
public string SchoolMunicipality = String.Empty; |
|
public string SchoolCategory = string.Empty; |
|
public string SchoolType = string.Empty; |
|
public string SchoolName = string.Empty; |
|
public string StudentFirstName = string.Empty; |
|
public string StudentLastName = string.Empty; |
|
public DateTime StudentBirthDate; |
|
public string StudentAmkaNumber = string.Empty; |
|
} |
|
} |
|
|
|
public class EduPassTelegramBot |
|
{ |
|
private readonly ITelegramBotClient? _botClient; |
|
|
|
private readonly string _chatId; |
|
|
|
private readonly DateTime _runningDate; |
|
|
|
public EduPassTelegramBot(EduPassOptions options) |
|
{ |
|
if (!string.IsNullOrEmpty(options.TelegramBotToken)) |
|
{ |
|
_botClient = new TelegramBotClient(options.TelegramBotToken); |
|
} |
|
_chatId = options.TelegramChatId; |
|
_runningDate = options.RunningDate; |
|
} |
|
|
|
public Task SendProcessingStartedAsync(EduPassOptions.Student student) |
|
{ |
|
if (_botClient == null) return Task.CompletedTask; |
|
return _botClient.SendTextMessageAsync(_chatId, |
|
$"Ξεκινησε η διαδικασία παραγωγής της δήλωσης EduPass για τον/την μαθητή/τρια " + |
|
$"{student.StudentFirstName} {student.StudentLastName} στις {_runningDate:ddd, dd MMM yyyy}."); |
|
} |
|
|
|
public Task SendScreenshotAsync(EduPassOptions.Student student, Stream stream, string extension) |
|
{ |
|
if (_botClient == null) return Task.CompletedTask; |
|
var onlineFile = new InputOnlineFile(stream, $"{student.StudentFirstName} {student.StudentLastName} - {_runningDate:yyyyMMdd}.{extension}"); |
|
return _botClient.SendDocumentAsync(_chatId, onlineFile); |
|
} |
|
} |
|
|
|
public class EduPassTaxisnetClient |
|
{ |
|
private readonly string _username; |
|
|
|
private readonly string _password; |
|
|
|
private readonly DateTime _runningDate; |
|
|
|
public EduPassTaxisnetClient(EduPassOptions options) |
|
{ |
|
_username = options.TaxisnetUsername; |
|
_password = options.TaxisnetPassword; |
|
_runningDate = options.RunningDate; |
|
} |
|
|
|
public async Task<(byte[] ScreenshotBytes, byte[] PdfBytes)> RunAsync(EduPassOptions.Student student) |
|
{ |
|
using var playwright = await Playwright.CreateAsync(); |
|
await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = true }); |
|
var page = await browser.NewPageAsync(new BrowserNewPageOptions { ViewportSize = new ViewportSize { Width = 1280, Height = 1200 } }); |
|
|
|
await page.GotoAsync("https://edupass.gov.gr/start/"); |
|
await page.ClickAsync("input[value='schools']"); |
|
await page.ClickAsync("button[type='submit']"); |
|
|
|
await page.WaitForNavigationAsync(); |
|
await page.ClickAsync("input[value='studentCard']"); |
|
await page.ClickAsync("button[type='submit']"); |
|
|
|
await page.WaitForNavigationAsync(); |
|
await page.ClickAsync("a[label='Σύνδεση']"); |
|
|
|
await page.WaitForNavigationAsync(); |
|
await page.ClickAsync("button[type='button']:has-text('Taxisnet')"); |
|
|
|
// Αυθεντικοποίηση Χρήστη |
|
await page.FillAsync("input[name='j_username']", _username); |
|
await page.FillAsync("input[name='j_password']", _password); |
|
await page.ClickAsync("button#btn-login-submit", new PageClickOptions { Force = true, NoWaitAfter = true }); |
|
try |
|
{ |
|
await page.ClickAsync("button#btn-submit", new PageClickOptions { Force = true, NoWaitAfter = true, Timeout = 3000 }); |
|
} |
|
catch |
|
{ |
|
// Expected to timeout if not exist |
|
} |
|
await page.ClickAsync("button[label='Συνέχεια']"); |
|
await page.ClickAsync("button[type='button']:has-text('Αποδοχή')", new PageClickOptions { Force = true, NoWaitAfter = true }); |
|
|
|
// Δήλωση EDUPASS - Σχολική Κάρτα |
|
// Συμπληρώστε τα στοιχεία του σχολείου στο οποίο φοιτά ο μαθητής |
|
|
|
await page.ClickAsync("div[customlabel='Περιφέρεια']"); |
|
await page.ClickAsync($"li[data-value='{student.SchoolCounty}']"); |
|
await page.ClickAsync("div[customlabel='Περιφερειακή Ενότητα']"); |
|
await page.ClickAsync($"li[data-value='{student.SchoolRegion}']"); |
|
await page.ClickAsync("div[customlabel='Δήμος']"); |
|
await page.ClickAsync($"li[data-value='{student.SchoolMunicipality}']"); |
|
await page.ClickAsync("div[customlabel='Κατηγορία']"); |
|
await page.ClickAsync($"li[data-value='{student.SchoolCategory}']"); |
|
await page.ClickAsync("div[customlabel='Τύπος']"); |
|
await page.ClickAsync($"li[data-value='{student.SchoolType}']"); |
|
await page.ClickAsync("div[customlabel='Σχολείο']"); |
|
await page.ClickAsync($"li[data-value='{student.SchoolName}']"); |
|
|
|
// Συμπληρώστε τα στοιχεία του μαθητή |
|
|
|
await page.FillAsync("input[name='input_firstname']", student.StudentFirstName); |
|
await page.FillAsync("input[name='input_lastname']", student.StudentLastName); |
|
await page.FillAsync("input[name='input_dob-day']", $"{student.StudentBirthDate:dd}"); |
|
await page.FillAsync("input[name='input_dob-month']", $"{student.StudentBirthDate:MM}"); |
|
await page.FillAsync("input[name='input_dob-year']", $"{student.StudentBirthDate:yyyy}"); |
|
await page.FillAsync("input[name='input_amka']", student.StudentAmkaNumber); |
|
await page.ClickAsync("div#mui-component-select-can_use_amka"); |
|
await page.ClickAsync("li[data-value='ΝΑΙ']"); |
|
|
|
// Συμπληρώστε τα στοιχεία self-test |
|
|
|
await page.FillAsync("input[name='self_test_date-day']", $"{_runningDate:dd}"); |
|
await page.FillAsync("input[name='self_test_date-month']", $"{_runningDate:MM}"); |
|
await page.FillAsync("input[name='self_test_date-year']", $"{_runningDate:yyyy}"); |
|
await page.ClickAsync("div#mui-component-select-self_test_result"); |
|
await page.ClickAsync("li[data-value='ΑΡΝΗΤΙΚΟ']"); |
|
await page.ClickAsync("button[label='Υποβολή']"); |
|
|
|
// Η δήλωση υποβλήθηκε |
|
|
|
await page.WaitForNavigationAsync(); |
|
|
|
// Prepare outputs |
|
|
|
var screenshotBytes = await page.ScreenshotAsync(new PageScreenshotOptions() { FullPage = true }); |
|
|
|
await page.EmulateMediaAsync(new PageEmulateMediaOptions() { Media = Media.Print }); |
|
var path = $"{student.StudentFirstName} {student.StudentLastName} - {_runningDate:yyyyMMdd}.pdf"; |
|
var pdfBytes = await page.PdfAsync(new PagePdfOptions { Path = path, Format = "A4" }); |
|
|
|
return (screenshotBytes, pdfBytes); |
|
} |
|
} |
Update program to sent the screenshot and the PDF to telegram bot. Also fixed clicking this "Can use AMKA" selection box that was added recently.