📜 ⬆️ ⬇️

Basics of working with LongPoll server VKontakte

Good day! Recently, I decided to get acquainted with the API of the largest social network in Europe - VKontakte. The “For Developers” section contains fairly detailed documentation, and there are quite a few articles on the Internet that help you get started with the VK API, so I decided that there should not be any serious problems in learning. However, when I got to the LongPoll server, it turned out that there were practically no articles on working with it, and the official documentation is not so complete to fully understand the material being studied. I had to try by trial and error to understand how LongPoll works, which I managed to do after a while. I decided to share the material I studied with other people in order to reduce their time learning new things. Below you can see the sections about which I managed to write.

Basics of working with the API (those who are familiar with the basic methods and requests for them, can skip this paragraph)
What is the VKontakte API? Here is how this official documentation treats:
Callback API is a tool for tracking user activity in your VKontakte community.

In other words, it is a way to send requests to VK servers in order to receive a response containing some information. With the VK API, you can do almost everything: send a message to the user, change the account password, create an album with photos, and so on. Personally, I use the vk_api library to work with the API, but you can also get away with the requests library. Now we consider the basic principles of work. If you decide to use the vk_api library, the sample query will look like this:

import vk_api session = vk_api.VkApi(token='{ACCESS_TOKEN}') print(session.method('users.get', {'user_ids': 210700286, 'fields': 'photo_50, city, verified'})) 

Let us examine the lines:

 import vk_api 
Here we import the library we need.
')
 session = vk_api.VkApi(token='{ACCESS_TOKEN}') 
With this line, we log in via access token (the ways to get it are available described in the documentation and on the Internet, I will not focus on them). Note: not all methods need authorization. About when it is required will be written in the documentation of the method on the site VKontakte.

 print(session.method('users.get', {'user_ids': 210700286, 'fields': 'photo_50, city'})) 
This part of the code deserves special attention. What is going on here? We call the method method, passing it two arguments: the first is the name of the API method, the second is the dictionary of the parameters of this method. A list of all methods and their parameters is in the API documentation. In this case, we call the "users.get" method and pass the following parameters: "user_ids" - a list of user id for which we want to receive data, "fields": additional information about users: avatar and city of residence. The output of the program will be the following output line: [{'id': 210700286, 'first_name': 'Lindsey', 'last_name': 'Stirling', 'city': {'id': 5331, 'title': 'Los Angeles'}, 'photo_50': 'https://pp.userapi.com/c636821/v636821286/38a75/Ay-bEZoJZw8.jpg'}]

If you make any mistake, for example, specify the wrong name of the method being called, an exception will be raised: vk_api.exceptions.ApiError: [5] User authorization failed: no access_token passed. .
Note: if an error is made in the name of an optional parameter, an exception will not be generated, and an unknown parameter will be ignored.

If you decide to use requests, you’ll have to go into the API documentation a bit to learn the format of the request and response.
The request should look like this: https://api.vk.com/method/{METHOD_NAME}?{PARAMS}&v={API_VERSION} , where {METHOD_NAME} is the name of the method, {PARAMS} are the parameters of the called method, and {API_VERSION} - the API version that the server should use when generating the response.
As a response, we will be returned a JSON object with information about the results of the method call. Let's implement an API request using the requests library:

 import requests data = requests.get('https://api.vk.com/method/{METHOD_NAME}'.format(METHOD_NAME='users.get'), params={'user_ids': 210700286, 'fields': 'photo_50, city'}).json() print(data) 

So, we analyze the written.

 import requests 
Import library requests

 data = requests.get('https://api.vk.com/method/{METHOD_NAME}'.format(METHOD_NAME='users.get'), params={'user_ids': 210700286, 'fields': 'photo_50, city'}).json() 
This line writes the server's response to the data variable. We give the function get two arguments: the address to which you want to make a request (in our case, a formatted string), and a dictionary of the parameters of this method. If the method is not called without access token, you need to add it to the dictionary with the key 'access_token'. The parameter “v” (API version) is not mandatory, since the latest version will be used by default, but if you need to use a different version, you must also add it to the dictionary with the 'v' key. The json () method that processes JSON objects is applied to the response sent from the server.

The last line displays the result of the work, in our case - {'response': [{'uid': 210700286, 'first_name': 'Lindsey', 'last_name': 'Stirling', 'city': 5331, 'photo_50': 'https://pp.userapi.com/c636821/v636821286/38a75/Ay-bEZoJZw8.jpg'}]} .

