Пользователь пока ничего не рассказал о себе

Достижения

Все достижения (14)

Наибольший вклад в теги

Все теги (189)

Лучшие ответы пользователя

Все ответы (1245)
  • Не могу понять в чем проблема?

    Vindicar
    @Vindicar
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]} :polegar_para_cima:**"""

    Вот это - трижды говнокод.
    1. Не засовывай в шаблонные строки ничего сложнее одной арфиметической операции - результат абсолютно нечитаем и неконтролируем (в чем ты убедился).
    Неправильно:
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]} :polegar_para_cima:**"""

    Правильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{score} :polegar_para_cima:**"""

    2. Никогда не формируй запросы через форматирование строк. Слишком легко словить ошибку, явную или неявную.
    Неправильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id))

    Правильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) )

    3. Всегда проверяй, что ты получаешь из базы! Нет гарантий, что запись с указанным id и впрямь существует.
    Неправильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) ).fetchone()[0]
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{score} :polegar_para_cima:**"""

    Правильно:
    score_row = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) ).fetchone()
    if score_row is not None:
        description = f"""У тебя , **{ctx.author}** вот столько балов!**{score_row[0]} :polegar_para_cima:**"""
    else:
        # что делать, если такого юзера еще нет в базе?
        cursor.execute("INSERT INTO users (id, cash) VALUES (?, 0)", (ctx.author.id,) ) # можно его добавить
        description = f"""У тебя , **{ctx.author}** пока нет ничего! Но скоро будет!"""

    4. БаЛЛов, блин.
    Ответ написан
    5 комментариев
  • Можно ли зделать свою команду в командной строке linux?

    Vindicar
    @Vindicar
    1. Добавь в начало файла шебанг, т.е. строку вида
    #!/usr/bin/env python
    Чтобы при запуске файла было понятно, чем его открывать
    2. Переименуй файл в add (без расширения) и сделай его исполняемым командой chmod +x add
    3. Либо помести файл в один из каталогов в переменной окружения PATH, либо добавь каталог, в котором файл лежит, в PATH.
    Загляни в скрытый файл .profile в твоём домашнем каталоге, он как раз этим занимается. Он может быть настроен так, чтобы автоматически добавлять в PATH каталог bin в твоем домашнем каталоге, тогда просто создай этот каталог и закинь файл туда.
    Ответ написан
    Комментировать
  • Как пустить часть трафика через VPN?

    Vindicar
    @Vindicar
    Есть два подхода. В обоих случаях тебе нужен список заблокированных 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 клиента, без привязки к роутеру. Можно хоть на ноуте настроить, как я сделал.
    Ответ написан
    Комментировать
  • Последовательность чтения кода браузером?

    Vindicar
    @Vindicar
    Percivald, ты не понимаешь.
    Тут три действия, а не два.
    1. Запланировать показ текущего значения изменяемого объекта planet (console.log() делает именно это!)
    2. Изменить значение объекта planet
    И спустя некоторое (пусть и небольшое) время
    3. Отобразить текущее значение изменяемого объекта planet.
    Не важно, в каком порядке выполняются 1 и 2, к момент выполнения 3 значение planet уже будет изменено.

    А вот если выводить строку, например, innerHTML, ситуация изменится, потому что строки не изменяемы!
    И тогда будет так:
    1. Запланировать показ объекта-строки, которая в настоящий момент находится в объекте planet.
    2. Сменить содержимое planet на другое. Старая строка при этом не пропадает, так как её показ уже запланирован. Про новую строку консоль ничего не знает.
    И спустя время
    3. Показать в консоли запланированный объект-строку.

    Иными словами, в первом случае содержимое объекта planet читается на шаге 3, где оно уже изменилось. Во втором случае, значение строки, которую мы взяли из planet, тоже читается на шаге 3 - но тот факт, что внутри planet эта строка была заменена на другую, ни на что не влияет.

    Вот, на пальцах:
    Вариант 1
    611443763c478362532846.png

    Вариант 2
    6114439e7363a433817881.png
    Ответ написан
    1 комментарий
  • Что делает команда cls < NUL?

    Vindicar
    @Vindicar
    Ну вообще < - это перенаправление ввода программы, так же как > - перенаправление стандартного вывода программы. NUL - это устройство (псевдофайл), точнее пустое устройство. Вывод в него не даёт ничего, а ввод эквивалентен чтению пустого файла.
    Вот только зачем это cls...
    Ответ написан
    Комментировать

Лучшие вопросы пользователя

Все вопросы (12)