Бот для группы вк python. Создание приложения Facebook



К сожалению, на данный момент нет хороших библиотек на Python2, для того, чтобы быстро создать чат-бота. Ниже я покажу, как легко можно написать примитивного чат бота для VK, используя API VK.


Статья написана для новичков, чтобы показать, что ничего сложного в написании ботов на Python нет.

Авторизация


В первом случае надо будет ввести логин и пароль. Во втором случае в группе надо включить "Сообщения сообщества" и создать ключ доступа к API:





import time import vk_api vk = vk_api.VkApi(login = "login", password = "password") #vk_api.VkApi(token = "a02d...e83fd") #Авторизоваться как сообщество vk.auth()

Отправка сообщений

Теперь напишем короткую функцию, которая отправляет сообщение выбранному человеку.


P.S. Сообщество может отправлять сообщения только ранее писавшим пользователям.


def write_msg(user_id, s): vk.method("messages.send", {"user_id":user_id,"message":s})

В vk.method мы можем вызывать любой метод из VK API и передавать параметры в виде словаря.


В данном случае мы вызываем метод messages.send и в качестве параметров передаем id пользователя и текст сообщения.

Прием сообщений

Отлично! Отправлять сообщения мы научились, осталось научиться их принимать. Для этого нам нужен метод messages.get .


Несколько параметров, на которые стоит обратить внимание:


1) out - если этот параметр равен 1, сервер вернет исходящие сообщения.
2) count - количество сообщений, которое необходимо получить.
3) time_offset - максимальное время, прошедшее с момента отправки сообщения до текущего момента в секундах.
4) last_message_id - идентификатор сообщения, полученного перед тем, которое нужно вернуть последним (при условии, что после него было получено не более count сообщений)


values = {"out": 0,"count": 100,"time_offset": 60} vk.method("messages.get", values)

В нашем случае этот метод вернет все полученные сообщения за последние 60 сек, если их конечно было меньше 100, а если больше, то последние 100.


В итоге мы получаем список items:


{u"count": 3441, u"items": [{u"body": u"\u041f\u0438\u0448\u0435\u043c \u0431\u043e\u0442\u0430 \u0434\u043b\u044f \u0432\u043a!", u"date": 1491934484, u"id": 7387, u"out": 0, u"read_state": 0, u"title": u" ... ", u"user_id": 23107592}, {u"body": u"\u041f\u0440\u0438\u0432\u0435\u0442 \u0425\u0430\u0431\u0440!", u"date": 1491934479, u"id": 7386, u"out": 0, u"read_state": 0, u"title": u" ... ", u"user_id": 23107592}]}

Если объяснять простыми словами, то items - это то, что можно выделить в диалоге.



Финальный аккорд, делаем вечный цикл, где на каждое сообщение будем отвечать "Привет, Хабр!".


while True: response = vk.method("messages.get", values) if response["items"]: values["last_message_id"] = response["items"]["id"] for item in response["items"]: write_msg(item,u"Привет, Хабр!") time.sleep(1)

Чат-бот готов.


P.S. Мы запоминаем параметр last_message_id, чтобы в следующий раз обрабатывать только новые сообщения.


Полный код

# -*- coding: utf-8 -*- import time import vk_api vk = vk_api.VkApi(login = "login", password = "password") #vk_api.VkApi(token = "a02d...e83fd") #Авторизоваться как сообщество vk.auth() values = {"out": 0,"count": 100,"time_offset": 60} def write_msg(user_id, s): vk.method("messages.send", {"user_id":user_id,"message":s}) while True: response = vk.method("messages.get", values) if response["items"]: values["last_message_id"] = response["items"]["id"] for item in response["items"]: write_msg(item,u"Привет, Хабр!") time.sleep(1)


Получилось 17 строк кода. Успехов!

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

Вот так будет выглядеть финальная версия нашего приложения:

Технический стек

Нажмите кнопку «create an app…» и следуйте инструкциям на экране:

Два нижних поля не будут использоваться, поэтому оставьте их пустыми. В поле с описанием приложения лучше написать что-то связанное с проектом. К огда приложение начнёт делать много запросов, представители Reddit могут проверить, для чего оно.

Теперь, когда ваше приложение создано, вам нужно сохранить client_id и client_secret в безопасном месте:

Первая часть нашего проекта выполнена. Теперь нам нужно настроить базу для нашего приложения Heroku.

Создание приложения на Heroku

На следующей странице дайте своему приложению уникальное имя. Нажмите «Heroku CLI» и загрузите последнюю версию интерфейса командной строки Heroku для вашей операционной системы. Следуйте инструкциям на экране и вернитесь, как только интерфейс будет загружен.

Создание базового приложения Python

Приведенный ниже код взят с сайта Константиноса Цапраилиса .

From flask import Flask, request import json import requests app = Flask(__name__) # This needs to be filled with the Page Access Token that will be provided # by the Facebook App that will be created. PAT = "" @app.route("/", methods=["GET"]) def handle_verification(): print "Handling Verification." if request.args.get("hub.verify_token", "") == "my_voice_is_my_password_verify_me": print "Verification successful!" return request.args.get("hub.challenge", "") else: print "Verification failed!" return "Error, wrong validation token" @app.route("/", methods=["POST"]) def handle_messages(): print "Handling Messages" payload = request.get_data() print payload for sender, message in messaging_events(payload): print "Incoming from %s: %s" % (sender, message) send_message(PAT, sender, message) return "ok" def messaging_events(payload): """Generate tuples of (sender_id, message_text) from the provided payload. """ data = json.loads(payload) messaging_events = data["entry"]["messaging"] for event in messaging_events: if "message" in event and "text" in event["message"]: yield event["sender"]["id"], event["message"]["text"].encode("unicode_escape") else: yield event["sender"]["id"], "I can"t echo this" def send_message(token, recipient, text): """Send the message text to recipient with id recipient. """ r = requests.post("https://graph.facebook.com/v2.6/me/messages", params={"access_token": token}, data=json.dumps({ "recipient": {"id": recipient}, "message": {"text": text.decode("unicode_escape")} }), headers={"Content-type": "application/json"}) if r.status_code != requests.codes.ok: print r.text if __name__ == "__main__": app.run()

Мы будем редактировать файл в соответствии с нашими потребностями. Бот Facebook будет работать следующим образом:

  1. Facebook отправляет запрос на наш сервер всякий раз, когда пользователь пишет сообщение на нашей странице Facebook.
  2. Мы отвечаем на запрос Facebook и сохраняем идентификатор пользователя и сообщение, которое было отправлено на нашу страницу.
  3. Мы отвечаем на сообщение пользователя через Graph API, используя сохранённый идентификатор пользователя и идентификатор сообщения.

Подробный разбор приведенного выше кода доступен на веб-сайте Константиноса Цапраилиса. В этом посте я сосредоточусь главным образом на интеграции Reddit и использовании базы данных Postgres на Heroku.

$ messenger-bot $ cd messenger-bot $ touch requirements.txt app.py Procfile

Выполните вышеприведенные команды в терминале и поместите вышеуказанный код Python в файл app.py . Потом поместите в Procfile следующее:

Web: gunicorn app:app

Теперь мы должны сообщить Heroku, какие библиотеки Python будет использовать наше приложение. Эти библиотеки должны быть перечислены в файле requirements.txt:

Click==6.6 Flask==0.11 gunicorn==19.6.0 itsdangerous==0.24 Jinja2==2.8 MarkupSafe==0.23 requests==2.10.0 Werkzeug==0.11.10

Выполните следующую команду в терминале. Вы получите такой результат:

$ ls Procfile app.py requirements.txt

Теперь мы создадим Git-репозиторий, который затем может быть помещен на серверы Heroku. Для его создания мы должны выполнить следующие шаги:

  1. Войти в Heroku.
  2. Создать новый репозиторий.
  3. Сохранить состояние проекта в репозиторий.
  4. Отправить его на Heroku.