If you pass the wrong method name, the following will be displayed: {'error': {'error_code': 5, 'error_msg': 'User authorization failed: no access_token passed.', 'request_params': [{'key': 'oauth', 'value': '1'}, {'key': 'method', 'value': 'user.get'}, {'key': 'user_ids', 'value': '210700286'}, {'key': 'fields', 'value': 'photo_50, city'}]}} .

What is LongPoll?
For a start, let's ask for help in the documentation:
Long Polling is a technology that allows you to receive information about new events using the "long requests". The server receives the request, but sends a response to it not immediately, but only when a certain event occurs (for example, a new incoming message arrives), or the specified timeout expires.
In other words, when receiving a request from you, the server waits for an event to occur, about which it should notify you, and when it occurs, Long Poll server sends a response to your request containing information about the incident event.
We will write a program that will notify the user about some changes in his account, which we will receive from the Long Poll server. To start receiving responses from the server, it is necessary to obtain three required parameters required for Long Poll-a to work: server, key, and ts.
key - the secret key of the session;
server - server address;
ts - the number of the last event from which you want to receive data.

They do not need to be received each time calling Long Poll, one call will be enough. It follows from the documentation that these values ​​can be obtained by calling the messages.getLongPollServer method. We will write a program that will make a request with this method and we will use the data to get to Long Poll.

 import requests token = '' #      access_token data = requests.get('https://api.vk.com/method/messages.getLongPollServer', params={'access_token': token}).json()['response'] #     print(data) 

If you did everything correctly, the program will display a dictionary with three keys: {'key': '###############################', 'server': 'imv4.vk.com/im####', 'ts': 0000000000}

Request to Long Poll server
Now, using the values ​​stored in the dictionary that was created in the previous part, we can make a request to the Long Poll server! To do this, you need to make a request to the following address: https://{$server}?act=a_check&key={$key}&ts={$ts}&wait=25&mode=2&version=2 , where {$ server}, {$ key} and {$ ts} are values ​​from the dictionary with the keys 'server', 'key' and 'ts', respectively, wait is the time that the Long Poll server will wait for updates, and mode is the additional response options. Let's write a program that will make one request to the Long Poll server

 import requests token = '' #      access_token params = requests.get('https://api.vk.com/method/messages.getLongPollServer', params={'access_token': token}).json()['response'] #     response = requests.get('https://{server}?act=a_check&key={key}&ts={ts}&wait=90&mode=2&version=2'.format(server=data['server'], key=data['key'], ts=data['ts'])).json() #    Long Poll     90     2 print(response) 

If an event has occurred in 90 seconds that falls into the list processed by Long Poll server, something similar will appear on the screen: {'ts': 0000000000, 'updates': [[9, -999999999, 0, 1501588841]]} . What does the answer mean and how can we continue working with it?

First, you may have noticed that the response contains the parameter 'ts', which we used when sending the request. He is here for a reason. All events that fall into the list of servers processed by Long Poll are numbered. When you create a new account, the first such event is number 1, the second is 2, and so on. When sending a request to Long Poll, you need to pass this parameter in order for the server to know from which number you need to send updates. Each server response also includes this parameter, so that you use it when you next call the Long Poll server.

Secondly, the dictionary contains the key 'updates' with a talking name. It is not difficult to guess that the value of this key stores the updates that occurred after sending the request. Update format is an array of arrays. Each array in the array is an update that needs to be processed. If there are more than one in the first array of arrays, it means that several events occurred simultaneously. The 'ts' parameter contains the number of the last one. If the array accessible by the 'updates' key is empty, no events occurred during the wait time. You ask: "And what are these incomprehensible numbers in the arrays?". The answer is quite simple - this is information about the event that happened, which can be transformed into a clearer view. We will deal with their processing later, and in the next part we will write a program that will constantly access the Long Poll server.

Cyclic requests to Long Poll and event codes
In order to constantly send requests to Long Poll, I decided to use a loop in order not to overflow the stack with recursion. Below is the implementation of a program that accesses Long Poll and displays updates on the screen.

 import requests token = '' #      access_token data = requests.get('https://api.vk.com/method/messages.getLongPollServer', params={'access_token': token}).json()['response'] #     while True: response = requests.get('https://{server}?act=a_check&key={key}&ts={ts}&wait=20&mode=2&version=2'.format(server=data['server'], key=data['key'], ts=data['ts'])).json() #    Long Poll     20    2 updates = response['updates'] if updates: # ,    for element in updates: #       print(element) data['ts'] = response['ts'] #     

This program cyclically sends requests to Long Poll, checks if there have been updates, and displays the received updates on the screen. But the output of this program in the form in which they are now, is no good. Now the output of the program looks like this:
[8, -999999999, 1, 1501592696]
[8, -999999999, 7, 1501592862]
[9, -999999999, 0, 1501592882]
[9, -999999999, 1, 1501592583]
[8, -999999999, 4, 1501592893]
[9, -999999999, 0, 1501592900]

