• Можно ли писать бэк на C#, а фронт на React и есть ли в этом смысл?

    MaxLevs
    @MaxLevs
    Такой стек многие используют.
    Через, например, Nginx настраивается маршрутизация запросов: по каким путям отдавать фронт, а по каким - дергать backend. А дальше - дело техники: чаще всего используют http-rest, и он непривередлив. Имплементируете rest-api через ASP.Net Core, дёргаете его с фронта, маршрутизация решает вопросы доставки пакетов.

    P.S. Лучше пару тестовых приложений написать ч разными вариациями имплементации. Так появится понимание из чего выбирать. А в интернетах уже написано, что устарело, а что - свежачок
    Ответ написан
    Комментировать
  • Как сконфигурировать Worker Service для логгирования запросов Entity Framework через NLog?

    MaxLevs
    @MaxLevs Автор вопроса
    Как верно заметил Василий Банников, для решения проблемы потребуется пакет NLog.Extensions.Logging.

    Для логирования скомпилированных запросов к базе используется метод UseLoggerFactory(ILoggerFactory). Фабрику можно создать вручную, и передаём в неё в качестве аргумента NLog.Extensions.Logging.NLogLoggerProvider для того, чтобы логирование подхватывалось NLog.

    LoggerFactory dbLoggerFactory = new LoggerFactory(new[] { new NLogLoggerProvider() });
    options.UseLoggerFactory(dbLoggerFactory);


    Стоит также отметить, что для того, чтобы NLog в этом случае использовал нужную конфигурацию (из файла NLog.conf), требуется ему на это указать в Program.cs.

    LogManager.LoadConfiguration("NLog.config");
    Ответ написан
    Комментировать
  • C#: Автоматическое переподключение UdpClient после рестарта сервера?

    MaxLevs
    @MaxLevs Автор вопроса
    Решил вопрос, отказавших от использования в качестве проверки работы сервера TCP-соединение. (Кто может подсказать, насколько такая замена вообще могла быть жизнеспособной?).

    Заменил код WaitForServerAlive() на следующий:
    Код здесь

    public async void WaitForServerAlive()
            {
                if(Debug)
                    Console.WriteLine($"[WARNING] [{ServerName}] Server is unavailable. Waiting for reconnection...");
                
                IsOnline = false;
                await Unwatch();
                
                _mcQuery.InitSocket();
                
                Timer waitTimer = null;
                waitTimer = new Timer(async obj => {
                    try
                    {
                        await _mcQuery.GetHandshake();
                        
                        IsOnline = true;
                        Watch();
                        lock (_retryCounterLock)
                        {
                            RetryCounter = 0;
                        }
                        
                        waitTimer.Dispose();
                    }
                    catch (SocketException)
                    {
                        if(Debug)
                            Console.WriteLine($"[WARNING] [{ServerName}] [WaitForServerAlive] Server doesn't response. Try to reconnect: {RetryCounter}");
                        
                        lock (_retryCounterLock)
                        {
                            RetryCounter++;
                            if (RetryCounter >= RetryMaxCount)
                            {
                                if(Debug)
                                    Console.WriteLine($"[WARNING] [{ServerName}] [WaitForServerAlive] Recreate socket");
                                
                                RetryCounter = 0;
                                _mcQuery.InitSocket();
                            }
                        }
                    }
                }, null, 500, 5000);
            }



    Здесь каждые 5 секунд мы стучим на сервер, запрашивая новый токен. На получение токена даётся 5 попыток, после чего сокет пересоздаётся, чтобы избежать ситуаций, когда сервер поднят, a данные всё равно через сокет идти не хотят. Любой удачно переданный пакет сбрасывает счетчик. Собственно сам WaitForServerAlive() вызывается если 5 раз подряд возникла неудачная попытка получить данные с сервера, это переводит приложение в режим ожидания восстановления соединения.

    Вышестоящий протокол подразумевает получение токена через хэндшейк-запрос, который возвращает результат всегда при корректно составленном запросе. Если сервер поднят, то мы получим токен. Обычно его достаточно получать раз в 30 секунд, чтобы запросы проходили. Для того, чтобы быстрее узнать о том, что сервер снова поднят, я отменяю обновление токена и вызываю похожий код раз в 5 секунд, до тех пор, пока не получу данные с сервера.
    После этого можно считать что сервер снова жив и возвращаться к штатной работе.
    Ответ написан
    Комментировать
  • Как буфферизировать ajax-запросы в async-функциях?

    MaxLevs
    @MaxLevs Автор вопроса
    Всё, сделал. (НО не всё понял)
    Можно было сразу догадаться
    Как я и думал, проблема в том, что я слишком сильно начал зарываться в замыкания. Из-за длинных цепочек замыканий стало сложно ориентироваться в коде и сказать, как правильно применить async/await (как поведёт себя async/await). Видимо, я всё ещё не до конца осознал механизмы работы async/await, помнил, но не осознал, запамятовал, что async возвращает промис ещё до return (Помнил, но не "дотягивался", банальная мысль).
    Как только я осознал, что воюю с async не в те ворота, то всё сразу встало на свои места. Можно было бы потратить пару дней на реализацию подхода с цепочками рекурсии, чтобы вдолбить механизмы его работы себе в голову, но решил не забивать гвозди микроскопом. Раз уж я "дотянулся" до верного механизма async и цепочка действий легла на это поле, то можно просто сделать.


    В моём случае, не нужно ждать, пока появится первый запрос на формирование блока комментариев страницы, поэтому достаточно сделать запрос общей формы (первые 2 шага) заранее, запихнуть это в промис и доставать из замыкания уже при появлении запросов.
    const getCommentsInputBlock = (function assableCommBlockGenerator() {
            // Запрос формы
            function requestForm () {
                const mangaId = $(".reader-controls").html().match(/mangaId=(\d+)/)[1];
                const chapterId = $(".reader-controls").html().match(/chapterId=(\d+)/)[1];
                return $.ajax({
                    type:'POST',
                    data:{'mangaId': mangaId,'chapterId': chapterId},
                    url:'/internal/modal/addTwittInline',
                });
            }
    
            // Косметические правки поведения
            async function makeUpForm () {
                const commentFormPromise = requestForm();
    
                const commInputBlock = $("<div>").html(await commentFormPromise);
                const frm = commInputBlock.find("form");
                frm.attr("onsubmit", frm.attr("onsubmit").replace(".val(rm_h.cur)", ""));
    
                return commInputBlock;
            }
    
            // Запрашиваем форму заранее - все равно понадобится (промис остаётся в замыкании)
            const commInputBlockPromise = makeUpForm();
    
            // Замыкание для генерации блока формы
            return async function adaptateFormToPage (key) {
                let commInputBlock = await commInputBlockPromise;
                const newCommentBlock = commInputBlock.clone();
                newCommentBlock.find("#twittPageNumHidden").attr({value: key});
                return newCommentBlock.attr({id: `com_input_${key}`});
            };
        })();


    Из-за этого маленького нюанса всё сводится к одному единственному замыканию. Проверка единственности запроса к базе и не нужна вовсе.

    Однако я всё ещё не понимаю, как действовать, если мы не можем предугадать запрос заранее, но мы должны обеспечить асинхронность, единственность запроса и гарантировать доступ к полученным данным во всех требуемых местах при актуализации?
    Очевидно будет, что выглядеть это должно так, я всё ещё не уверен во всём:
    const reqData = await (async function assableRequestor() {
        const dataPromises = {};
        return async function reqData(params) {
            const prmsStr = `${params}`;
            if(!dataPromises.includes(prmsStr)) {
                const dataPromise = $.ajax(params);
                dataPromises[prmsStr] = dataPromise;
                return await dataPromise;
            }
            return await datas[prmsStr];
        };
    })();
    
    async function doSomething(params) {
        let data = await reqData(params);
        /*Модификация данных*/
        return data;
    }
    
    async function doItCool(params) {
        let data = await reqData(params);
        /*Другая Модификация данных*/
        return data;
    }
    
    setTimeout(()=>{doSomething(params1)}, 5000);
    setTimeout(()=>{doItCool(params1)}, 3000);
    Ответ написан
    Комментировать
  • Как хранить и изменять данные пользователей discord js?

    MaxLevs
    @MaxLevs
    Вопрос о хранении данных на компьютере - это вопрос не по Discord, а по api Node.js или его библиотекам.
    Данные тебе нужно хранить в постоянной памяти.
    Для этого ты можешь например, сохранять объекты javascript в json и записывать его как файл в какой-нибудь папке (fs). Или, например, использовать для этого базы данных.

    Получение информации о пользователях в discord - тоже отдельный вопрос.
    В discord.js есть класс GuildMember. В нем вся информация об участнике конкретного сервера.

    Для отправки сообщения нужно знать, в какой чат ты его посылаешь.
    Ответ написан
    Комментировать
  • Вместо одной строки выводит множество похожих строк из списка?

    MaxLevs
    @MaxLevs
    Это print(filecontents[1])
    замени на это print(line)
    Ответ написан
    Комментировать
  • Python, почему функция возвращает None?

    MaxLevs
    @MaxLevs
    Функция wrap() не содержит return, поэтому возвращает None.
    Ответ написан
  • Как выполнять функцию python каждый день в определенное время?

    MaxLevs
    @MaxLevs
    Используя стандартный модуль threading.
    Пример
    from time import sleep, time
    from functools import wraps
    
    
    def mult_threading(func):
         """Декоратор для запуска функции в отдельном потоке"""
         @wraps(func) 
         def wrapper(*args_, **kwargs_): 
             import threading 
             func_thread = threading.Thread(target=func,  
                                            args=tuple(args_),  
                                            kwargs=kwargs_) 
             func_thread.start()
             return func_thread 
         return wrapper
    
    
    #  Сразу делаем функцию многопоточной
    @mult_threading 
    def some_func(x, y, name="Petia", df=None, *args, **kwargs): 
         sleep(5) #  Тут мы чего-то доолго ждем / вычисляем / etc
         print("X = %s; Y = %s; Name=%s; df=%s" % (x, y, name, df)) 
         print("Another args:", args, kwargs)
    
    
    #  ==Проверяем работу==
    #  Стартуем нашу долгоиграющую функцию
    some_func(4, 7, df=11, 21, clone="SomeClone")
    
    #  Занимаемся очень важными делами
    for Z in range(25): 
        print(Z)
        sleep(0.2)


    Результат
    5c46b2b44f46b621492560.gif
    Ответ написан
    3 комментария
  • Как вывести игру, в которую играет пользователь?

    MaxLevs
    @MaxLevs
    Научитесь выражаться яснее.

    Для того, чтобы получить текст текущего статуса (также известного как "название игры") у посетителя сервера, можно использовать поле Member.game.
    • Выбираем нужный сервер из списка client.servers
    • Выбираем на этом сервере какого-нибудь посетителя из списка server.members
    • У выбранного пользователя смотрим поле member.game и получаем объект класса Game
    • Поле game.name содержит тот самый заветный текст


    Если же хотите изменить статус самого бота, то надо использовать метод Client.change_status(...).
    await client.change_status(game=Game(name="Я не умею в гугл"))
    Ответ написан
    Комментировать
  • Как спарсить данные с сайта, если сайт не даёт зайти с СНГ региона?

    MaxLevs
    @MaxLevs
    Для этого нужно использовать прокси-сервер.

    Включить его можно как на уровне ОС (но тогда все ваши соединения будут проходить через него),
    либо непосредственно из скрипта, используя инструменты той библиотеки, которой парсите.
    Примеры:
    Ответ написан
    2 комментария
  • Как реализовать ответ пользователю из текстового файла с шаблонами?

    MaxLevs
    @MaxLevs
    Самый простой вариант
    Назовём файл qa.txt
    1. Создать переменную db типа dict, ключом будет текст вопроса, а значением текст ответа
    2. Открыть файл qa.txt
    3. Читать файл построчно
    4. Каждую прочитанную строку разбивать через регулярные выражения (модуль re) на две части: вопрос и ответ
    5. Добавить очередную строку в словарь db

    Когда файл будет полностью переведён в словарь db, можно будет получать ответы так
    print(db["Как дела?"]) #хорошо

    P.S. Исправь ответ, оформив код.
    Ответ написан
  • Как получить вывод последней строки последнего файла в каталоге в Centos7?

    MaxLevs
    @MaxLevs
    Самый свежий файл ls -t | head -n1
    Последняя строка файла xxx.txt cat xxx.txt | tail -n1

    Всё вместе cat $(ls -t | head -n1) | tail -n1
    Ответ написан
    4 комментария
  • Как вызвать функцию из класса другого файла?

    MaxLevs
    @MaxLevs
    Это не функция, а метод класса nick.Example.
    Для вызова нужно:
    1. Создать объект класса nick.Example
      nick_ojb = nick.Example(<some_params_here>)
    2. Вызвать соответствующий метод у полученного объекта
      nick_ojb.proba()


    Подробнее: про модульность | про классы.
    Ответ написан
    2 комментария
  • Почему в переменную попадает следующий элемент?

    MaxLevs
    @MaxLevs
    for index, char in enumerate(string, 1):

    Нумерация массивов в Python начинается с 0.
    Ты задаешь начальное значение нумерации значений из массива явно, поэтому index всегда ссылается на следующий элемент строки.
    arr = ["a", "b", "c", "d"]
    enumerate(arr, 7) # {7:"a", 8:"b", 9:"c", 10:"d"}


    P.S. Код, действительно, не лаконичный. В комментах к вопросу sim3x кинул неплохой вариант.
    Ответ написан
    2 комментария
  • Как в Python избежать ошибки TabError?

    MaxLevs
    @MaxLevs
    TabError говорит о том, что в коде понамешаны индентации и из табов, и из пробелов.
    Определись, какой стиль отступов использовать и приведи код к однообразию. (Согласно PEP8 предпочтительней 4 пробела).

    Также проверь, чтобы индентации были верно соблюдены, так как это критично в Python.
    Ответ написан
    Комментировать
  • Как разбить текст по 3 слова слова?

    MaxLevs
    @MaxLevs
    text = "слово1 слово2 слово3 слово4 слово5 слово6 слово7 слово8 слово9"
    text = text.split()
    text = [' '.join(text[x:x+3]) for x in range(0, len(text), 3)]

    Разбивает по 3 слова. Если группа из 3 слов не может быть составлена - отбрасывается.
    Демонстрация
    5c4046d6a1e46864489023.png
    Ответ написан
    Комментировать
  • Как правильно использовать переменные в терминале?

    MaxLevs
    @MaxLevs
    В .bashrc
    mkcd() {
        mkdir $1
        cd $1
    }


    Затем в консоли можно будет писать так
    ~> mkcd foobar
    ~/foobar>


    Пример
    _48cdb181b0272f06432995574bb386df.gif?no
    Ответ написан
    5 комментариев
  • Как открыть файл с удалённого сервера?

    MaxLevs
    @MaxLevs
    Поставить на удалённой машине web-сервер (например, apache).
    Перейти по адресу 10.18.100.159/html/hdvideos/Zachetnij.prepod.3.201...

    Проверь, открыт ли 80 порт
    telnet 10.18.100.159 80
    Ответ написан
    Комментировать