Кодим боевого бота голоса (клеймо резонатора)
В один день чуть бухой резонатор накатал пост с идей клеймение некоторых участников голоса. Так как мне исходная идея не понравилась, то переделал под свои нужды и первым кто попал под прицел бота оказался как раз сам резонатор. Наука вроде иногда требует жертв.
Поэтому сегодня мы постараемся научиться кодить что-то в свою защиту от посягательств на свою персону.
Концепт
Главное в разработке с самого начала более менее обдумать что кому. Так как в этом проекте я увидел перспективы монетизации, то имеет смысл уделить большее внимание всем деталям... и заодно устроить образовательный курс как по кодингу, так и по экономике... ну а что? надеюсь многие тут не лыком шиты.
В чем идея "клеймо резонатора"? На самом деле все просто. Как только цель что-либо постит или комментит на голосе, как за ним пристраивается бот-клеймо и оставляет комментарии, мол клеймо такое-то. Происходит заспамленность того места, куда сунулась цель, что явно не особо нравится окружающим. Так что в продолжении идеи резонатора бот-клеймо не будет оставлять следующую пачку комментариев если под комментом кто-то поставит флаг.
Вот такая интересная мешанина. С одной стороны оставляется коммент как это делает читах, только не один, а по максимуму, и не выставляется самим ботом флаг, а любой может флагануть и тем самым избавить свой блог от заклейменного.
Можно еще долго разжевывать все нюансы, но лично сейчас я сам не уверен, что многие поняли что к чему. И более того, как это монетизировать, поэтому просто перейдем к образовательной части и будем учиться кодить.
Начало
# -*- 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)
Делаем лишнее действие и сплитуем ссылку на пост или коммент отдельно на кусок с автором и кусок с пермлинком (это чтобы новичкам чуть более было понятно где что и как называется). Далее извлекаем необходимые данные из коммента, и если есть хоть один кто оставил флаг (меньше нуля процент апвота), то возвращаем "истину", иначе возвращаем "ложь".
Вот и всё. бот запущен и смотрим что же он там делает, возможно вылезут баги - это обычное дело - подправим.
А теперь главное! На голосе есть куча гуманитариев, экономистов и прочих, кто считает, что разбирается в толпе итд итд. К вам предложение. Если напишите свой бизнес-план о возможной монетизации данного проекта, укажете свой процент и свой функционал в нем. То с удовольствием приму в команду.
Вопросы и бизнес модели оставляйте в комментариях ибо нам есть что обсудить, когда речь идет о заработке.