The first digit in each array indicates the event code. Using it, you can understand what event happened. Here is a list of event codes with a brief description (from the official documentation):
1 - Replacing message flags (FLAGS: = $ flags);
2 - Set message flags (FLAGS | = $ mask);
3 - Reset message flags (FLAGS & = ~ $ mask);
4 - Adding a new message;
6 - Read all incoming messages in $ peer_id that came before the message with $ local_id.
7 - Read all outgoing messages in $ peer_id that came before the message with $ local_id.
8 - The friend $ user_id has become online. $ extra is not equal to 0, if the flag 64 was transmitted in mode.
9 - The friend $ user_id became offline ($ flags is 0 if the user left the site (for example, clicked exit) and 1 if offline by timeout (for example, away status). $ timestamp - time of the last action of the user $ user_id on the site;
10 - Reset the $ peer_id dialog flags . Corresponds to the operation (PEER_FLAGS & = ~ $ flags). Only for community conversations;
11 - Replacing the dialog flags $ peer_id. Corresponds to the operation (PEER_FLAGS: = $ flags). Only for community conversations;
12 - Setting the flags of the $ peer_id dialog. Corresponds to the operation (PEER_FLAGS | = $ flags). Only for community conversations;
13 - Delete all messages in the $ peer_id dialog with identifiers up to $ local_id;
14 - Recently restored (less than 20 days ago) deleted messages in the $ peer_id dialog with identifiers up to $ local_id;
51 - One of the parameters (composition, subject) of the chat $ chat_id conversation has been changed. $ self - 1 or 0 (whether the changes are caused by the user);
61 - User $ user_id types the text in the dialog. The event comes once in ~ 5 seconds with constant typing. $ flags = 1;
62 - User $ user_id dials text in the conversation $ chat_id;
70 - User $ user_id made a call with the identifier $ call_id;
80 - The unread counter in the left menu has become $ count;
112 - Alert settings have changed. $ peer_id - ID of the chat / interlocutor.

Thus, if the first number in the array is 8, then one of your friends has become online, if 9 is offline and so on. The remaining numbers in the array also have a value, but we will pick them up later, since their value depends on the event code.

Handling incoming events
In this part, we implement the handling of events that come to us as an answer. Let me remind you that these events are presented in the form of arrays with information that needs to be processed. I suggest starting with code 80 - updating the counter of unread messages, since in my opinion this event is the least complicated. Here is an example of events with code 80:
[80, 0, 0]
[80, 1, 0]

The first parameter, as you already know, is the event code. There remain 2 elements: 0 and 0 in the first case and 1 0 in the second. The last parameter in code 80 should always be zero, so it can be ignored; only the second is important to us. The second parameter indicates how many unread messages the user currently has. The minimum value is 0 (no new messages), the maximum is unlimited. This is enough to handle all events with code 80. We implement this into code:

 #         ,       while True: response = requests.get('https://{server}?act=a_check&key={key}&ts={ts}&wait=20&mode=2&version=2'.format(server=data['server'], key=data['key'], ts=data['ts'])).json() #    Long Poll     20    2 updates = response['updates'] if updates: # ,    for element in updates: #       action_code = element[0] #      if action_code == 80: #    print('    ', element[1]) #  data['ts'] = response['ts'] #     

If you run this program, it will display messages about the change in the number of unread messages. The following relatively simple updates have codes 8 and 9 - a friend has become online and offline, respectively. Let's complete our program so that it can process them as well. Let's start with code 9. Let's write a line that will check the event code:

 elif action_code == 9: 

Next, consider the format of incoming updates with code 9:
[9, -000000000, 1, 1501744865]
With the index 0, as you already know, the update code is stored - 9. Next comes the negative id of the user who has become offline (to get the real id, you need to multiply by -1 in order to get rid of the minus). An element with index 3 can take only 2 values: 0 or 1. 1 means that the “offline” mark is set after the inactivity timeout expires, and 0 means that the user explicitly left the site, for example, by clicking the “exit” button. The last value in the response is the time of the last user action on the site at Unix time. Let's write down all received data in variables:

 user_id = element[1] * -1 # id ,   user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'fields': 'sex'}).json()['response'][0] # ,      id = user_id timeout = bool(element[2]) #        - last_visit = element[3] #        Unix time 

As you can see, in addition to the user's first and last name, we also get his gender. It is necessary that the program correctly uses the message in the sentences and does not write something like “Ivan Ivanov went out from VKontakte”. The timeout variable stores False if the user has explicitly left the site, and True if the timeout has expired. Now you can display the received data:

 #     "import time",     if user['sex'] == 1: verb = ['', ''] else: verb = ['', ''] if timeout: print(user['first_name'], user['last_name'], verb[0], '   -.     :', time.ctime(last_visit).split()[3]) else: print(user['first_name'], user['last_name'], verb[1], ' .     :', time.ctime(last_visit).split()[3]) 

The only thing that I see unobvious in this code is the time output:

time.ctime(last_visit).split()[3]
Let's deal with this part of the code. The ctime function of the time library takes as an argument a number - time in Unix time and returns a string like 'Thu Jan 1 03:00:00 1970'
'Thu Jan 1 03:00:00 1970'
. Since we only need the time of the last action on the site, we split this line using the split method and space the array, where index 0 stores the day of the week, index 1 - month, 2 - number, 3 - time, and 4 - year. We retrieve the element with the index 3, that is, time.

Now we will write the implementation of processing updates with code 8. Their format looks like this: [8, -6892937, 4, 1501750273] . The second element in the array is the negative id of the user who has become online, the third is the platform from which the user logged in, and the fourth is the time of the last user action on the site at Unix time. We realize the received data in the code:

 user_id = element[1] * -1 # id ,   user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'fields': 'sex'}).json()['response'][0] # ,      id = user_id platform = element[2] #    last_visit = element[3] #     Unix time if user['sex'] == 1: verb = '' else: verb = '' 

Here we have recorded the data from the answer in variables, and also put the verb in the right gender. The platform parameter now contains a number in the range from 1 to 7 inclusive. Each number represents the platform from which the user performed the action. We translate this number into the text:

 #      if platform == 1: platform = '   web- VK' elif platform == 2: platform = '  VK  iPhone' elif platform == 3: platform = '  VK  iPad' elif platform == 4: platform = '  VK  Android' elif platform == 5: platform = '  VK  Windows Phone' elif platform == 6: platform = '  VK  Windows' elif platform == 7: platform = ' web- VK' 

Now you can display information on the screen:

 print(user['first_name'], user['last_name'], verb, ' ', platform, '', time.ctime(last_visit).split()[3]) 

Next we look at codes 61 and 62. They report that someone is typing a message. The difference is that updates with code 61 notify typing in personal messages, and 62 - in conversations. Updates with code 62 look like this: [62, 000000000, 000] . The second element of the array is the id of the user who is typing the messages, and the third is the ID of the conversation. Updates with code 61 are as follows: [61, 000000000, 1] . Here the value has only the second element - the id of the user typing the message. Write the event handler:

 elif action_code == 61: user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': element[1]}).json()['response'][0] #      print(user['first_name'], user['last_name'], ' ') elif action_code == 62: user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': element[1]}).json()['response'][0] #     ,   chat = requests.get('https://api.vk.com/method/messages.getChat', params={'chat_id': element[2], 'access_token': token}).json()['response']['title'] #    print(user['first_name'], user['last_name'], '    "{}"'.format(chat)) 

In the next topic, we will write an inbound message handler and look at the message flags.

Message handling and flags
The most interesting update, I think, is the addition of messages. These updates are code 4 and return information about incoming and outgoing messages. Here is an example of an update with code 4: [4, $ts, $flag, $id, $unixtime, $text, {'title': ' ... '}] . Here $ ts is the number of the incoming event, $ flag is the message flags, $ id is the interlocutor's id or 2000000000 + conversation id (in the case of collective dialogs), $ unixtime is the time the message was added in Unix time, and the last element is the dictionary containing information about attachments, sender and changes in the settings of the conversation. For a start, let's look at where the message was added: in personal correspondence or conversation. If the message was sent in a conversation, then, as I have already written, in the $ id field there will be indicated a number resulting from the addition of 2,000,000,000 and chat_id (conversation identifier). If the message was added in personal correspondence, in the $ id field there will be the interlocutor's id, which is always less than 2,000,000,000 + chat_id of any conversation. , , $id — 2000000000 > 0, , , . , id , , 'from'. :

 elif action_code == 4: if element[3] - 2000000000 > 0: # ,       user_id = element[6]['from'] # id  chat_id = element[3] - 2000000000 # id  chat = requests.get('https://api.vk.com/method/messages.getChat', params={'chat_id': chat_id, 'access_token': token}).json()['response']['title'] #    user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'name_case': 'gen'}).json()['response'][0] #     ,   time_ = element[4] #    text = element[5] #   if text: # ,     print(time.ctime(time_).split()[3] + ':', ' ', user['first_name'], user['last_name'], '  "{}"'.format(chat) + ':', text) else: user_id = element[3] # id  user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'name_case': 'gen'}).json()['response'][0] #     ,   time_ = element[4] #    text = element[5] #   if text: # ,     print(time.ctime(time_).split()[3] + ':', ' ', user['first_name'], user['last_name'] + ':', text) 

