Using VK Streaming API with Telegram Notification


Vkontakte launched the Streaming API, a tool for obtaining public data from VKontakte for the given keywords.

VK itself sends new suitable content as it appears. Thus, you can get interesting records without joining dozens of groups, immediately after publication.

Let's write a bot for a telegram with notification of entries in the VK.

Receive news


First you need to create an application in VK and take the service key from the settings



. The WebSocket protocol is used to transfer data. We use the "websocket" library.

import websocket

Before connecting, use the streaming.getServerUrl method. As a result, the method returns the URL for further requests in the endpoint (string) field and the access key in the key (string) field.

Get url and key

def get_streaming_server_key(token):
    request_url = "https://api.vk.com/method/streaming.getServerUrl?access_token={}&v=5.64".format(token)
    r = requests.get(request_url)
    data = r.json()
    return {"server":data["response"]["endpoint"],"key":data["response"]["key"]}

Listening to the server

def listen_stream():
    websocket.enableTrace(True)
    ws = websocket.WebSocketApp("wss://{}/stream?key={} ".format(stream["server"], stream["key"]),
                                on_message=on_message,
                                on_error=on_error,
                                on_close=on_close)
    ws.on_open = on_open
    ws.run_forever()
def on_message(ws, message):
    print(">>>> receive message:", message)
def on_error(ws, error):
    print(">>>> error thead:",error)
def on_close(ws):
    print(">>>> close thead")
def on_open(ws):
    print(">>>> open thead")
stream = get_streaming_server_key(my_servise_token)
listen_stream()

After starting, the following should appear in the console
- request header - GET / stream? Key = e6290ba04916a314c398c331f60224d012fabeb1 HTTP / 1.1
Upgrade: websocket
Connection: Upgrade
Host: streaming.vk.com
Origin: streaming.vk.com
Sec-WebSocket-Key: vG40A5bwbPaVBS + DLBOyog =
Sec : 13
- - response header - HTTP / 1.1 101 Switching Protocols
Server: Apache
Date: Thu, 20 Jul 2017 22:06:55 GMT
Connection: upgrade
Upgrade: websocket
Sec-WebSocket-Accept: QRJNqD8K7vWNMcQesYKo64q8MfA =
- >>>> open thead
send: b "\ x8a \ x80d ') \ x90"
send: b' \ x8a \ x80 \ xfcmp \ xe6 '
send: b' \ x8a \ x80s \ x9f6 {'
send: b' \ x8a \ x80 \ xc9 \ xfa . \ xd4 '
send: b'\ x8a \ x80fU <\ xed '
send: b '\ x8a \ x80 \ xc6Ji \ x19'
send: b '\ x8a \ x80 \ xd2D \ x08!'

Work with rules


Addendum

HTTP POST Method
Content Type application / json
Request URL https: // {endpoint} / rules? Key = {key}


def set_my_rules(value):
    rule_params = {"rule":{"value":value,"tag":'tag_'+str(random.randint(11111, 99999))}}
    headers = {'content-type': 'application/json'}
    r = requests.post("https://{}/rules?key={}".format(stream["server"], stream["key"]), data=json.dumps(rule_params), headers=headers)
    data = r.json()
    return data['code'] == 200

Getting

HTTP GET method
Request URL https: // {endpoint} / rules? Key = {key}



def get_my_rules():
    r = requests.get("https://{}/rules?key={}".format(stream["server"], stream["key"]))
    data = r.json()
    if data['code'] != 200:
        return False
    return data['rules']

Removal

HTTP Method DELETE
Content Type application / json
Request URL https: // {endpoint} / rules? Key = {key}


def del_my_rules(tag):
    headers = {'content-type': 'application/json'}
    rule_params = {"tag":tag}
    r = requests.delete("https://{}/rules?key={}".format(stream["server"], stream["key"]), data=json.dumps(rule_params), headers=headers)
    data = r.json()
    return data['code'] == 200

Trying to get the news.

stream = get_streaming_server_key(my_servise_token)
set_my_rules('кот')
listen_stream()

