• Как пустить часть трафика через VPN?

    Vindicar
    @Vindicar
    RTFM!
    Есть два подхода. В обоих случаях тебе нужен список заблокированных IP, его можно взять на антизапрете, например.
    Дальше вопрос, как пускать трафик.
    1. На хабре был материал про динамическую подгрузку маршрутов через BGP. Плюс - работает с любыми протоколами, и не требует дополнительной настройки со стороны проксируемого ПО. Минусы - ощутимо сложнее в понимании, на мой взгляд, да и с кроссплатформенностью могут быть проблемы. В статье приведена реализация на роутере Mikrotik.
    2. Использовать файл proxy.pac. Его можно сгенерировать скриптом типа такого:
    #!/bin/bash
    #!/bin/bash
    DNS_SERVER=8.8.8.8
    BLACKLIST_URL="http://antizapret.prostovpn.org/iplist.txt"
    #куда класть файл proxy.pac
    PACDIR=/var/www/html
    TMPLIST=/tmp/iplist.txt
    #домены, которые нужно пускать через прокси независимо от содержимого iplist.txt
    DOMAINS=(\
    rutracker.org \
    facebook.com \
    facebook.net \
    fbcdn.net \
    twitter.com \
    twitter.co \
    t.co \
    twimg.com \
    twitpic.com \
    periscope.tv \
    pscp.tv \
    )
    #качаем чёрный список
    wget -q --tries=10 -O "$TMPLIST" "$BLACKLIST_URL"
    # вытаскиваем IP наших прописанных доменов
    declare -a EXTRAIPS=()
    for domain in "${DOMAINS[@]}"
    do
            dig A "$domain" +short @$DNS_SERVER | grep -v '\.$' >>"$TMPLIST"
    done
    #в чёрном списке есть отдельные IP и есть подсети
    #также чёрный список очень длинный, поэтому кодируем его более компактно.
    IPLIST=`grep -Ex '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' "$TMPLIST" | awk '/^[0-9]+/ {split($1,b,/\./); printf("0x%02x%02x%02x%02x,", b[1],b[2],b[3],b[4]);}'`
    SUBNETLIST=`awk '/[0-9.]+\.[0-9]+\.[0-9]+\.[0-9]+\/[0-9]+/ {split($1,p,/\//); printf("[\"%s\", %s], ", p[1], p[2]);}' <"$TMPLIST"`
    #генерируем proxy.pac по шаблону
    #он проверяет домен на вхождение в фиксированные домены, а потом IP по списку.
    function templatePAC {
            NAME=$1
            shift
            DMNLIST=("$@")
            cat >"$PACDIR/$NAME" <<EOF
    function FindProxyForURL(url, host) {
      var domainblacklist = [
    EOF
            for d in "${DMNLIST[@]}"
            do
                    echo "  '$d'," >>"$PACDIR/$NAME"
            done
            cat >>"$PACDIR/$NAME" <<EOF
      ];
      var ipblacklist = [ $IPLIST ];
      var subnetblacklist = [ $SUBNETLIST ];
    
      function endsWith(str, suffix) {
        return str.indexOf(suffix, str.length - suffix.length) !== -1;
      }
      function numberToMask(n) {
        var m=[0,128,192,224,240,248,252,254,255];
        var r=[];
        for (var i=0; i<4; i++) {
          var p = (n > 8) ? 8 : n;
          r[i] = m[p];
          n -= p;
        }
        return r.join(".");
      }
      function maskMatch(ip, mask) {
        var m = numberToMask(mask[1]);
        return isInNet(ip, mask[0], m);
      }
    
      var blocked = false;
      for (var i=0; !blocked && (i<domainblacklist.length); i++)
        blocked = blocked || ((host == domainblacklist[i]) || endsWith(host, '.'+domainblacklist[i]));
      if (!blocked) {
        var ip = dnsResolve(host);
        for (var i=0; !blocked && (i<subnetblacklist.length); i++)
          blocked = blocked || maskMatch(ip, subnetblacklist[i]);
        blocked = blocked || (ipblacklist.indexOf(convert_addr(ip)) != -1);
      }
      if (blocked)
        return "PROXY ТУТ_ТВОЙ_ПРОКСИ:ПОРТ";
      else
        return "DIRECT";
    }
    EOF
    }
    # генерируем файл
    templatePAC proxy.pac "${DOMAINS[@]}"
    
    rm -f "$TMPLIST"

    Тогда можно отдавать этот proxy.pac любым веб-сервером (но лучше внутри VPN - если VPN не работает, то смысл в файле?), и настроить браузер на его использование.
    Минусы: работает только с браузерами, требует наличия вебсервера и полноценного прокси-сервера внутри VPN-сети (т.е. просто арендованный VPN не подойдёт, нужен VPS). Но мне показалось это проще в понимании, чем возня с BGP, да и требуется только наличие современного браузера и VPN клиента, без привязки к роутеру. Можно хоть на ноуте настроить, как я сделал.
    Ответ написан
    Комментировать
  • Как сделать чтобы при вводе команды писались все участники роли. discord.py?

    Vindicar
    @Vindicar
    RTFM!
    Ты документацию читал? Там нужная информация есть.
    А что касается задания роли - указываешь тип параметра команды discord.Role, и 90% дела сделано.
    Ответ написан
  • Нужно извлечь из этого res.Как это реализовать?

    Vindicar
    @Vindicar
    RTFM!
    В документации это опущено, но если взглянуть в исходник, то у экземпляров класса Stream есть свойство resolution.
    Ответ написан
  • Как сделать сообщение бота ответом на команду?

    Vindicar
    @Vindicar
    RTFM!
    Может и слепой.
    Берешь свойство message у контекста, получаешь объект сообщения. У него есть метод reply().
    Ответ написан
    Комментировать
  • Как получить данные из postgresql в python?

    Vindicar
    @Vindicar
    RTFM!
    Ну во-первых, да, ваш цикл не имеет смысла именно по указанной причине.
    Последовательность должна быть сначала execute(), потом цикл for.
    Во-вторых...
    "SELECT * from rawdata where deveui = '" + str(dev[0]) + "'

    Не делайте так. Освойте подстановку параметров.
    Ответ написан
    2 комментария
  • Каким образом изменяется id объектов внутри изменяемых типов данных?

    Vindicar
    @Vindicar
    RTFM!
    Первый сценарий: элемент списка хранил ссылку на одно число (экземпляр типа int), потом стал хранить ссылку на другое. Сам список при этом располагается по тому же адресу, что и раньше.
    Второй сценарий: то же самое, но с элементом словаря.
    Ответ написан
    Комментировать
  • Как перенести код с консольного питона на aiogram?

    Vindicar
    @Vindicar
    RTFM!
    1. Поучи, как работают асинхронная программа, и почему цикл вида
    while True:
        schedule.run_pending()

    парализует её работу.
    2. Портируй код с использованием асинхронного aioschedule.
    Ответ написан
    8 комментариев
  • Как ускорить функцию на пайтоне?

    Vindicar
    @Vindicar
    RTFM!
    while Adj[x,rand] != 1:
        rand = np.random.randint(0,nodes_length)


    Ну проблема вот в этом, ты скакать по массиву так можешь очень долго. Почему бы не составить список индексов r для который Adj[x, r] != r, а потом сделать random.choice() из него?
    Ну и далее, numpy массивы не предназначены для изменения своей длины, вот это твое chrom = np.append(chrom,rand) чётко показывает, что тебе нужен список. Если очень надо, преврати его в массив перед возвратом.
    Ответ написан
    Комментировать
  • Как создать алгоритм синтаксического анализа списка токенов?

    Vindicar
    @Vindicar
    RTFM!
    Ну для начала, ты неправильно ставишь цель. После синтаксического разбора у тебя будет не список, а древовидная структура данных, а итоговый код будет результатом обхода этой структуры в глубину.
    Так что читай про восходящий алгоритм. Идея у него простая. У тебя должен быть набор правил твоей грамматики, например:
    ЦИКЛ_WHILE = 'while' '(' ВЫРАЖЕНИЕ ')' ОПЕРАТОР
    Заглавными я записал нетерминальные символы - что-то, что раскрывается далее в последовательность токенов.
    Остальное - терминальные символы, т.е. токены.
    Итак, у тебя есть цепочка символов - терминальных или нетерминальных. Нетерминальные хранят в себе кусочек дерева программы, терминальные хранят в себе один токен.
    1. Перебираешь правила, ищешь правило, соответствующее текущей позиции в цепочке. Для начала цепочки это будет правило "программа в целом".
    2. Строишь узел дерева, соответствующий найденному правилу.
    3. Помещаешь в этот узел терминальные символы, входящие в правило. В примере выше это будут 'while' и '('. Сдвигаешь позицию в цепочке.
    4. Если в правиле дальше идёт нетерминальный символ, рекурсивно обрабатываешь цепочку по правилу для этого символа, начиная с текущей позиции. Когда обработка закончится, у тебя позиция в цепочке сместится на конец последовательности символов для этого нетерминала, и можно будет продолжить для следующего символа в правиле.
    5. Когда правило закончилось - возвращаешь полученное мини-дерево, чтобы вышележащий код его встроил в свой узел дерева.
    6. Если есть альтернативы, сохраняешь текущую позицию в цепочке и пробуешь альтернативы по очереди. Если альтернатива не сработала (правило тут не подходит), то возвращаешься к сохранённой позиции и пробуешь уже с другой альтернативой.
    7. Если в какой-то момент ни одно правило не подошло, или если мы получили неожиданный терминал, есть синтаксическая ошибка в коде.

    Это сравнительно легко реализуется через косвенную рекурсию. Т.е. у тебя в парсере будет много методов nfrjuj вида (псевдокод!):
    def parse_while_node(tokens: List[Token], pos: int) -> TreeNode, int:
        """Принимает список токенов и позицию в нём, возвращает мини-дерево и новую позицию в списке."""
        node = WhileNode() # узел дерева разбора, соответствующий циклу while
        assert tokens[pos].type == 'while'  # проверяем фиксированный токен, выкидываешь исключение если это не он
        pos += 1
        assert tokens[pos].type == '('
        pos += 1
        # обращаемся к другому правилу для разбора нетерминального символа ВЫРАЖЕНИЕ
        # сохраняем мини-дерево для выражения условия и обновляем позицию
        node.condition, pos = parse_expression_node(tokens, pos)
        assert tokens[pos].type == ')'
        pos += 1
        # аналогично парсим нетерминал ОПЕРАТОР
        node.body, pos = parse_operator_node(tokens, pos)
        # возвращаем вызвавшему нас коду наше минидерево с узлом while на вершине,
        # а также позицию где мы остановились
        return node, pos

    А для реализации правила вида
    ОПЕРАТОР = ПРИСВАИВАНИЕ | ВЕТВЛЕНИЕ | ЦИКЛ_WHILE
    можно будет сделать так:
    def parse_operator_node(tokens: List[Token], pos: int) -> TreeNode, int:
        variants = [parse_assignment_node, parse_if_node, parse_while_node]
        for variant in variants:
            try: # пробуем вариант из ветвления
                node, pos = variant(tokens, pos)
            except:
                pass # вариант не подошёл - пробуем другой
            else: # вариант подошёл
                return node, pos
        else: # ни один вариант не подошёл
            raise Exception()
    Ответ написан
    1 комментарий
  • Откуда цифра в конце вывода stdout?

    Vindicar
    @Vindicar
    RTFM!
    write() возвращает количество записанных символов/байт.
    В консоли питона, если введённое выражение вычислилось не в None, то полученный результат выводится.
    У тебя сначала выводится строка от вызова write(), а потом в консоли выводится возвращённое write() значение. Так как ты не вывел символ перевода строки, она сливается с выведенной строкой.
    Запиши код в файл и выполни его, и увидишь что цифра не появляется - потому что это поведение есть только интерактивной консоли.
    Ответ написан
    Комментировать
  • Что делать если при попытке выдачи роли через бота дискорд появляется ошибка?

    Vindicar
    @Vindicar
    RTFM!
    Что делать? Открыть глаза, прочитать ошибку, понять ошибку. Мыслить логически.
    await req(guild_id, user_id, role.id, reason=reason)
    AttributeError: 'NoneType' object has no attribute 'id'

    "У None нет атрибута id". Т.е. вместо некоего объекта с атрибутом id передали None.
    Смотрим на строку кода и ищем обращение к атрибуту id. Это role.id, т.е. вместо параметра роли в метод передали None.
    Смотрим выше, пока не найдём ссылку на строку не из discord.py.
    await author.add_roles(role)
    Т.е. твоя переменная role имеет значение None.
    Ищем эту строку в коде, потом смотрим выше откуда взялось role.
    role = guild.get_role(940997266100064316)
    Смотрим документацию на get_role().
    Returns the role or None if not found.

    Т.е. role может содержать None, если переданный id не соответствует роли в этом сервере.
    Вот тебе и ответ. Перепроверь id, который ты передаёшь в get_role().
    Ответ написан
    Комментировать
  • Рисовать примитивы поверх рабочего стола в windows?

    Vindicar
    @Vindicar
    RTFM!
    Через WinAPI найти окно рабочего стола. Вроде как их может быть два, одно с иконками, одно с фоном. Гугл подскажет, какой класс окна там нужен. Начать можно с FindWindow(), потом, если надо, пройтись по иерархии окон через EnumChildWindows().
    А дальше практичнее всего разместить своё окно как дочернее от найденного. Тогда можно будет рисовать на своём окне что захочешь. SetParent() в помощь. Само окно по идее можно создать и через GUI фреймворк, а не через API, но тогда придётся модифицировать стили окна.
    Дергать WinAPI из-под Питона неудобно, но модуль ctypes поможет.
    Ответ написан
  • Как исправить ошибку с выдачей роли в дискорд боте пайтон?

    Vindicar
    @Vindicar
    RTFM!
    что еще за self.get_guild(), и почему нельзя взять guild из ctx?
    Сейчас discord.py ожидает, что self будет передана как параметр при вызвое команды пользователем.
    Ответ написан
    Комментировать
  • Как боту дискорд подсчитать слова в сообщении Python?

    Vindicar
    @Vindicar
    RTFM!
    Почитай про параметры команд в discord.py, она уже реализует и разбиение на слова, и отключение этой механики.
    Если хочешь разбивать на слова сам, то строковый метод split() тебе в помощь. Получишь список слов.
    Ну а количество... как длину списка найти, знаешь, я надеюсь?
    Ответ написан
    Комментировать
  • Как дать понять питону, что если строка является 'null', то ее пробивать нельзя?

    Vindicar
    @Vindicar
    RTFM!
    До чего изобретателен может быть человек, не понимающий что он делает!
    Ключевое слово: кортеж.
    await cur.execute(sql, (id))
    (id) - это то же самое, что id.
    А вот (id,) - это уже кортеж из одного элемента.
    execute() как раз и ожидает вторым параметром кортеж, или иную коллекцию, где один элемент - это одно подставляемое значение.

    Этот метод необходим для удаления скобок, которые ставит pymysql при обычном fetchone

    "Скобки", как ты выразился - это потому что fetchone() возвращает кортеж, по одному элементу на значение в строке (ну или None если очередной строки нет). Т.е. для каждого пункта между SELECT и FROM будет один элемент в кортеже, в том же порядке. Ты запрашиваешь только teleid, поэтому получаешь кортеж из одного элемента.
    Получить этот элемент можно, обратившись по индексу 0.
    row = await cur.fetchone()
    if row is not None: #есть хоть одна строка?
        teleid = row[0]
        # дальше делаешь что хочешь с teleid
    else: # нет такой строки
        print('Беда')

    Перед тем как писать ботов, освой азы языка, а? Структуры данных в частности.
    Ответ написан
    Комментировать
  • Почему переводит на другую строку?

    Vindicar
    @Vindicar
    RTFM!
    Проверить, что name не содержит символ перевода строки.
    Ответ написан
  • Aiogram: Как сохранить введенные данные пользователя?

    Vindicar
    @Vindicar
    RTFM!
    Ну алгоритм всегда один и тот же.
    Тебе нужно для каждого пользователя бота хранить шаг, на котором он находится, и все введённые ранее данные.
    Тогда по получению текста от пользователя ищем его ID в хранилище, смотрим, на каком он шаге, и пытаемся интерпретировать полученный текст в зависимости от этого.

    А вот где хранить данные - вопрос реализации. Можно сделать словарь вида "ID пользователя - набор данных", можно сделать БД. Принцип это не меняет.
    Ответ написан
    Комментировать
  • Где перечислено это, что используется в хендлере?

    Vindicar
    @Vindicar
    RTFM!
    1. По приведённой ссылке описывается API запросов Телеграма, а не API для питон кода. Используй одну из библиотек, вроде pyTelegramBotAPI или aiogram. У первого доки получше, вроде.
    2. Если используешь aiogram, то в асинхронность вникать придётся. pyTelegramBotAPI использует синхронный код. В чём-то это будет проще, в чём-то - сложнее.
    Ответ написан
  • Несколько вопросов по линуксу от новичка?

    Vindicar
    @Vindicar
    RTFM!
    По поводу логов - logrotate настрой, он наверняка уже установлен, только разобраться как натравить его на лог твоей программы. Но опять же, некоторые проги с ума сходят от такого. Нужно пробовать.
    Ответ написан
    Комментировать
  • Как вычесть результат функции из результата другой функции?

    Vindicar
    @Vindicar
    RTFM!
    Ну во-первых тебе стоит поучить питон на более простых вещах, а потом уже браться за GUI.
    Во-вторых, пусть твои функции помещают результат своего расчёта в глобальную переменную, каждая в свою. Сейчас они записывают его текстом в интерфейс, а как число не сохраняют нигде.
    Ответ написан
    Комментировать