, . Here are some of them:
  • ;
  • -;
  • , ;

, , 2. — , , ( ):
+1:
+2:
+4:
+8:
+16:
+32: .
+64: «»
+128: ( )
+256:
+512:
+65536: . ( ). <2.

. , , . , :

 summands = [] # ,      flag = element[2] #   for number in [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 65536]: #      if flag & number: # ,         summands.append(number) #  ,     

, , ,

 if 2 not in summands: 

, , :

 elif action_code == 4: summands = [] # ,      flag = element[2] #   for number in [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 65536]: #      if flag & number: # ,         summands.append(number) #  ,     if 2 not in summands: if element[3] - 2000000000 > 0: # ,       user_id = element[6]['from'] # id  chat_id = element[3] - 2000000000 # id  chat = requests.get('https://api.vk.com/method/messages.getChat', params={'chat_id': chat_id, 'access_token': token}).json()['response']['title'] #    user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'name_case': 'gen'}).json()['response'][0] #     ,   time_ = element[4] #    text = element[5] #   if text: # ,     print(time.ctime(time_).split()[3] + ':', ' ', user['first_name'], user['last_name'], '  "{}"'.format(chat) + ':', text) else: user_id = element[3] # id  user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'name_case': 'gen'}).json()['response'][0] #     ,   time_ = element[4] #    text = element[5] #   if text: # ,     print(time.ctime(time_).split()[3] + ':', ' ', user['first_name'], user['last_name'] + ':', text) 