Для этого введите следующие команды в терминал:

$ heroku login $ git init $ heroku git:remote -a $ git commit -am "Initial commit" $ git push heroku master ... remote: https://.herokuapp.com/ deployed to Heroku ... $ heroku config:set WEB_CONCURRENCY=3

Сохраните адрес из строки «remote: …» - это адрес вашего Heroku-приложения. Он понадобится нам на следующем этапе.

Создание приложения Facebook

Для создания приложения нам нужна его страница на Facebook . Таково требование Facebook - у каждого приложения должна быть страница.

Теперь нам нужно зарегистрировать новое приложение. Перейдите на страницу создания приложения и следуйте инструкциям ниже:

Затем перейдите в свой файл app.py и замените PAT в строке 9 на Page Access Token, который мы сохранили выше.

Cохраните все и отправьте код в Heroku.

$ git commit -am "Added in the PAT" $ git push heroku master

Теперь, если вы перейдете на страницу Facebook и отправите сообщение на эту страницу, вы получите своё собственное сообщение в ответ. Это подтвердит, что мы всё сделали верно. Если сообщение не пришло, проверьте логи Heroku, которые дадут вам некоторое представление об ошибке. Вы можете получить доступ к логам следующим образом:

$ heroku logs -t -a

Примечание: бот будет отвечать только на ваши сообщения, потому что он ещё не одобрен Facebook. Однако вы можете добавить нескольких тестировщиков. Для этого следуйте указаниям на странице разработчика.

Получение данных с Reddit

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

У становим praw - Python-библиотеку сайта Reddit. Это легко сделать, введя следующую команду в терминале:

$ pip install praw

Теперь протестируем некоторые прелести Reddit в оболочке Python. В документации чётко показано, как получить доступ к Reddit и его сообществам. Сейчас самое подходящее время, чтобы использовать client_id и client_secret , которые мы создали в первой части статьи.

$ python Python 2.7.13 (default, Dec 17 2016, 23:03:43) on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import praw >>> reddit = praw.Reddit(client_id="**********", ... client_secret="*****************", ... user_agent="my user agent") >>> >>> submissions = list(reddit.subreddit("GetMotivated").hot(limit=None)) >>> submissions[-4].title u" Hi, Stranger."

Не забудьте добавить в свой собственный client_id и client_secret вместо **** .

В приложении используется limit = None . Это позволит получать как можно больше сообщений. Изображения мы будем использовать только из GetMotivated и Memes, а текстовые сообщения только из Jokes и ShowerThoughts.

Теперь, когда мы знаем, как получить доступ к Reddit, используя библиотеку Python, мы можем продолжить и интегрировать его в app.py .

Добавим несколько дополнительных библиотек в наш файл requirements.txt , чтобы он выглядел примерно так:

$ cat requirements.txt click==6.6 Flask==0.11 gunicorn==19.6.0 itsdangerous==0.24 Jinja2==2.8 MarkupSafe==0.23 requests==2.10.0 Werkzeug==0.11.10 flask-sqlalchemy psycopg2 praw

Просто отправить пользователю изображение или текст, взятый из Reddit, было бы нетрудно. В функции send_message мы могли бы сделать что-то вроде этого:

Import praw ... def send_message(token, recipient, text): """Send the message text to recipient with id recipient. """ if "meme" in text.lower(): subreddit_name = "memes" elif "shower" in text.lower(): subreddit_name = "Showerthoughts" elif "joke" in text.lower(): subreddit_name = "Jokes" else: subreddit_name = "GetMotivated" .... if subreddit_name == "Showerthoughts": for submission in reddit.subreddit(subreddit_name).hot(limit=None): payload = submission.url break ... r = requests.post("https://graph.facebook.com/v2.6/me/messages", params={"access_token": token}, data=json.dumps({ "recipient": {"id": recipient}, "message": {"attachment": { "type": "image", "payload": { "url": payload }} }), headers={"Content-type": "application/json"}) ...

Но нам нужен идентификатор для каждого изображения или текста, отправляемого пользователю, чтобы не отправлять одну и ту же запись дважды. Чтобы решить эту проблему, мы будем использовать PostgresSQL и идентификаторы постов Reddit (у каждого поста на Reddit есть уникальный id).

Мы будем использовать отношение «многие-ко-многим». Создадим две таблицы:

  • пользователи;
  • посты.

Сначала определим их в нашем коде, а затем уже разберёмся, как это будет работать:

From flask_sqlalchemy import SQLAlchemy ... app.config["SQLALCHEMY_DATABASE_URI"] = os.environ["DATABASE_URL"] db = SQLAlchemy(app) ... relationship_table=db.Table("relationship_table db.Column("user_id", db.Integer,db.ForeignKey("users.id"), nullable=False), db.Column("post_id",db.Integer,db.ForeignKey("posts.id"),nullable=False db.PrimaryKeyConstraint("user_id", "post_id")) class Users(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255),nullable=False) posts=db.relationship("Posts", secondary=relationship_table, backref="users") def __init__(self, name): self.name = name class Posts(db.Model): id=db.Column(db.Integer, primary_key=True) name=db.Column(db.String, unique=True, nullable=False) url=db.Column(db.String, nullable=False)

Таким образом, в таблице будет два поля. Имя будет идентификатором, отправленным с запросом Facebook Messenger Webhook. Посты будут связаны с другой таблицей - «Посты». В таблице сообщений есть имя и URL-адрес. «Имя» будет заполнено идентификатором поста Reddit, а URL - адресом этого поста.

Итак, теперь наш окончательный код будет работать так:

  1. Мы запрашиваем список сообщений из определенного сообщества Reddit: reddit.subreddit(subreddit_name).hot(limit=None)
  2. Проверяем, был ли конкретный пост отправлен пользователю ранее.
  3. Если сообщение уже было отправлено, мы будем продолжать запрашивать посты от Reddit, пока не найдем новую запись.
  4. Если сообщение не было отправлено пользователю, мы отправляем сообщение и выходим из цикла.

Итоговый код app.py выглядит так:

From flask import Flask, request import json import requests from flask_sqlalchemy import SQLAlchemy import os import praw app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = os.environ["DATABASE_URL"] db = SQLAlchemy(app) reddit = praw.Reddit(client_id="*************", client_secret="****************", user_agent="my user agent") # This needs to be filled with the Page Access Token that will be provided # by the Facebook App that will be created. PAT = "*********************************************" quick_replies_list = [{ "content_type":"text", "title":"Meme", "payload":"meme", }, { "content_type":"text", "title":"Motivation", "payload":"motivation", }, { "content_type":"text", "title":"Shower Thought", "payload":"Shower_Thought", }, { "content_type":"text", "title":"Jokes", "payload":"Jokes", } ] @app.route("/", methods=["GET"]) def handle_verification(): print "Handling Verification." if request.args.get("hub.verify_token", "") == "my_voice_is_my_password_verify_me": print "Verification successful!" return request.args.get("hub.challenge", "") else: print "Verification failed!" return "Error, wrong validation token" @app.route("/", methods=["POST"]) def handle_messages(): print "Handling Messages" payload = request.get_data() print payload for sender, message in messaging_events(payload): print "Incoming from %s: %s" % (sender, message) send_message(PAT, sender, message) return "ok" def messaging_events(payload): """Generate tuples of (sender_id, message_text) from the provided payload. """ data = json.loads(payload) messaging_events = data["entry"]["messaging"] for event in messaging_events: if "message" in event and "text" in event["message"]: yield event["sender"]["id"], event["message"]["text"].encode("unicode_escape") else: yield event["sender"]["id"], "I can"t echo this" def send_message(token, recipient, text): """Send the message text to recipient with id recipient. """ if "meme" in text.lower(): subreddit_name = "memes" elif "shower" in text.lower(): subreddit_name = "Showerthoughts" elif "joke" in text.lower(): subreddit_name = "Jokes" else: subreddit_name = "GetMotivated" myUser = get_or_create(db.session, Users, name=recipient) if subreddit_name == "Showerthoughts": for submission in reddit.subreddit(subreddit_name).hot(limit=None): if (submission.is_self == True): query_result = Posts.query.filter(Posts.name == submission.id).first() if query_result is None: myPost = Posts(submission.id, submission.title) myUser.posts.append(myPost) db.session.commit() payload = submission.title break elif myUser not in query_result.users: myUser.posts.append(query_result) db.session.commit() payload = submission.title break else: continue r = requests.post("https://graph.facebook.com/v2.6/me/messages", params={"access_token": token}, data=json.dumps({ "recipient": {"id": recipient}, "message": {"text": payload, "quick_replies":quick_replies_list} }), headers={"Content-type": "application/json"}) elif subreddit_name == "Jokes": for submission in reddit.subreddit(subreddit_name).hot(limit=None): if ((submission.is_self == True) and (submission.link_flair_text is None)): query_result = Posts.query.filter(Posts.name == submission.id).first() if query_result is None: myPost = Posts(submission.id, submission.title) myUser.posts.append(myPost) db.session.commit() payload = submission.title payload_text = submission.selftext break elif myUser not in query_result.users: myUser.posts.append(query_result) db.session.commit() payload = submission.title payload_text = submission.selftext break else: continue r = requests.post("https://graph.facebook.com/v2.6/me/messages", params={"access_token": token}, data=json.dumps({ "recipient": {"id": recipient}, "message": {"text": payload} }), headers={"Content-type": "application/json"}) r = requests.post("https://graph.facebook.com/v2.6/me/messages", params={"access_token": token}, data=json.dumps({ "recipient": {"id": recipient}, "message": {"text": payload_text, "quick_replies":quick_replies_list} }), headers={"Content-type": "application/json"}) else: payload = "http://imgur.com/WeyNGtQ.jpg" for submission in reddit.subreddit(subreddit_name).hot(limit=None): if (submission.link_flair_css_class == "image") or ((submission.is_self != True) and ((".jpg" in submission.url) or (".png" in submission.url))): query_result = Posts.query.filter(Posts.name == submission.id).first() if query_result is None: myPost = Posts(submission.id, submission.url) myUser.posts.append(myPost) db.session.commit() payload = submission.url break elif myUser not in query_result.users: myUser.posts.append(query_result) db.session.commit() payload = submission.url break else: continue r = requests.post("https://graph.facebook.com/v2.6/me/messages", params={"access_token": token}, data=json.dumps({ "recipient": {"id": recipient}, "message": {"attachment": { "type": "image", "payload": { "url": payload }}, "quick_replies":quick_replies_list} }), headers={"Content-type": "application/json"}) if r.status_code != requests.codes.ok: print r.text def get_or_create(session, model, **kwargs): instance = session.query(model).filter_by(**kwargs).first() if instance: return instance else: instance = model(**kwargs) session.add(instance) session.commit() return instance relationship_table=db.Table("relationship_table", db.Column("user_id", db.Integer,db.ForeignKey("users.id"), nullable=False), db.Column("post_id",db.Integer,db.ForeignKey("posts.id"),nullable=False), db.PrimaryKeyConstraint("user_id", "post_id")) class Users(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255),nullable=False) posts=db.relationship("Posts", secondary=relationship_table, backref="users") def __init__(self, name=None): self.name = name class Posts(db.Model): id=db.Column(db.Integer, primary_key=True) name=db.Column(db.String, unique=True, nullable=False) url=db.Column(db.String, nullable=False) def __init__(self, name=None, url=None): self.name = name self.url = url if __name__ == "__main__": app.run()

Отправьте его в Heroku:

$ git commit -am "Updated the code with Reddit feature" $ git push heroku master

Осталось последнее. Нам нужно сказать Heroku, что мы будем использовать базу данных. Для этого введите в терминале следующую команду:

$ heroku addons:create heroku-postgresql:hobby-dev --app

Так мы создадим базу данных, которой достаточно для нашего проекта. Теперь нам нужно инициализировать её правильными таблицами. Для этого мы сначала должны запустить оболочку Python на нашем сервере Heroku:

$ heroku run python

Затем в оболочке Python ввести следующие команды:

>>> from app import db >>> db.create_all()

Наше приложение готово! Поздравляю!

Некоторые интересные особенности кода

Во-первых, в коде используется функция быстрых ответов интерфейса Facebook Messenger Bot API. Это позволяет нам отправлять некоторые предварительно отформатированные данные, которые пользователь может быстро выбрать. Они будут выглядеть примерно так:

С каждым запросом на публикацию в API Facebook мы отправляем дополнительные данные:

Quick_replies_list = [{ "content_type":"text", "title":"Meme", "payload":"meme", }, { "content_type":"text", "title":"Motivation", "payload":"motivation", }, { "content_type":"text", "title":"Shower Thought", "payload":"Shower_Thought", }, { "content_type":"text", "title":"Jokes", "payload":"Jokes", }]

Еще одна интересная особенность кода заключается в том, как мы определяем, является ли сообщение текстом, изображением или видеозаписью. В сообществе GetMotivated некоторые изображения не имеют расширения «.jpg» или «.png» в их URL, поэтому мы полагаемся на:

Submission.link_flair_css_class == "image"

Вы могли заметить эту строку кода в файле app.py:

Payload = "http://imgur.com/WeyNGtQ.jpg"

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

Следующая функция проверяет, существует ли пользователь с определенным именем или нет. Если он существует, она выбирает этого пользователя из базы данных и возвращает его. Если он не существует, она создает его, а затем возвращает вновь созданного пользователя:

MyUser = get_or_create(db.session, Users, name=recipient) ... def get_or_create(session, model, **kwargs): instance = session.query(model).filter_by(**kwargs).first() if instance: return instance else: instance = model(**kwargs) session.add(instance) session.commit() return instance

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

В большинстве случаев, приложения обмениваются с сервером информацией по HTTP, посылая информацию POST-запросом, в ответ получая XML. Наша задача состоит в том, чтобы эмитировать эти запросы. Нашим подопытным кроликом будет приложение «Тюгяга »

Какие инструменты нам потребуются:

  • Python - Любимый всеми язык. Будем использовать только стандартную библиотеку.
  • Charles - простой HTTP-прокси. Его мы будем использовать для перехвата и анализа запросов.

Итак, приступим:

Для начала запустим Charles. Разобраться в нём сможет даже ребёнок. Приложение советую запускать в Firefox’е. Попробуйте выполнить какое-нибудь действие в «Тюряге», например собрать сигареты, и посмотрите на последний запрос. В общем случае вы увидите что-то вроде этого:

POST /prison/universal.php?office HTTP/1.1
Host: 109.234.156.250
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Referer: xxxxx
Content-type: application/x-www-form-urlencoded
Content-length: 111

method=office&sig=4b8874255d3f868e4e9f4006e51635de&user=xxxxxxxxx&getidea=1&key=xxxxxxxxxxxxxx

Тут мы имеем URI, HTTP-заголовки, пустую строку, и данные, отправленные на сервер. Что же отправляется на сервер:

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

user - Ваш id.

sig - Сигнатура, генерируемая тюрягой. Честно говоря, я не разобрался для чего она служит и по какому принципу генерируется. Но без неё никак. Лично я просто отловил их несколько штук и рандомно подставляю для каждого запроса. :)

method - Сообщает серверу, что за действие вы совершили.

Отправляются ещё и дополнительные данные, такие как getidea - сообщает сколько сигарет вы собрали.

Переходим к питону:

#!/usr/bin/env python3 # t.py import urllib, time, http.client, random, threading from xml.dom import minidom

Импортируем необходимые модули из стандартной библиотеки
xml.dom.minidom нужен если вы собирайтесь обрабатывать XML-ответ.

sigs = ("21ddcf3ea352f24ebdfe65bce51258da","4b8874255d3f868e4e9f4006e51635de","8dbedd3e931c8fd4fc97fa0fa74a1a20", "2243effc5a45a32c67b06898fb0b9548","7f47c0b6e9e385b8234ca9dce375a0c5","bdab387b62bed654492b8c93670a537e", "f17687ea1a535d61124dadb30887d14c","938b2f649aec28319ae2433ead41dae5") h ={ "Host":"188.93.20.139", "User-Agent":"Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15", "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language":"ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3", "Accept-Charset":"windows-1251,utf-8;q=0.7,*;q=0.7", "Keep-Alive":"115", "Content-type":"application/x-www-form-urlencoded", } u = "Ваш_ID" k = "Ваш key, для идентификации в приложении"

Создаём кортеж из сигнатур, заголовки в форме словаря(лишние я удалил), и две переменные.

Def request(post): global h # используем в функции глобальную переменную h connection = http.client.HTTPConnection("109.234.155.196:80") # Создаём объект соединения connection.request("POST", "/prison/universal.php", body = post, headers = h) # отправляем запрос resp = connection.getresponse() # получаем ответ return resp.read() # возвращаем ответ из функции

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

Def take_sigareties(): global sigs, u, k # используем в функции глобальные переменные post = urllib.parse.urlencode({ "method" : "office", "getidea" : "5", "sig" : random.choice(sigs), "user" : u, "key" : k }) # с помощью метода urllib.parse.urlencode подготавливаем данные для отправки. данные скармливаем методу в виде словаря while True: # запускаем бесконечный цикл for _ in range(0,20): # запускае цикл for на 20 раз request(post) # с помощью функции, которую мы создали ранее, отправляем данные на сервер print("Собрал сиги") time.sleep(5*20*60+15) # усыпляем поток выполнения на 6015 секунд. т.е. следующая итерация for произойдёт через указанное время. time.sleep(8*60*60) # после того как собрали 20 раз сиги, усыпляем поток на 8 часиков, чтобы нас не спалили;)

Создаём функцию для сбора сигареток

По аналогии создадим функцию для сбора прибыли раз в 8 часов:

Def take_rewards(): global sigs, u, k post = urllib.parse.urlencode({ "method" : "getAllBuildingsRewards", "sig" : random.choice(sigs), "user" : u, "key" : k }) while True: request(post) print("Собрал прибыль") time.sleep(8*60*60+15)

Т.к. нам надо чтобы функции работали независимо друг от друга, запустим их в отдельных потоках:

T1 = threading.Thread(target = take_sigareties) # создаём объект потока, target"у подаётся созданная функция t1.deamon = True # это нужно для того, чтобы при закрытии основного потока, дочерний поток тоже закрывался t2 = threading.Thread(target = take_rewards) t2.deamon = True t1.start() # запускаем поток на выполнение t2.start()

На этом собственно всё, запускаем скрипт, и радуемся, что больше не надо заходить в приложение каждые 20 минут, чтобы собрать сигоретки.

По аналогии можно писать ботов для других приложений.

Вот полный код бота.

#!/usr/bin/env python3 # t.py import urllib, time, http.client, random, threading from xml.dom import minidom sigs = ("21ddcf3ea352f24ebdfe65bce51258da","4b8874255d3f868e4e9f4006e51635de","8dbedd3e931c8fd4fc97fa0fa74a1a20", "2243effc5a45a32c67b06898fb0b9548","7f47c0b6e9e385b8234ca9dce375a0c5","bdab387b62bed654492b8c93670a537e", "f17687ea1a535d61124dadb30887d14c","938b2f649aec28319ae2433ead41dae5") h ={ "Host":"188.93.20.139", "User-Agent":"Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15", "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language":"ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3", "Accept-Charset":"windows-1251,utf-8;q=0.7,*;q=0.7", "Keep-Alive":"115", "Content-type":"application/x-www-form-urlencoded", } u = "Ваш_ID" k = "Ваш key" def request(post): global h # используем в функции глобальную переменную h connection = http.client.HTTPConnection("109.234.155.196:80") # Создаём объект соединения connection.request("POST", "/prison/universal.php", body = post, headers = h) # отправляем запрос resp = connection.getresponse() # получаем ответ return resp.read() # возвращаем ответ из функции def take_rewards(): global sigs, u, k post = urllib.parse.urlencode({ "method" : "getAllBuildingsRewards", "sig" : random.choice(sigs), "user" : u, "key" : k }) while True: request(post) print("Собрал прибыль") time.sleep(8*60*60+15) def take_sigareties(): global sigs, u, k # используем в функции глобальные переменные post = urllib.parse.urlencode({ "method" : "office", "getidea" : "5", "sig" : random.choice(sigs), "user" : u, "key" : k }) # с помощью метода urllib.parse.urlencode подготавливаем данные для отправки. данные скармливаем методу в виде словаря while True: # запускаем бесконечный цикл for _ in range(0,20): # запускае цикл for на 20 раз request(post) # с помощью функции, которую мы создали ранее, отправляем данные на сервер print("Собрал сиги") time.sleep(5*20*60+15) # усыпляем поток выполнения на 6015 секунд. т.е. следующая итерация for произойдёт через указанное время. time.sleep(8*60*60) # после того как собрали 20 раз сиги, усыпляем поток на 8 часиков, чтобы нас не спалили;) def do_city_action(): global sigs, u, k while True: action_id = 1 while action_id < 8: for _ in range(0,5): post = urllib.parse.urlencode({ "method" : "doCityAction", "city" : "1", "action_id" : str(action_id), "action_type" : "3", "sig" : random.choice(sigs), "user" : u, "key" : k }) response = request(post) print("Выполнил задание") if int(minidom.parseString(str(response, "utf8")).getElementsByTagName("energy").firstChild.data) < 10: time.sleep(40*5*60) action_id +=1 def vote_friends_to_gym(): global sigs, u, k friends = () # кортеж друзей, которых вы хотите позвать в спортзал while True: for friend in friends: post = urllib.parse.urlencode({ "method" : "voteForFriend", "model_id" : "1", "sex" : "0", "friend_uid" : friend, "vote" : "5", "username" : "London Eyes", "sig" : random.choice(sigs), "user" : u, "key" : k }) request(post) print("Позвал " + friend + " в спортзал") time.sleep(24*60*60+15) def break_terpilas_faces(): global sigs, u, k terpilas = () # кортеж друзей, на которых вы хотите наехать while True: for terpila in terpilas: post = urllib.parse.urlencode({ "method" : "challengeToDuel", "enemy" : terpilas, "sig" : random.choice(sigs), "user" : u, "key" : k }) request(post) print("Наехал на " + terpila) time.sleep(24*60*60+15) def send_presents(): recipients = "" # чезез запятую id друзей, которым вы хотите заслать подогрев while True: post = urllib.parse.urlencode({ "method" : "sendPresent", "recipients" : recipients, "present_id" : "5", "sig" : random.choice(sigs), "user" : u, "key" : k }) request(post) print("Послал подогревы") time.sleep(24*60*60+15) t1 = threading.Thread(target = take_rewards) # создаём объект потока, target"у подаётся созданная функция t1.deamon = True # это нужно для того, чтобы при закрытии основного потока, дочерний поток тоже закрывался t2 = threading.Thread(target = take_sigareties) t2.deamon = True t3 = threading.Thread(target = do_city_action) t3.deamon = True t4 = threading.Thread(target = vote_friends_to_gym) t4.deamon = True t5 = threading.Thread(target = break_terpilas_faces) t5.deamon = True t6 = threading.Thread(target = send_presents) t6.deamon = True t1.start() # запускаем поток на выполнение t2.start() t3.start() t4.start() t5.start() t6.start()



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: