📜 ⬆️ ⬇️

Streaming api A small example in PHP

In the summer, there was a contest from VKontakte on the topic “Streaming API Contest”. I decided to participate, but since I couldn’t find a normal idea for the implementation of all the features of the Streaming API, I decided to just output the recordings according to the specified rules.

More about the rules
A rule is a set of keywords whose presence in the text of an object means that the object will fall into the stream. If words are specified without double quotes, the search is simplified (all word forms, case insensitive). To search by exact entry (taking into account the register, word forms, etc.) each word must be specified in double quotes.

More detail here .

At first I thought about implementing everything on Node.Js, but then, in order not to waste time setting it up on a VPS server, I decided to use PHP.
')
I decided to give the entire logic of the project to the client, on the server only small settings for working with the VK API and the analyzer.

Let's start with the interesting - the main thing:

//    var socket = new WebSocket("wss://streaming.vk.com/stream?key=" + window.key); var close_connect = ge("close_connect"); /* *      */ socket.onmessage = function(event) { var incomingMessage = event.data; var loading = document.getElementById("loading_text"); var preview = document.getElementById("preview_text"); var serf = document.getElementById("serf"); loading.classList.add("none"); preview.classList.add("none"); serf.classList.remove("none"); parser(event.data); //     console.log(event.data); }; socket.onclose = function(event) { if (event.wasClean) { console.warn('  '); } else { console.warn(' '); } console.info(': ' + event.code + ' : ' + event.reason); var loading = ge("loading_text"); if (event.code == 1006) { loading.innerHTML = "     ,     .<br/>  -   .   . <br/>   - " + event.code; } else { loading.innerHTML = "-  -   ... <br/>   - " + event.code; } }; socket.onerror = function(error) {}; //close connect close_connect.addEventListener("click", function() { socket.close(); close_connect.innerHTML = "  ."; ge("analiz_block").classList.remove("none"); }, false); 

As it became clear from the code above, the site has one session for all users, i.e. while someone is already sitting and parsing the rules, another will not get access to the site.

There is a minus here
While one person creates the rules and receives news, another can see these same rules and delete them. I noticed it late, after the contest, so I did not fix it.

Next, we analyze the main function parser (event.data) . I love templates, they are easy to manage and easy to interact with.

Lot of code
 var parser = function(json) { var response = JSON.parse(json); console.log(response); var code = response.code; console.log(code); if (code != 100) return; var tpl_block = document.getElementById("tpl"); var tpl = tpl_block.innerHTML; var main_tpl = tpl_block.innerHTML; var content = document.getElementById("main").innerHTML; var main = document.getElementById("main"); var time = response.event['creation_time']; var date = new Date(time); var type; var cnt = ge("cnt"); var cnt_value = +cnt.innerHTML; cnt.innerHTML = cnt_value + 1; var creation_time = timestampToDate(response.event['creation_time'] * 1000); if (response.event['event_type'] == "post") { type = ""; count['post'] = ++count['post']; } else if (response.event['event_type'] == "comment") { type = ""; count['comment'] = ++count['comment']; } else if (response.event['event_type'] == "share") { type = ""; count['share'] = ++count['share']; } var photo_context; if (response.event.attachments) { //image if (response.event.attachments[0].type == "photo") { photo_context = '<div class="body-img"><img alt="image" src="' + response.event.attachments[0].photo['photo_604'] + '" /></div>'; } else { photo_context = ""; } } else { photo_context = ""; } tpl = tpl.split("{event_type}").join(type); tpl = tpl.split("{text}").join(response.event['text']); tpl = tpl.split("{url}").join(response.event['event_url']); tpl = tpl.split("{date}").join(creation_time); tpl = tpl.split("{photo}").join(photo_context); tpl = tpl.split("{type}").join(response.event['event_type']); tpl = tpl.split("{cnt}").join(cnt_value+1); tpl = tpl.split("\"").join("'"); if (filter.top) main.innerHTML = tpl + "" + content; else main.innerHTML = content + "" + tpl; //post_id if (response.event['event_type'] != "comment") { var post_owner_id = response.event.event_id['post_owner_id']; var post_id = response.event.event_id['post_id']; var wall_id = post_owner_id + "_" + post_id; array_post_id.push(wall_id); } //limit if (cnt_value + 1 >= +filter.limit) { socket.close(); close_connect.innerHTML = "  ."; ge("analiz_block").classList.remove("none"); } } 


The template itself:

 <section id="tpl" class="none"> <div class="template-container block-md_" data-type="{type}" data-num="{cnt}"> <div class="template-header"> <div class="template-title" id="tpl_title"><b>{event_type}</b></div> </div> <div class="template-body"> <div data-body-text="data-body-text-{cnt}">{text}</div> {photo} </div> <div class="template-footer flex"> <div>  - {date}</div> <div> <a href="javascript: return;" class="none button-footer-post button-spam" onclick="spam.addMSG({cnt})"></a> <a href="{url}" class="button-footer-post" target="_blank"> </a> </div> </div> </div> </section> 

In the code above occurs:

1. Pars json with information about the records (comment, repost or publication)
2. Pars a template for information we received from json

One template for three types of publication. Conveniently.

The project is working, the records are displayed, everything is gorgeous, but boring. To hand over such a project to a competition is the same thing as not to take it. Therefore, it was decided to write a small filter on the records, which would be able to show small statistics. I took as a basis information on the number of records, total coverage, the “Like” button and repost, as well as the average age of the audience reached and the percentage of the sex.

Code analysis
 var analiz = { start: function() { // if (count['post'] == 0 && count['comment'] == 0 && count['share'] == 0) { alert("  .  -   ."); return; } var url = "/vk-competition/VKanaliz.php"; var loading = ge("loading_sp"); var button = ge("btn_analiz"); var analiz_stats = ge("analiz_stats"); loading.classList.remove("none"); button.classList.add("none"); ajax.post({ url: url, data: "post_id=" + array_post_id.join(","), callback: function(data) { var resp = JSON.parse(data); if (resp.error) { alert(resp.error); return; } else { var count_likes_all_ = resp.response.count_likes_all; var count_share_all_ = resp.response.count_share_all; var count_views_all_ = resp.response.count_views_all; var analiz_posts = ge("analiz_post"); var analiz_share = ge("analiz_share"); var analiz_comments = ge("analiz_comments"); var analiz_likes = ge("analiz_likes"); var analiz_views = ge("analiz_views"); var analiz_reposts = ge("analiz_reposts"); var analiz_years = ge("analiz_years_"); var analiz_sex = ge("analiz_sex"); var percent_sex_m, percent_sex_w; if (resp.response.percent_sex_w == "-") percent_sex_w = 0; else percent_sex_w = resp.response.percent_sex_w; if (resp.response.percent_sex_w == "-") percent_sex_m = 0; else percent_sex_m = 100 - +percent_sex_w; console.log("spam " + resp.response.spam + "%"); //insert data analiz_posts.innerHTML = count['post']; analiz_share.innerHTML = count['share']; analiz_comments.innerHTML = count['comment']; analiz_likes.innerHTML = count_likes_all_; analiz_views.innerHTML = "≈" + count_views_all_; analiz_reposts.innerHTML = count_share_all_; analiz_sex.innerHTML = percent_sex_w + "%, " + percent_sex_m + "%"; analiz_years.innerHTML = resp.response.middle_years; //show stats loading.classList.add("none"); analiz_stats.classList.remove("none"); } } }); } } 


VKanaliz.php - a file that returns data in json. Its contents can be viewed here .

What was the result? As a result, a small project came out that allows analyzing the publication, its scope and feedback. Already better than before.

→ See live example here
→ Source code is available on GitHub

All good!

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


All Articles