The following should appear in the console
send: b '\ x8a \ x80 \ xc9 \ xfa. \ xd4'
send: b '\ x8a \ x80fU <\ xed'
send: b '\ x8a \ x80 \ xc6Ji \ x19'
send: b '\ x8a \ x80 \ xd2D \ x08! '
{"Code": 100, "event": {"event_type": "post", "event_id": {"post_owner_id": - 35708825, "post_id": 4560}, "event_url": " vk.com/wall- 35708825_4560 "," text ":" vk.com/small.dolly
The cat disappeared. In the city of Elektrostal on Zagonova street in the area of ​​16 schools. Young boy, 2 years castrated. The usual gray color with stripes. There is a white spot on the chin and chest. Large cat about 7 kg. Lost on June 27. If someone saw him, please inform 89250506596 or 89251527466. We love him very much and want him to return home "," creation_time ": 1498942995," tags ": [" test_cats "]," author ": {" id ": - 35708825}}} - our news

Telegram


We use the telebot library.


import telebot
TELEGRAM_API_TOKEN = '3277332...' # токен выдаваемый при создании бота
bot = telebot.TeleBot(TELEGRAM_API_TOKEN)

Bot start


def _send(msg):
    markup = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
    markup.add('Мои интересы', 'Очистить список интересов', 'Добавить')
    msg = bot.send_message(chatID, msg, reply_markup=markup) # шлем текст с вариантами ответа
    bot.register_next_step_handler(msg, process_step) # устанавливаем обработчик для наших ответов
# обработчик для 'help', 'start'
@bot.message_handler(commands=['help', 'start'])
def send_welcome(message):
    global chatID
    chatID = message.chat.id
    hello_test = 'Привет, %s! Я бот использующий VK Streaming API!' % message.from_user.first_name
    _send(hello_test)
# обработчик для наших ответов
def process_step(message):
    if message.text == 'Мои интересы':
        _send(get_rules_list())
    if message.text == 'Очистить список интересов':
        _send(clear_rules_list())
    if message.text == 'Добавить':
        msg = bot.send_message(chatID, "Что добавить?")
        bot.register_next_step_handler(msg, add_rule_handler)

Add




if message.text == 'Добавить':
        msg = bot.send_message(chatID, "Что добавить?")
        bot.register_next_step_handler(msg, add_rule_handler)
.....
def add_rule_handler(message):
    new_rule = set_my_rules(message.text)
    if new_rule:
        _send("Successful")
    else:
        logging.debug("Error add rules")
        _send("Error")

My interests

def get_rules_list():
    rules = get_my_rules()
    if rules:
        return "\n".join([str(rule['value']) for rule in rules])
    else:
        logging.debug("Error get rules list")
        return 'Error'

Clear list of interests

def clear_rules_list():
    rules = get_my_rules()
    if rules:
        for rule in rules:
            del_my_rules(rule['tag'])
        return "Successful"
    else:
        logging.debug("Error clear rules list")
        return 'Error'

News Submission

def on_message(ws, message):
    print(">>>> receive message:", message)
    message = json.loads(message)
    if not message['code']:
        return
    if not message['event']['event_type'] or message['event']['event_type'] != 'post':
        return # выходим, если запись не отдельный пост
    post = message['event']['event_type'] +"\n"+message['event']['text'].replace("
", "\n") +"\n\n"+ message['event']['event_url'] _send_post(post)

We start everything together


For correct operation, sockets must be run in a separate thread.

def listen_stream():
    websocket.enableTrace(True)
    ws = websocket.WebSocketApp("wss://{}/stream?key={} ".format(stream["server"], stream["key"]),
                                on_message=on_message,
                                on_error=on_error,
                                on_close=on_close)
    ws.on_open = on_open
    #ws.run_forever()
    wst = threading.Thread(target=ws.run_forever)
    wst.daemon = True
    wst.start()

We launch

if __name__ == '__main__':
    try:
        chatID = 0
        stream = get_streaming_server_key(my_servise_token)
        listen_stream()
        bot.polling(none_stop=True)
    except Exception as e:
        logging.exception("error start")





That's all, thanks.

Full script code
Streaming API docs
Telegram API docs
Python websocket-client
Python TelegramBotAPI

Also popular now: