Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
ksantoprotein
6 лет назад

Кодим боевого бота голоса (клеймо резонатора)

В один день чуть бухой резонатор накатал пост с идей клеймение некоторых участников голоса. Так как мне исходная идея не понравилась, то переделал под свои нужды и первым кто попал под прицел бота оказался как раз сам резонатор. Наука вроде иногда требует жертв.

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

Концепт

Главное в разработке с самого начала более менее обдумать что кому. Так как в этом проекте я увидел перспективы монетизации, то имеет смысл уделить большее внимание всем деталям... и заодно устроить образовательный курс как по кодингу, так и по экономике... ну а что? надеюсь многие тут не лыком шиты.

В чем идея "клеймо резонатора"? На самом деле все просто. Как только цель что-либо постит или комментит на голосе, как за ним пристраивается бот-клеймо и оставляет комментарии, мол клеймо такое-то. Происходит заспамленность того места, куда сунулась цель, что явно не особо нравится окружающим. Так что в продолжении идеи резонатора бот-клеймо не будет оставлять следующую пачку комментариев если под комментом кто-то поставит флаг.

Вот такая интересная мешанина. С одной стороны оставляется коммент как это делает читах, только не один, а по максимуму, и не выставляется самим ботом флаг, а любой может флагануть и тем самым избавить свой блог от заклейменного.

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


Начало

# -*- coding: utf-8 -*-

from piston import Steem
bot = "deathspore"
bot_wif=["5K..."]
golos = Steem('wss://ws.golos.io', wif = bot_wif)

Вот такое начало при подключении к блокчейну голос через публичную ноду с использованием python 3.4 и сторонней библиотеки piston. Описание как что установить и настроить в анналах нашего блокчейна есть... ищите.

А мы пока перейдем к той части, когда нам нужно выбрать цель/цели и подобрать к ним сообщения. Для этого опишем отдельно функцию... а потом... в будущем перепишем, но сам формат вызова оставим неизменным. Это очень грамотный подход, когда в коде программы отдбеные кусочки когда помещаешь в функцию.

def load_stigma():

Зададим название функции, чтобы она отражала происходящее. Таким образом мы даем себе понять, что с помощью этой функции мы заполучим список целей и заодно текстовку к ним. Ага, тестовка... сразу скажу, текстовка, он же комментарий будет состоять из трех частей:
text_user
text_var
text_const

первая переменная описывает тот текст, который захочет сам пользователь бота. Не забываем про монетизацию. Вторая переменная будет содержать некую часть, которая с каждым комментом будет разная, это необходимо, чтобы комменты НЕ выглядели явным спамом (пока поставим в них пропуск) и третья часть постоянна. Она как раз будет описывать, что мол флаганите и бот больше не будет комментить.

Далее у меня уже есть три цели для экспериментов. Во-первых это @antonkostroma - многие хотят что-то да оставить ему в послании, далее это @tr1n1t1, за тринити гонятся агенты матрицы! И @rumeet-ez - он попал мне под горячую руку, так как решил сделать левый пост и типа собрать апы от ботов... так и призывал, мол боты, идите ко мне... Ну вот они и пришли... теперь петушком меня называет... на его бы месте не спешил бы, дело в том, что на данный момент моих ресурсов вполне хватит чтобы вогнать его репу почти в ноль. но надо давать шанс всем хотя бы признать свои ошибки.

    mas_stigma = []

    login = 'antonkostroma'
    text_user = 'Клеймо справедливого флагователя'
    text_var = ''
    text_const = 'Флаганите цель и бот перестанет оставлять комментарии'
    body = '\n'.join([text_user, text_var, text_const])
    mas_stigma.append([login, body])

    login = 'tr1n1t1'
    text_user = 'Беги, Тринити!!! Агент Матрицы преследует тебя...'
    text_var = ''
    text_const = 'Флаганите цель и бот перестанет оставлять комментарии'
    body = '\n'.join([text_user, text_var, text_const])
    mas_stigma.append([login, body])

    login = 'rumeet-ez'
    text_user = 'Клеймо тестера на ботов'
    text_var = ''
    text_const = 'Флаганите цель и бот перестанет оставлять комментарии'
    body = '\n'.join([text_user, text_var, text_const])
    mas_stigma.append([login, body])

    return(mas_stigma)

Это решение топорное и предназначено для новичков. Код должен быть не только изящным, но и понятным. И раз у нас немного целей, то можно обойти шаблонами такого рода, чтобы понять синтаксис языка.

В начале функции задаем пустой список mas_stigma, он будет содержать логины login и текст комментария body. Текстовым переменным присваиваются значения и только text_var мы резервируем на будущее и оставляем пустой. Далее склеиваем все это в единый коммент... а теперь внимание, новички могут делать это так:
body = text_user + text_var + text_const
Но это приведет к единому тексту, надо добавить еще символ перевода строки и тогда выглядеть это будет так:
body = text_user + '\n' + text_var + '\n' + text_const
С одной стороны это понятно для новичка, но этот код плохой и так делать не надо. Это жрет много памяти, так как каждое сложение происходит ПО ОТДЕЛЬНОСТИ и в совокупности генерируется много не нужного нам, чтобы этого избежать используется конструкция join
body = '\n'.join()
И тогда то, что перечислите списком в скобках будет склеено в одну переменную через символ, который задан в кавычках ''.

В теле кода бота вызовем функцию таким образом

mas_stigma = load_stigma()

Хотя, сделаем немного иначе, запустим бесконечный цикл и будем вызывать основной код бота посылая в качестве аргумента результат самой функции. В будущем это позволит изменять настройки бота не выключая его. Так в каждом цикле работы он будет подгружать новые параметры.

while True:

    print('new step')
    run_stigma(load_stigma())

Вот так то лучше.
И переходим к объявлению функции - сердца бота

def run_stigma(mas_stigma):

первым делом нам необходимо раскрыть список следующим образом

for login, body in mas_stigma:

Так в питоне запускается цикл. Он проработает три раза и каждый раз в логине и комменте будут те значения, что мы присвоили в самом начале (или будем присваивать по ходу). и Еще... в начале кода еще укажем
from piston.account import Account
from datetime import datetime, date, time
from time import sleep

Надо подключить еще и эти библиотеки, а в самой функции пропишем следующее:

        new_account = Account(login)
        i = 0

        for rh in new_account.rawhistory(first=99999999999,limit=-1, only_ops=['comment'], exclude_ops=[]):
    
            time0 = time_now()

            author = rh[1]["op"][1]["author"]
            identifier = author + '/' + rh[1]["op"][1]["permlink"]
            time1 = datetime.strptime(rh[1]["timestamp"], "%Y-%m-%dT%H:%M:%S")
            age = (time0 - time1).total_seconds() / (60 * 60)
            if age > 24.0 or i >= 100:
                break

Фух, сложный момент, надо пояснить-то. Для начала мы инициируем выбранный аккаунт и устанавливаем счетчик i=0 (на будущее, если мы оставим 100 комментариев, то бот перейдет к следующей мишени)

Далее сканируем историю аккаунта и отбираем только комментарии (0 уровень комментариев - это пост). Засекаем текущее время и извлекаем из полученного массива идентификатор поста/комментария и время его создания. Если возраст больше суток (24 часа), то так же выходим из цикла и переходим на следующую мишень).

60 * 60 - это как раз способ превратить секунды в часы, а time_now() - авторская функция и выглядит она

def time_now():                 # Текущее время блокчейна

    golos_info=golos.info()
    return( datetime.strptime(golos_info["time"], "%Y-%m-%dT%H:%M:%S") )

Далее нам необходимо отсечь комменты НЕ цели, а они будут в истории аккаунта и проверить пост на наличие флагов (в виде отдельной функции).

            if author == login:
                if not check_flag(identifier):

                    print(round(age, 1),'h', identifier)

                    try:
                        r = golos.reply(identifier, body, author = bot)
                        i += 1
                        sleep(20)
                    except:
                        print('error comment')

            

Надеюсь этот кусочек кода понятен. Проверяем эквивалентность логина с автором, проверяем есть ли флаги и если есть совпадение по логину и нет флагов, то оставляем коммент, если коммент удался, то увеличиваем счетчик и ждем 20 секунд (время между двумя комментариями у нас ограничено 20 секундами).

Переходим к создании новой функции

def check_flag(identifier):

    post_author, post_permlink = identifier.split('/')
    post = golos.rpc.get_content(post_author, post_permlink)

    flag = False

    for active_votes in post["active_votes"]:

        if int(active_votes["percent"]) < 0:
            flag = True
            break

    return(flag)

Делаем лишнее действие и сплитуем ссылку на пост или коммент отдельно на кусок с автором и кусок с пермлинком (это чтобы новичкам чуть более было понятно где что и как называется). Далее извлекаем необходимые данные из коммента, и если есть хоть один кто оставил флаг (меньше нуля процент апвота), то возвращаем "истину", иначе возвращаем "ложь".


Вот и всё. бот запущен и смотрим что же он там делает, возможно вылезут баги - это обычное дело - подправим.

А теперь главное! На голосе есть куча гуманитариев, экономистов и прочих, кто считает, что разбирается в толпе итд итд. К вам предложение. Если напишите свой бизнес-план о возможной монетизации данного проекта, укажете свой процент и свой функционал в нем. То с удовольствием приму в команду.

Вопросы и бизнес модели оставляйте в комментариях ибо нам есть что обсудить, когда речь идет о заработке.

2
353.297 GOLOS
На Golos с July 2017
Комментарии (75)
Сортировать по:
Сначала старые