I was helping one of my relatives with a Facebook campaign for their store.The campaign was a success as we gathered about more than 1000 new likes and a lot of queries.They were happy but I really wanted to do some more with that data like tag those people who liked if their setting allowed or send a message on messenger for arrival of new items.In short keep a track of the all that was happening.The idea is to harness the data so that maximum can be achieved next time on similar campaigns.
I wanted a something simple so that the guys at the store can do it themselves without any fiddling with api.After some trial and error i came up with this js code which can be pasted into console after opening the window which appears when you click link just on the side of like button.
/*a script to get all the people who liked the page
after a facebook campaign. A successful capmpaign will get 1000's of
likes so it will be impossible to load all the names in one go.Also the
list loads progressively with each scroll. So
the code introduces a last element in the json which you have to put in
place of "i" in the given code when you press see more button in
subsequent runs.On my fairly powerful laptop and decent internet I was
not able to get more than 350 persons without a good lag.
The value of i is calculated by trial and error as the data attributes `
before that holds something else(not required) and not the names.I hope
it will be more or less similar in all of them.
This code is to be pasted in the console once the window with all the
likes is opened.*/
var arrayName = document.querySelectorAll('[data-gt]');
var PersonObject={};
try {
for(var i = 55;i<=arrayName.length;i++ ){
var element=arrayName[i];
console.log(element);
var name=element.innerHTML;
// console.log(i)
PersonObject[("name"+i)]=name;
// console.log(PersonObject)
}
}
catch(error){
console.log("error occured at"+i)
}
finally{
PersonObject["lastElement"]=i;
var NamesJson = JSON.stringify(PersonObject)
console.log(NamesJson)
}
I tried to write the gist of code in comments.
Now my real question,this all seems so hacky and patched stuff but not elegant. Isn't there a way for business owners to actually harness this data in more systematic way without the need for any api's or any programming knowledge?
Related
I am trying to adjust the Omegle bot code in JavaScript that I have seen on the internet.
I want to use this bot to give the children on Omegle more knowledge about what other things they can do in their life instead of wasting their time on chats like that.
the issue is that the message I want to print is very long, such that Omegle will not send it (it looks like it was sent but when I tried with a friend, he didn't see anything. only when I divided the long message into small three messages.
I need to send three messages (one after another) instead of one.
the following code is what I have found, it is very simple - I just copy and paste it into the browser console and it works. - but it worked for only one message and then skip to the next person.
here is the original code:
function executeOmegle()
{
let btn = document.querySelector('.disconnectbtn')
let messageBox = document.querySelector('.chatmsg')
let sendBtn = document.querySelector('.sendbtn')
btn.click()
messageBox.innerHTML=" Hello, i am a bot"
sendBtn.click()
}
setInterval(executeOmegle,4000)
I need to send three messages, so I have modified the code like this:
but this will not work - it sends only the first message and skips to the next person.
function executeOmegle()
{
let btn = document.querySelector('.disconnectbtn')
let messageBox = document.querySelector('.chatmsg')
let sendBtn = document.querySelector('.sendbtn')
btn.click()
messageBox.innerHTML=" first message "
sendBtn.click()
messageBox.innerHTML=" Second message "
sendBtn.click()
messageBox.innerHTML=" Third message "
sendBtn.click()
}
setInterval(executeOmegle,4000)
can someone please help me to understand what I am doing wrong?
I don't have any experience in JavaScript or another platform.
I wish the code can be fixed so I will be able to use it "easily" in my browser.
thank you for your help,
Dan
PS
This is my first time on stack overflow.
I don't have any experience with JavaScript.
before I posted this question for six hours I tried to fix the code and did my research with no success.
so why do people here give bad feedback to my question as someone that didn't do his research?
or that the subject is not useful?
I am using Cloud Firestore as my database
This is my form codes on my webpage that creates a new document into my Cloud Firestore collection called "esequiz". So how do I code it in such a way that it always plus 1 to the number of documents there are in the database? And also set a limit to having the amount of documents inside the database
form.addEventListener('submit', (e) => {
e.preventDefault();
db.collection('esequiz').add({
question: form.question.value,
right: form.right.value,
wrong: form.wrong.value
});
form.question.value = '';
form.right.value = '';
form.wrong.value = '';
});
It currently works but it will show up as an auto generated ID. How do I make it carry on from the numbers, like as my current documents? When i save I would like it to read the current last document id, OR simply count the number of documents, then just + 1
Insight from Andrei Cusnir, counting documents in Cloud Firestore is not supported.
Now I am trying Andrei's approach 2, to query documents in descending order, then using .limit to retrieve the first one only.
UPDATED
form.addEventListener('submit', (e) => {
e.preventDefault();
let query = db.collection('esequiz');
let getvalue = query.orderBy('id', 'desc').limit(1).get();
let newvalue = getvalue + 1;
db.collection('esequiz').doc(newvalue).set({
question: form.question.value,
right: form.right.value,
wrong: form.wrong.value
});
form.question.value = '';
form.right.value = '';
form.wrong.value = '';
});
No more error, but instead, the code below returns [object Promise]
let getvalue = query.orderBy('id', 'desc').limit(1).get();
So when my form saves, it saves as [object Promise]1, which I don't know why it is like this. Can someone advise me on how to return the document id value instead of [object Promise]
I think it is because I did specify to pull the document id as the value, how do I do so?
UPDATED: FINAL SOLUTION
Played around with the codes from Andrei, and here are the final codes that works. Much thanks to Andrei!
let query = db.collection('esequiz');
//let getvalue = query.orderBy('id', 'desc').limit(1).get();
//let newvalue = getvalue + 1;
query.orderBy('id', 'desc').limit(1).get().then(querySnapshot => {
querySnapshot.forEach(documentSnapshot => {
var newID = documentSnapshot.id;
console.log(`Found document at ${documentSnapshot.ref.path}`);
console.log(`Document's ID: ${documentSnapshot.id}`);
var newvalue = parseInt(newID, 10) + 1;
var ToString = ""+ newvalue;
db.collection('esequiz').doc(ToString).set({
id: newvalue,
question: form.question.value,
right: form.right.value,
wrong: form.wrong.value
});
});
});
If I understood correctly you are adding data to the Cloud Firestore and each new document will have as name an incremental number.
If you query all the documents and then count how many are of them, then you are going to end up with many document reads as the database increases. Don't forget that Cloud Firestore is charging per document Read and Write, therefore if you have 100 documents and you want to add new document with ID: 101, then with the approach of first reading all of them and then counting them will cost you 100 Reads and then 1 Write. The next time it will cost you 101 Reads and 1 Write. And it will go on as your database increases.
The way I see is from two different approaches:
Approach 1:
You can have a single document that will hold all the information of the database and what the next name should be.
e.g.
The structure of the database:
esequiz:
0:
last_document: 2
1:
question: "What is 3+3?
right: "6"
wrong: "0"
2:
question: "What is 2+3?
right: "5"
wrong: "0"
So the process will go as follows:
Read document "/esequiz/0" Counts as 1 READ
Create new document with ID: last_document + 1 Counts as 1 WRITE
Update the document that holds the information: last_document = 3; Counts as 1 WRITE
This approach cost you 1 READ and 2 WRITES to the database.
Approach 2:
You can load only the last document from the database and get it's ID.
e.g.
The structure of the database (Same as before, but without the additional doc):
esequiz:
1:
question: "What is 3+3?
right: "6"
wrong: "0"
2:
question: "What is 2+3?
right: "5"
wrong: "0"
So the process will go as follows:
Read the last document using the approach described in Order and limit data with Cloud Firestore documentation. So you can use direction=firestore.Query.DESCENDING with combination of limit(1) which will give you the last document. Counts as 1 READ
Now you know the ID of the loaded document so you can create new document with ID: that will use the loaded value and increase it by 1. Counts as 1 WRITE
This approach cost you 1 READ and 1 WRITE in total to the database.
I hope that this information was helpful and it resolves your issue. Currently counting documents in Cloud Firestore is not supported.
UPDATE
In order for the sorting to work, you will also have to include the id as a filed of the document that so you can be able to order based on it. I have tested the following example and it is working for me:
Structure of database:
esequiz:
1:
id: 1
question: "What is 3+3?
right: "6"
wrong: "0"
2:
id:2
question: "What is 2+3?
right: "5"
wrong: "0"
As you can see the ID is set the same as the document's ID.
Now you can query all the documents and order based on that filed. At the same time you can only retrieve the last document from the query:
const {Firestore} = require('#google-cloud/firestore');
const firestore = new Firestore();
async function getLastDocument(){
let query = firestore.collection('esequiz');
query.orderBy('id', 'desc').limit(1).get().then(querySnapshot => {
querySnapshot.forEach(documentSnapshot => {
console.log(`Found document at ${documentSnapshot.ref.path}`);
console.log(`Document's ID: ${documentSnapshot.id}`);
});
});
}
OUTPUT:
Found document at esequiz/2
Document's ID: 2
Then you can take the ID and increase it by 1 to generate the name for your new document!
UPDATE 2
So, the initial question is about "How to store data in the Cloud Firestore with documents having incremental ID", at the moment you are facing issues of setting up Firestore with you project. Unfortunately, the new raised questions should be discussed in another Stackoverflow post as they have nothing to do with the logic of having incremental IDs for the document and it is better to keep one issue per question, to give better community support for members that are looking for a solution about particular issues. Therefore, I will try to help you, in this post, to execute a simple Node.js script and resolve the initial issue, which is storing to Cloud Firestore documents with incremental IDs. Everything else, on how to setup this in your project and how to have this function in your page, should be addressed in additional question, where you also will need to provide as much information as possible about the Framework you are using, the project setup etc.
So, lets make a simple app.js work with the logic described above:
Since you have Cloud Firestore already working, this means that you already have Google Cloud Platform project (where the Firestore relies) and the proper APIs already enabled. Otherwise it wouldn't be working.
Your guide in this tutorial is the Cloud Firestore: Node.js Client documentation. It will help you to understand all the methods you can use with the Firestore Node.js API. You can find helpful links for adding, reading, querying documents and many more operations. (I will post entire working code later in this steps. I just shared the link so you know where to look for additional features)
Go to Google Cloud Console Dashboard page. You should login with your Google account where your project with the Firestore database is setup.
On top right corner you should see 4 buttons and your profile picture. The first button is the Activate Cloud Shell. This will open a terminal on the bottom of the page with linux OS and Google Cloud SDK already install. There you can interact with your resources within GCP projects and test your code locally before using it in your projects.
After clicking that button, you will notice that the terminal will open in the bottom of your page.
To make sure that you are properly authenticated we will set up the project and authenticate the account again, even if it is already done by default. So first execute $ gcloud auth login
On the prompted question type Y and hit enter
Click on the generated link and authenticate your account on the prompted window
Copy the generated string back to the terminal and hit enter. Now you should be properly authenticated.
Then setup the project that contains Cloud Firestore database with the following command: $ gcloud config set project PROJECT_ID. Now you are ready to build a simple app.js script and execute it.
Create a new app.js file: nano app.js
Inside paste my code example that can be found in this GitHub link. It contains fully working example and many comments explaining each part therefore it is better that it is shared through GitHub link and not pasted here. Without doing any modifications, this code will execute exactly what you are trying to do. I have tested it my self and it is working.
Execute the script as: node app.js
This will give you the following error:
Error: Cannot find module '#google-cloud/firestore'
Since we are importing the library #google-cloud/firestore but haven't installed it yet.
Install #google-cloud/firestore library as follows: $ npm i #google-cloud/firestore. Described in DOC.
Execute the script again: $ node app.js.
You should see e.g. Document with ID: 3 is written.
If you execute again, you should see e.g. Document with ID: 4 is written.
All those changes should appear in your Cloud Firestore database as well. As you can see it is loading the ID of the last document, it is creating a new ID and then it creates a new document with the given arguments, while using the new generated ID as document name. This is exactly what the initial issue was about.
So I have shared with you the full code that works and does exactly what you are trying to do. Unfortunately, the other newly raised issues, should be addressed in another Stackoverflow post, as they have nothing to do with the initial issue, which is "How to create documents with incremental ID". I recommend you to follow the steps and have a working example and then try to implement the logic to your project. However, if you are still facing any issues with how to setup Firestore in your project then you can ask another question. After that you can combine both solutions and you will have working app!
Good luck!
I don't think the way you are trying to get the length of the collection is right and I am entirely not sure what is the best way to get that either. Because the method you are trying to implement will cost you a lot more as you are trying to read all the records of the collection.
But there can be alternatives to get the number you require.
Start storing the ID in the record and make the query with limit 1 and a descending sort on ID.
Store the latest number in another collection and increment that every time you create a new record, And fetch the same whenever needed.
These methods might fail if concurrent requests are being made without transactions.
I am working on a coin program to award the members for being on my site. The program I have makes two random numbers and compares them, if they are the same, you get a coin. The problem I have is someone could go in the console and get "free" coins. They could also cheat by opening more tabs or making a program to generate more coins right now which I am trying to stop. I am thinking about converting it over to php from js to stop the cheating (for the most part) but I don't know how to do this. The code in question is:
$.ajax({
type: 'post',
url: '/version2.0/coin/coins.php',
data: {Cid : cs, mode : 'updateCoins'},
success: function (msg) {
window.msg=msg;
}});
And the code for the console is that with a loop around it. In the code above, "cs" is the id of the member so by replacing it with their id would cause them to get all the coins they would want.
Should I just have an include with variable above it? But then how would I display the success message which has the current number of coins. Also, this code is in a setInterval function that repeats every 15 milliseconds.
There are multiple ways you could do this, but perhaps the simplest would be to go in your server side code - when a request comes in, you check the time of last coin update, if there ins't one, you run your coin code and save the time of this operation in their session. If there is a stored time, ensure that it is beyond the desired time. If it is, continue to the coin update. If it isn't, simply respond with a 403 or other failure code.
In pseudo code:
if (!$userSession['lastCoinTime'] || $currentTime + $delay > $userSession['lastCoinTime']) {
// coin stuff
$userSession['lastCoinTime'] = // new time
} else {
// don't give them a chance at coin, respond however you want
}
However, since you're talking about doing this check every 15ms, I would use websockets so that the connection to the server is ongoing. Either way, the logic can be comparable.
Just in case there's any uncertainty about this, definitely do ALL of the coin logic on the server. You can never trust the user for valid data coming in. The most you can trust, depending on how your authentication is setup, is some kind of secret code only they would have that would just let you know who they are, which is a technique used in place of persistent sessions. Unless you're doing that, you would rely on the session to know who the user is - definitely don't let them tell you that either!
Can I restrict the number of users in a session? Is there any option in vline.session? Please guide if this can be done by writing custom javascript.
EDIT:
Referring to https://vline.com/developer/docs/vline.js/vline.MediaSession#examples, a two party call controller is explained. I want to ask is there any way to restrict number of users in a session? There is no such option present in session's docs. Is it supported as a part of the API?
If this can be done using custom javascript, how?
As a part of my effort, I have tried to implement vline-django examples, but could not find a section in documentation that addresses this issue.
EDIT 2: The code that is working for me.
var vlineClient = (function(){
var client, session,
authToken = {{ user|vline_auth_token|safe }},
serviceId = {% vline_service_id %},
profile = {{ user|vline_user_profile|safe }};
// Create vLine client
window.vlineClient = client = vline.Client.create({"serviceId": serviceId, "ui": true});
// Add login event handler
client.on('login', onLogin);
// Do login
client.login(serviceId, profile, authToken);
function onLogin(event) {
session = event.target;
// Find and init call buttons
var callButtons = document.getElementsByClassName('callbutton');
for (var i=0; i < callButtons.length; ++i) {
initCallButton(callButtons[i]);
}
}
// add event handlers for call button
function initCallButton(button) {
var userId = button.getAttribute('data-userid');
// fetch person object associated with username
session.getPerson(userId).done(function(person) {
// update button state with presence
function onPresenceChange() {
button.setAttribute('data-presence', person.getPresenceState());
}
// set current presence
onPresenceChange();
// handle presence changes
person.on('change:presenceState', onPresenceChange);
// start a call when button is clicked
button.addEventListener('click', function() {
person.startMedia();
});
});
}
return client;
})();
How do I move ahead?
Reference: https://vline.com/developer/docs/vline.js/
if i understand correctly the OP is trying to make a multi-user chat room - this is also what i wanted to do with vline and because i wanted a/v chat as well the number of participants should obviously be capped - it appears that the term 'session' is causing the confusion here so i will refrain from using it
i worked around this by creating a fixed number of users in a db and handling authentication
myself before actually associating a visitor with one of the prepared users - so some javascript logs in each visitor as one of those existing 'anonymous' users and sets only a logged_in? flag in the db so that the next visitor will log in as the next vacant user slot and when all slots are occupied the visitor gets a "chat room full - try again later" response
probably not the most elegant solution - for example the visitor chosen usernames are stored client-side and must be re-assigned to one of the user-definable vline session vars so it can be passed along with each message and the logged_in? db flag needs to be reset when the user exits
note that this was almost a year ago so im a bit foggy on exactly what i did but my app (rails) in up on github if youre interested to fork it - also i should add that although this sort of thing wasnt strictly supported by the vline API at the time there were at least some hints that some analogous feature was being prepared for so there may be some API support for this now - i did notice since then that they have released a "chat room demo" app on github and i would expect that their implementation is more concise than mine so you may want to look at that first - my app tho does have a mostly complete UI with gravatars and collaboration is welcomed
I have a java script functions to display rating..
When user click on stars to rate I need to display the Thank you for rating message and when user refresh the page I need to display thank you for rating message instead of Rate this article.
Below is my code: could any one help me out?
<script type="text/javascript">
var sMax; // Isthe maximum number of stars
var holder; // Is the holding pattern for clicked state
var preSet; // Is the PreSet value onces a selection has been made
var rated;
// Rollover for image Stars //
function rating(num){
sMax = 0; // Isthe maximum number of stars
for(n=0; n<num.parentNode.childNodes.length; n++){
if(num.parentNode.childNodes[n].nodeName == "A"){
sMax++;
}
}
if(!rated){
s = num.id.replace("_", ''); // Get the selected star
a = 0;
for(i=1; i<=sMax; i++){
if(i<=s){
document.getElementById("_"+i).className = "on";
document.getElementById("rateStatus").innerHTML = num.title;
holder = a+1;
a++;
}else{
document.getElementById("_"+i).className = "";
}
}
}
}
// For when you roll out of the the whole thing //
function off(me){
if(!rated){
if(!preSet){
for(i=1; i<=sMax; i++){
document.getElementById("_"+i).className = "";
document.getElementById("rateStatus").innerHTML = me.parentNode.title;
}
}else{
rating(preSet);
document.getElementById("rateStatus").innerHTML = document.getElementById("ratingSaved").innerHTML;
}
}
}
// When you actually rate something //
function rateIt(me){
if(!rated){
document.getElementById("rateStatus").innerHTML = document.getElementById("ratingSaved").innerHTML + " :: "+me.title;
preSet = me;
rated=1;
sendRate(me);
rating(me);
}
}
// Send the rating information somewhere using Ajax or something like that.
function sendRate(sel){
alert("Your rating was: "+sel.title);
}
</script>
<form id="form1">
<span id="rateStatus">Rate This Article:</span>
<span id="ratingSaved">Thank you for rating.</span>
<div id="rateMe" title="Rate Me...">
<a onclick="rateIt(this)" id="_1" title="ehh..." onmouseover="rating(this)" onmouseout="off(this)"></a>
<a onclick="rateIt(this)" id="_2" title="Not Bad" onmouseover="rating(this)" onmouseout="off(this)"></a>
<a onclick="rateIt(this)" id="_3" title="Pretty Good" onmouseover="rating(this)" onmouseout="off(this)"></a>
</div>
you need to save the cookie as soon as user rate the article and check that cookie value when you load the page again to confirm if the article is already loaded or not.
Or you can also fetch the current ratings of this article from the server if you are refreshing the page anyways
You have a few options here, and what you do is going to depend on your requirements.
The big issue is one of permanence. By that, if I rate something and get the Thank You message should I see that if I look at the same page from my phone browser, or a browser on another computer? Otherwise, is it simply a message that needs to show once and you don't care if I see the "Please rate" option again later?
Based on your question about saving state between page refreshes, it sounds like your needs are more on the side of saving permanence.
Ultimately, the only way to guarantee that the rating state is saved permanently is to tie it into a user account on the backend (server) application. That way, when I view the same page from other browsers, or after a long time, then the server can lookup in the database and see that "Geuis rated this, show the Thank You message".
If you only need to show the Thank You for a short amount of time, you can store a key in a temporary cache like memcache. On each page refresh, a short piece of javascript can make an xhr request to your cache server to check if I've rated the page or not. Eventually the key falls out of the cache, so maybe in an hour or a day when I go back to see the page then I'll be prompted to rate the page. This is a semi-permanent solution, but it does work across any device or browser as long as its tied into an account.
The most fragile, but easiest, solution to implement is purely client-side. Here, your options are to either a) store the rated/not rated value in a cookie, or b) use localStorage. In either situation, it will let store the state. But cookies and localStorage are not transferred between devices or browsers. localStorage won't expire, but eventually cookies will. Also, the user can eventually decide to clear out their cookies and localStorage caches and would set the state back to "Rate me".
I'm not providing any code samples because, as I hope you can see, the answer really lies first in exactly what you're trying to accomplish along the spectrum of permanence.
And just to say it, there's really no such thing as anonymous permanence. I.e. you can't have a user to be anonymous to your site yet save their voting state permanently in a way that transfers between browsers. You have to have something akin to a server-side account to do that.