-. , , , , , -: [[4, $ts, $flag, $id, $unixtime, $text, {'attach1_type': 'photo', 'attach1': '$photoId', 'attach2_type': 'video', 'attach2': '$videoId', 'attach3_type': 'audio', 'attach3': '$audioId', 'attach4_type': 'doc', 'attach4': '$docId', 'geo': '2_SVK-le', 'geo_provider': '4', 'title': ' ... '}] . , API . (photos.getById docs.getById) ( , ). - , . , ( ) .

 if 512 in summands: # ,   - index = 1 photos = [] #    id  docs = [] #    id  media_type = 'attach1_type' while media_type in element[6].keys(): # ,   -    media_type = element[6]['attach{}_type'.format(index)] #  ,    if media_type == 'photo': #     photos.append(element[6]['attach{}'.format(index)]) #  id    elif media_type == 'doc': #     docs.append(element[6]['attach{}'.format(index)]) #  id    index += 1 #   media_type = 'attach{}_type'.format(index) change = lambda ids, type_: requests.get('https://api.vk.com/method/{}.getById'.format(type_), params={type_: ids, 'access_token': token}).json() # ,     if photos: # ,      photos = change(', '.join(photos), 'photos') #  ,    photos   if 'response' in photos.keys(): photos = [attachment['src_xbig'] for attachment in photos['response']] #    print('   :', ', '.join(photos)) else: pass #  ,    if docs: # ,      docs = change(', '.join(docs), 'docs') #  ,    docs   if 'response' in docs.keys(): docs = [attachment['url'] for attachment in docs['response']] #    print('   :', ', '.join(docs)) else: pass #  ,    



 if text: 
, , - .

: , , , . , 6 4. :

  • : [4, $ts, $flag, $chat_id, $unixtime, '', {'source_act': 'chat_title_update', 'source_text': ' ', 'source_old_text': ' ', 'from': '$id'}]
  • : [4, $ts, $flag, $chat_id, $unixtime, '', {'attach1_type': 'photo', 'attach1': '247178624_456242629', 'source_act': 'chat_photo_update', 'from': '247178624'}]
  • : [4, $ts, $flag, $chat_id, $unixtime, '', {'source_act': 'chat_invite_user', 'source_mid': '$added_user_id', 'from': '$adder_id'}]
  • ( ): [4, $ts, $flag, $chat_id, $unixtime, '', {'source_act': 'chat_kick_user', 'source_mid': '&removed_user_id', 'from': '&remover_id'}]
  • : [4, $ts, $flag, $chat_id, $unixtime, '', {'source_act': 'chat_create', 'source_text': '', 'from': '$creator_id'}]

, :

 elif action_code == 4: if 'source_act' not in element[6].keys(): # <,  > else: source_act = element[6] if source_act['source_act'] == 'chat_title_update': #        changer_id = source_act['from'] # id ,   source_text = source_act['source_text'] #    source_old_text = source_act['source_old_text'] #    changer = requests.get('https://api.vk.com/method/users.get', params={'user_ids': changer_id, 'fields': 'sex'}).json()['response'][0] #     ,   if changer['sex']: verb = '' else: verb = '' print(changer['first_name'], changer['last_name'], verb, '   "{}"  "{}"'.format(source_old_text, source_text)) elif source_act['source_act'] == 'chat_photo_update': chat_id = element[3] - 2000000000 # id  chat = requests.get('https://api.vk.com/method/messages.getChat', params={'chat_id': chat_id, 'access_token': token}).json()['response']['title'] #    user_id = source_act['from'] # id ,   photo_id = source_act['attach1'] # id  photo = requests.get('https://api.vk.com/method/photos.getById', params={'photos': photo_id, 'access_token': token}).json() #    user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'fields': 'sex'}).json()['response'][0] #    ,   if 'error' not in photo.keys(): #        if user['sex']: verb = '' else: verb = '' print(user['first_name'], user['last_name'], verb, '  "{}" '.format(chat), photo['response'][0]['src_xbig']) else: pass #  ,      elif source_act['source_act'] == 'chat_invite_user': chat_id = element[3] - 2000000000 # id  chat = requests.get('https://api.vk.com/method/messages.getChat', params={'chat_id': chat_id, 'access_token': token}).json()['response']['title'] #    invited_id = source_act['source_mid'] # id  inviter_id = source_act['from'] # id  if invited_id == inviter_id: #         -   user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': inviter_id, 'fields': 'sex'}).json()['response'][0] #     if user['sex']: verb = '' else: verb = '' print(user['first_name'], user['last_name'], verb, '  "{}"'.format(chat)) else: inviter_user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': inviter_id, 'fields': 'sex'}).json()['response'][0] #     invited_user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': invited_id, 'name_case': 'acc'}).json()['response'][0] #     if inviter_user['sex']: verb = '' else: verb = '' print(inviter_user['first_name'], inviter_user['last_name'], verb, '  "{}"'.format(chat), invited_user['first_name'], invited_user['last_name']) elif source_act['source_act'] == 'chat_kick_user': chat_id = element[3] - 2000000000 # id  chat = requests.get('https://api.vk.com/method/messages.getChat', params={'chat_id': chat_id, 'access_token': token}).json()['response']['title'] #    removed_id = source_act['source_mid'] # id  remover_id = source_act['from'] # id  if removed_id == remover_id: #        user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': remover_id, 'fields': 'sex'}).json()['response'][0] #     if user['sex']: verb = '' else: verb = '' print(user['first_name'], user['last_name'], verb, '  "{}"'.format(chat)) else: remover_user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': remover_id, 'fields': 'sex'}).json()['response'][0] #     removed_user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': removed_id, 'name_case': 'acc'}).json()['response'][0] #     if remover_user['sex']: verb = '' else: verb = '' print(remover_user['first_name'], remover_user['last_name'], verb, '  "{}"'.format(chat), removed_user['first_name'], removed_user['last_name']) elif source_act['source_act'] == 'chat_create': chat = source_act['source_text'] #   creator_id = source_act['from'] # id  creator = requests.get('https://api.vk.com/method/users.get', params={'user_ids': creator_id, 'fields': 'sex'}).json()['response'][0] # ,     if creator['sex']: verb = '' else: verb = '' print(creator['first_name'], creator['last_name'], verb, ' "{}"'.format(chat)) 


.
: Long Poll . .

: , , KeyError 8: response = requests.get('https://{server}?act=a_check&key={key}&ts={ts}&wait=20&mode=2&version=2'.format(server=data['server'], key=data['key'], ts=data['ts'])).json()['response'] # Long Poll 20 2 . , «error 2», , &key . :

 response = requests.get('https://{server}?act=a_check&key={key}&ts={ts}&wait=20&mode=2&version=2'.format(server=data['server'], key=data['key'], ts=data['ts'])).json() #    Long Poll     20    2 try: updates = response['updates'] except KeyError: #       KeyError,   key ,     data = requests.get('https://api.vk.com/method/messages.getLongPollServer', params={'access_token': token}).json()['response'] #     continue #     ,     

! : . . , . , , , &_amp ( , ). . , sub re ( !).

 import re # <...> symbols = {'<br>': '\n', '&_amp;': '&', '&_quot;': '"', '&_lt;': '<', '&_gt;': '>', '&_tilde;': '~', '&_circ;': 'ˆ', '&_ndash;': '–', '&_mdash;': '—', '&_euro;': '€', '&_permil;': '‰'} #       for code, value in symbols.items(): text = re.sub(code, value, text) 


, , , , , . , :

 import re import time import requests token = '' #      access_token data = requests.get('https://api.vk.com/method/messages.getLongPollServer', params={'access_token': token}).json()['response'] #     while True: response = requests.get('https://{server}?act=a_check&key={key}&ts={ts}&wait=20&mode=2&version=2'.format(server=data['server'], key=data['key'], ts=data['ts'])).json() #    Long Poll     20    2 try: updates = response['updates'] except KeyError: #       KeyError,   key ,     data = requests.get('https://api.vk.com/method/messages.getLongPollServer', params={'access_token': token}).json()['response'] #     continue #     ,     if updates: # ,    for element in updates: #       action_code = element[0] if action_code == 80: #    print('    ', element[1]) #  elif action_code == 9: user_id = element[1] * -1 # id ,   user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'fields': 'sex'}).json()['response'][0] #      id = user_id timeout = bool(element[2]) #        - last_visit = element[3] #       if user['sex'] == 1: verb = ['', ''] else: verb = ['', ''] if timeout: print(user['first_name'], user['last_name'], verb[0], '   -.     :', time.ctime(last_visit).split()[3]) else: print(user['first_name'], user['last_name'], verb[1], ' .     :', time.ctime(last_visit).split()[3]) elif action_code == 8: user_id = element[1] * -1 # id ,   user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'fields': 'sex'}).json()['response'][0] #      id = user_id platform = element[2] #    last_visit = element[3] #     Unix time if user['sex'] == 1: verb = '' else: verb = '' #      if platform == 1: platform = '   web- VK' elif platform == 2: platform = '  VK  iPhone' elif platform == 3: platform = '  VK  iPad' elif platform == 4: platform = '  VK  Android' elif platform == 5: platform = '  VK  Windows Phone' elif platform == 6: platform = '  VK  Windows' elif platform == 7: platform = ' web- VK' print(user['first_name'], user['last_name'], verb, ' ', platform, '', time.ctime(last_visit).split()[3]) elif action_code == 61: user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': element[1]}).json()['response'][0] #      print(user['first_name'], user['last_name'], ' ') elif action_code == 62: user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': element[1]}).json()['response'][0] #     ,   chat = requests.get('https://api.vk.com/method/messages.getChat', params={'chat_id': element[2], 'access_token': token}).json()['response']['title'] #    print(user['first_name'], user['last_name'], '    "{}"'.format(chat)) elif action_code == 4: if 'source_act' not in element[6].keys(): summands = [] # ,      flag = element[2] #   for number in [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 65536]: #      if flag & number: # ,         summands.append(number) #  ,     if 2 not in summands: if element[3] - 2000000000 > 0: # ,       user_id = element[6]['from'] # id  chat_id = element[3] - 2000000000 # id  chat = requests.get('https://api.vk.com/method/messages.getChat', params={'chat_id': chat_id, 'access_token': token}).json()['response']['title'] #    user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'name_case': 'gen'}).json()['response'][0] #     ,   time_ = element[4] #    text = element[5] #   symbols = {'<br>': '\n', '&_amp;': '&', '&_quot;': '"', '&_lt;': '<', '&_gt;': '>', '&_tilde;': '~', '&_circ;': 'ˆ', '&_ndash;': '–', '&_mdash;': '—', '&_euro;': '€', '&_permil;': '‰'} #       for code, value in symbols.items(): text = re.sub(code, value, text) print(time.ctime(time_).split()[3] + ':', ' ', user['first_name'], user['last_name'], '  "{}"'.format(chat) + ':', text) else: user_id = element[3] # id  user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'name_case': 'gen'}).json()['response'][0] #     ,   time_ = element[4] #    text = element[5] #   symbols = {'<br>': '\n', '&_amp;': '&', '&_quot;': '"', '&_lt;': '<', '&_gt;': '>', '&_tilde;': '~', '&_circ;': 'ˆ', '&_ndash;': '–', '&_mdash;': '—', '&_euro;': '€', '&_permil;': '‰'} #       for code, value in symbols.items(): text = re.sub(code, value, text) print(time.ctime(time_).split()[3] + ':', ' ', user['first_name'], user['last_name'] + ':', text) if 512 in summands: # ,   - index = 1 photos = [] #    id  docs = [] #    id  media_type = 'attach1_type' while media_type in element[6].keys(): # ,   -    media_type = element[6]['attach{}_type'.format(index)] #  ,    if media_type == 'photo': #     photos.append(element[6]['attach{}'.format(index)]) #  id    elif media_type == 'doc': #     docs.append(element[6]['attach{}'.format(index)]) #  id    index += 1 #   media_type = 'attach{}_type'.format(index) change = lambda ids, type_: requests.get('https://api.vk.com/method/{}.getById'.format(type_), params={type_: ids, 'access_token': token}).json() # ,     if photos: # ,      photos = change(', '.join(photos), 'photos') #  ,    photos   if 'response' in photos.keys(): photos = [attachment['src_xbig'] for attachment in photos['response']] #    print('   :', ', '.join(photos)) else: pass #  ,    if docs: # ,      docs = change(', '.join(docs), 'docs') #  ,    docs   if 'response' in docs.keys(): docs = [attachment['url'] for attachment in docs['response']] #    print('   :', ', '.join(docs)) else: pass #  ,    else: source_act = element[6] if source_act['source_act'] == 'chat_title_update': #        changer_id = source_act['from'] # id ,   source_text = source_act['source_text'] #    source_old_text = source_act['source_old_text'] #    changer = requests.get('https://api.vk.com/method/users.get', params={'user_ids': changer_id, 'fields': 'sex'}).json()['response'][0] #     ,   if changer['sex']: verb = '' else: verb = '' print(changer['first_name'], changer['last_name'], verb, '   "{}"  "{}"'.format(source_old_text, source_text)) elif source_act['source_act'] == 'chat_photo_update': chat_id = element[3] - 2000000000 # id  chat = requests.get('https://api.vk.com/method/messages.getChat', params={'chat_id': chat_id, 'access_token': token}).json()['response']['title'] #    user_id = source_act['from'] # id ,   photo_id = source_act['attach1'] # id  photo = requests.get('https://api.vk.com/method/photos.getById', params={'photos': photo_id, 'access_token': token}).json() #    user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': user_id, 'fields': 'sex'}).json()['response'][0] #    ,   if 'error' not in photo.keys(): #        if user['sex']: verb = '' else: verb = '' print(user['first_name'], user['last_name'], verb, '  "{}" '.format(chat), photo['response'][0]['src_xbig']) else: pass #  ,      elif source_act['source_act'] == 'chat_invite_user': chat_id = element[3] - 2000000000 # id  chat = requests.get('https://api.vk.com/method/messages.getChat', params={'chat_id': chat_id, 'access_token': token}).json()['response']['title'] #    invited_id = source_act['source_mid'] # id  inviter_id = source_act['from'] # id  if invited_id == inviter_id: #         -   user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': inviter_id, 'fields': 'sex'}).json()['response'][0] #     if user['sex']: verb = '' else: verb = '' print(user['first_name'], user['last_name'], verb, '  "{}"'.format(chat)) else: inviter_user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': inviter_id, 'fields': 'sex'}).json()['response'][0] #     invited_user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': invited_id, 'name_case': 'acc'}).json()['response'][0] #     if inviter_user['sex']: verb = '' else: verb = '' print(inviter_user['first_name'], inviter_user['last_name'], verb, '  "{}"'.format(chat), invited_user['first_name'], invited_user['last_name']) elif source_act['source_act'] == 'chat_kick_user': chat_id = element[3] - 2000000000 # id  chat = requests.get('https://api.vk.com/method/messages.getChat', params={'chat_id': chat_id, 'access_token': token}).json()['response']['title'] #    removed_id = source_act['source_mid'] # id  remover_id = source_act['from'] # id  if removed_id == remover_id: #        user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': remover_id, 'fields': 'sex'}).json()['response'][0] #     if user['sex']: verb = '' else: verb = '' print(user['first_name'], user['last_name'], verb, '  "{}"'.format(chat)) else: remover_user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': remover_id, 'fields': 'sex'}).json()['response'][0] #     removed_user = requests.get('https://api.vk.com/method/users.get', params={'user_ids': removed_id, 'name_case': 'acc'}).json()['response'][0] #     if remover_user['sex']: verb = '' else: verb = '' print(remover_user['first_name'], remover_user['last_name'], verb, '  "{}"'.format(chat), removed_user['first_name'], removed_user['last_name']) elif source_act['source_act'] == 'chat_create': chat = source_act['source_text'] #   creator_id = source_act['from'] # id  creator = requests.get('https://api.vk.com/method/users.get', params={'user_ids': creator_id, 'fields': 'sex'}).json()['response'][0] # ,     if creator['sex']: verb = '' else: verb = '' print(creator['first_name'], creator['last_name'], verb, ' "{}"'.format(chat)) data['ts'] = response['ts'] #     

Long Poll-a, , «» «» , .
, , - . See you soon!

:

Source: https://habr.com/ru/post/335106/


All Articles