Ежедневник IT-ка
133 subscribers
22 photos
4 videos
1 file
43 links
Программируем на практике!!
По вопросам по поводу проектов: @vladimir_dzen
Download Telegram
Forwarded from vladimir
Сегодня продолжю работать с ZennoPoster и Telegram, но уже в видео формате.

Основные шаги.
1.
Создание проекта.
2. Создание переменных.
3. Отправка сообщения в ТГ, 2-мя способами.

#ZennoPoster, #Telegram
Media is too big
VIEW IN TELEGRAM
Отправление фото и видео в Telegram используя ZennoPoster и библиотеку "Telegram.Bot"

#ZennoPoster, #Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
Продолжаем работу в программе  ZennoPoster, но на этот раз рассматриваю пример работы с Датами.
// Получаем время из переменной с указанием часовго пояса: 15.02.2022 12:00 +00:00
string capDateAndTimeRunRegistrationInSeil = project.Variables["capDateAndTimeRunRegistrationInSeil"].Value;

/* 1. Вариат с использованием struct DateTimeOffset .*/

// Парсим и сохраняем значение времени в struct DateTimeOffset.
var dtOffset_forSeil = DateTimeOffset.Parse(capDateAndTimeRunRegistrationInSeil);

// Преобразуем struct DateTimeOffset в struct DateTime(для дальнейшей работы).
var time_forSeil_DtOff = dtOffset_forSeil.DateTime;

// Выводим сообщение в лог.
project.SendToLog("ВРЕМЯ РЕГИСТРАЦИИ С ПОМОЩЬЮ DateTimeOffset: " + time_forSeil_DtOff.ToString("dd.MM.yyyy HH:mm:ss"), ZennoLab.InterfacesLibrary.Enums.Log.LogType.Info, true, ZennoLab.InterfacesLibrary.Enums.Log.LogColor.Yellow);


/* 2. Вариат без использования struct DateTimeOffset .*/

// Конвертируем в struct DateTime.
var time_forSeil_Dt = Convert.ToDateTime(capDateAndTimeRunRegistrationInSeil);

// Выводим сообщение в лог.
project.SendToLog("ВРЕМЯ РЕГИСТРАЦИИ С ПОМОЩЬЮ БЕЗ DateTimeOffset: " + time_forSeil_Dt.ToString("dd.MM.yyyy HH:mm:ss"), ZennoLab.InterfacesLibrary.Enums.Log.LogType.Info, true, ZennoLab.InterfacesLibrary.Enums.Log.LogColor.Yellow);


/* 3. Получение кол-во времени до события исходя из текущего согласно нашего часового пояса и времени начало самого события.*/

// Получение текущего времени согласно нашего часового пояса.
DateTime dtNow = DateTime.Now;

// Выводим сообщение в лог.
project.SendToLog("ТЕКУЩЕЕ ВРЕМЯ СОГЛАСНО НАШЕГО ЧАСОВОГО ПОЯСА: " + dtNow.ToString("dd.MM.yyyy HH:mm:ss"), ZennoLab.InterfacesLibrary.Enums.Log.LogType.Info, true, ZennoLab.InterfacesLibrary.Enums.Log.LogColor.Green);

// Преобразование текущего времени согласно нашего часового пояса в UTC.
var utcTime_forNow = dtNow.ToUniversalTime();

// Выводим сообщение в лог.
project.SendToLog("ТЕКУЩЕЕ ВРЕМЯ СОГЛАСНО UTC: " + utcTime_forNow.ToString("dd.MM.yyyy HH:mm:ss"), ZennoLab.InterfacesLibrary.Enums.Log.LogType.Info, true, ZennoLab.InterfacesLibrary.Enums.Log.LogColor.Green);

// Подсчёт кол-во времени до события.
TimeSpan diff = time_forSeil_DtOff.Subtract(utcTime_forNow);

// Выводим сообщение в лог.
project.SendToLog("ОСТАЛОСЬ ВРЕМЕНИ ДО РЕГИСТРАЦИИ СОГЛАСНО UTC(ЗАДАННОГО ВРЕМЕНИ) И НАШЕГО ВРЕМЕНИ(СКОНВЕРТИРОВАННОЕ В UTC): " + diff.Days.ToString("0") + " дн. " + diff.Hours.ToString("0") + " час. " + diff.Minutes.ToString("0") + " мин.", ZennoLab.InterfacesLibrary.Enums.Log.LogType.Info, true, ZennoLab.InterfacesLibrary.Enums.Log.LogColor.Orange);


 #ZennoPoster, #DateTime
Рассматриваю интересные моменты для получения информации используя метод из API Zennoposter: GetChildren.

1. Кол-во блоков с которых необходимо получить информацию из списка.

HtmlElementCollection entries = instance.ActiveTab.FindElementsByXPath("//div[contains(@class,'postlist') and contains(@id,'postsList')]/div");
int countBlocks = entries.Count;

2. Получение блоков в которых содержаться две необходимые части(текст и фото).

HtmlElement entry = instance.ActiveTab.FindElementByXPath("//div[contains(@class,'postlist') and contains(@id,'postsList')]/div", numRow);

numRow
- номер блока для парсинга.

HtmlElementCollection entries_m = entry.GetChildren(false);

Рекомендую посмотреть на этот метод:

GetChildren(false);

Позволяет получить элементы(детей) от главного элемента(родителя). С ним можно "творить" настоящие чудеса т.к. идёт упрощение кода и нет необходимости писать доп.-ые xpath запросы, чтобы обратиться к нужному элементу.

for (p = 0; p < entries_m.Count; p++)
{
HtmlElementCollection entries = entries_m.Elements[p].GetChildren(false);
for (s = 0; s < entries.Count; s++)
{
HtmlElementCollection entries_ = entries.Elements[s].GetChildren(false);
for (m = 0; m < entries_.Count; m++)
{
if (string.IsNullOrEmpty(postTitle))
{
postTitle = entries_.Elements[m].InnerHtml;
project.SendInfoToLog(postTitle);
break;
}
}
}
}

entries_m.Count
- полученное кол-во блоков, которое равно 2(т.е. текстовая и фото).

HtmlElementCollection entries = entries_m.Elements[p].GetChildren(false);

entries_m.Elements[p].GetChildren(false)
- здесь обращаемся к нужному элементу согласно индекса(т.е. 0), из которого также получаем "детей" элемента.

Итог: Метод GetChildren очень мощный метод, который даёт возможность обращаться к нижестоящим элементам без Xpath запросов.

#ZennoPoster, #Xpath
​​Затрону тему с LINQ запросами и не только:

   static void Main(string[] args)
    {
      Console.ForegroundColor = ConsoleColor.Red;
      Console.WriteLine("LINQ");
      // Создание списка с произвольными числами.
      List<int> numbers = new List<int> { 1, 5, 10, 12, -1, -300, 500 };
      Console.WriteLine($"Min число: {numbers.Min()}");
      Console.WriteLine($"Max число: {numbers.Max()}");
      Console.WriteLine($"Кол-во чисел в списке: {numbers.Count()}");
      Console.WriteLine($"Кол-во чисел в списке больше 0: {numbers.Count(x => x > 0)}");
      Console.WriteLine($"Сумма отрицательных чисел:{numbers.Where(x => x < 0).Sum()}");

      Console.ReadLine();

      Console.ForegroundColor = ConsoleColor.Yellow;
      // Генерация чётных чисел.
      Console.WriteLine("Генерация чётных чисел");
      var result = Enumerable.Range(-4, 10).Where(x => x % 2 == 0);

      foreach (var item in result)
      {
        Console.Write(item + "\t");
      }

      Console.ForegroundColor = ConsoleColor.Green;
      // Повторение объекта.
      Console.WriteLine(" ");
      Console.WriteLine(" ");
      Console.WriteLine("Повторение объектов");
      var repeat = Enumerable.Repeat("Привет мир!", 5);

      foreach (var item in repeat)
      {
        Console.WriteLine(item);
      }
      Console.ReadLine();
    }
  }

#LINQ , #CSharp
Столкнулся с задачей для сервиса imgbb.com (загрузка фото), точнее с его API. Вроде всё элементарно, но оказалось чуть сложнее, чем на первый взгляд.

Выделяю 3 ключевых момента, на которые необходимо сделать акцент.

foreach (string pathFile in project.Lists["pathToFoto"])
{
if (!string.IsNullOrEmpty(pathFile.Trim()))
{
string url = $"https://api.imgbb.com/1/upload?key={project.Variables["apiKey"].Value}";
string base64String = null;

1.Обязательно конвертировать фото в base64
using (Image image = Image.FromFile(pathFile))
{
using (MemoryStream m = new MemoryStream())
{
image.Save(m, image.RawFormat);
byte[] imageBytes = m.ToArray();
base64String = Convert.ToBase64String(imageBytes);
}
}
HttpClient client = new HttpClient();

2.Обязательно создать экземпляр класса StringContent
StringContent fotoContent = new StringContent(base64String, Encoding.UTF8);

3.Обязательно загружать фото используя экземпляр класса MultipartFormDataContent
var content = new MultipartFormDataContent();
content.Add(fotoContent, "image");
var result = client.PostAsync(url, content);
int code = result.Result.StatusCode.GetHashCode();
Thread.Sleep(1000);
if(result.Result.StatusCode.GetHashCode() != 200) throw new Exception("Problem WITH LOAD FOTO");
string jsonResult = result.Result.Content.ReadAsStringAsync().Result;
}
}

Вроде всего 3 акцента, но о них нигде и ничего не пишется на их странице, особенно о Multipart.

#API, #POST, #GET, #CSharp
​​Немного предыстории.
Заказчик хотел получать сигналы от биржи в телеграмм используя Emoji.
На первый взгляд, всё просто, если вы знаете как...., но тут явного решения не было, поэтому пришлось напрячься, чтобы найти его.

1. Переходим на сайт с emoji (пример: unicode-table.com)

2. Копируем emoji в Юникоде.

3. Пишем код:

    private static ITelegramBotClient _botClient;

    static void Main(string[] args)
    {

// Читаем данные для нашего бота с ранее подготовленного .json
 BotData botData = GetUserCredential<BotData>();

 // Создаём экземпляр класса TelegramBotClient используя ITelegramBotClient
 _botClient = new TelegramBotClient(botData.Token);

   // Получаем чат ID.
 string chatID = botData.Chat;

  // Эмоджи в Юникоде.
 string emoji = "U+1F600";

  // Парсим в INT эмоджи, но уже "1F600"(т.е. без 1-х 2-х знаков), через HexNumber(шестнадцатеричное число)
 int _emoji = int.Parse(emoji.Substring(2), NumberStyles.HexNumber);

  // Отсылаем сообщение.
 _botClient.SendTextMessageAsync(chatID, "Как прекрасен этот мир! " + char.ConvertFromUtf32(_emoji)).Wait();
}

// Метод получение данных из .json
    private static T GetUserCredential<T>()
    {
      using (var fileStream = new FileStream("TGbot.json", FileMode.Open, FileAccess.Read))
      {
        string contents;
        using (var sr = new StreamReader(fileStream))
        {
          contents = sr.ReadToEnd();
        }
        return JsonConvert.DeserializeObject<T>(contents);
      }
    }

На этом всё. Код работает.

#Telegram, #CSharp
SENDEREMOJITELEGRAM.zip
6.7 MB
Код для примера! Без вирусов :).
Публикация приложения одна из простых и желанных вещей в программирование. Поэтому покажу как происходит это у меня:
1. Выбираем, то проект который будем публиковать.
2. Открываем в терминале.
3. Запускаем команду в терминале PowerShell:
dotnet publish -c Release --self-contained -p:PublishSingleFile=true
4. В конф. проекта добавляем эту строку:
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
Она необходима для того, чтобы программа запускалась на всех операц. системах Windows.
Подробнее можно посмотреть по ссылке.

 #CSharp, #WPF
Сегодня коснусь SQL запроса.
Очень часто необходимо взять данные с двух табл., которые имеют один(минимум) общий столбец с одинаковыми значениями(это условие Обязательно).

Цель: 
Сделать запрос, который выберет название товаров и артикулов из 2-х разных таблиц согласно названия города и категории , в которых совпадает sku(id) товаров.
1. Таблицы для анализа, для которых и создаётся SQL запрос.
2. Содержание 1 табл.: 'olx_sales_week_by_wh'