How can I scrape the member count of Facebook groups into a Google Spreadsheet? - facebook

I'm trying to get the number of members of some Facebook groups. I tried to play with the Facebook Graph API but it does not work:
function facebook(url) {
var jsondata = UrlFetchApp.fetch('http://graph.facebook.com/http://www.facebook.com/groups/449592401822610/?ref=br_rs');
var object = Utilities.jsonParse(jsondata.getContentText());
return object.shares;
}
Is it possible to do that?
Thanks for your help
[UPDATE]
Sometimes I don't have the ID of the group. I wrote this to solve the issue but it does not work...
function facebook(group) {
if (isNaN(group) == true) {
var jsondata1 = UrlFetchApp.fetch('https://graph.facebook.com/search?q='+group+'&type=group&access_token={my token}');
var object1 = Utilities.jsonParse(jsondata1.getContentText());
var id = object1.data.id;
var jsondata2 = UrlFetchApp.fetch('https://graph.facebook.com/v2.5/'+id+'/members?summary=true&access_token={my token}');
var object2 = Utilities.jsonParse(jsondata2.getContentText());
return object2.summary.total_count;
}
else {
var jsondata = UrlFetchApp.fetch('https://graph.facebook.com/v2.5/'+group+'/members?summary=true&access_token={my token}');
var object = Utilities.jsonParse(jsondata.getContentText());
return object.summary.total_count;
}
}
Any idea?

Using Graph API
https://graph.facebook.com/v2.5/449592401822610/members?summary=true&access_token={user-access_token}
you will get response like this if it is closed group
{
"data": [
],
"summary": {
"total_count": 4113
}
}
and if it is public group you will also receive members detail in data section
Good Luck
NOTE: this will only return count <5000 member. If your group is near 5000 or more than 5000 it will return 4897, 4756, or some other "random" number, but will never return more than 5000.

It looks like the URL in your code is wrong, I'm guessing it should be
http://graph.facebook.com/groups/449592401822610/?ref=br_rs

Related

Algolia sorting by geolocation in Swift

I have a problem with Algolia geolocation sorting in iOS App.
I need to display all documents in a range of 100 km from the user location.
I have multiple documents in my Indice. The document looks like this:
"document": {
"price": 5000,
"unit": "cały projekt",
"_geoloc": {
"lat": 54.5,
"lng": 18.55
},
"title": "Test ogloszenia",
"range": 0,
"activeFrom": {
"_seconds": 1597042800,
"_nanoseconds": 0
}
}
In my Algolia Ranking and Sorting, I have default set GEO.
My Swift code for sorting locations looks like below:
func getAnnouncesLocation(location: CLLocationCoordinate2D, completion: #escaping ([Announcement]) -> ()) {
var announcementsArray = [Announcement]()
let query = Query(query: "")
query.aroundLatLng = LatLng(lat: location.latitude, lng: location.longitude)
query.aroundRadius = .explicit(100000) // 100 km
collectionIndex = searchClient.index(withName: "products_geolocation")
collectionIndex.search(query) { (content, error) in
guard let content = content else {
if let error = error {
print(error.localizedDescription)
}
return
}
print("HITS \(content)")
}
}
The code doesn't return any error but the content is empty.
Another sorting like by price works perfectly. The only problem is with geolocation.
If that can help to set sorting by the price I need to add a sort-by attribute like this: document.price in Dashboard.
I am saving data to Algolia from my server in Node.js and there I am creating _geoloc value.
The latitude and longitude are hardcoded for testing so there isn’t a problem with async.
Thank you for any kind of help.
Regards
Matt
I found a bug in my project.
While sending the document to Algolia I send like this:
const record = {
objectID: doc.id,
document: document
};
where document contained all properties and also _geoloc property. After some investigation, I separated _geoloc from the document I sent it like below:
const record = {
objectID: doc.id,
document: document,
_geoloc: coordinates
};
Now everything works fine.
Cheers

How to traversal a array in JSON Response in Fiddler CustomRules.js?

In CustomRules.js
static function OnBeforeResponse(oSession: Session) {
var responseStringOriginal = oSession.GetResponseBodyAsString();
var responseJSON = Fiddler.WebFormats.JSON.JsonDecode(responseStringOriginal);
var responseJSONObject = responseJSON.JSONObject;
}
There is an array in response responseJSONObject , which are like
[
{
"id": "6661370502453447944"
},
{
"id": "333"
},
...
]
Question 1: How can I get this array's length or traversal this array?
Question 2: How can I save the javascript array to the responseJSON.JSONObject?
I tried
var newJSON = Fiddler.WebFormats.JSON.JsonDecode('{}');
var newJSONObject = newJSON.JSONObject;
newJSONObject['type'] = 'aweme_info'; //ok
newJSONObject['aweme_length'] = 3; //ok
newJSONObject['k']['kell'] = 'good'; //failed
var tpArray = new Array();
for (var i = 1; i < 3; i++) {
tpArray.push(i);
}
var jsonString = JSON.stringify(tpArray); // failed
// how can I convert tpArray to JSON?
Question 3: Where can I find any documentation about this object "Fiddler.WebFormats.JSON", like what method and properties it have.
I tried several ways but nothing works and I can't using the JSON.parse() function in this script.
I also google for the documents of this object (Fiddler.WebFormats.JSON) and found nothing.
Thank you very much and welcome reply any infomation.
https://learn.microsoft.com/en-us/dotnet/api/system.collections.hashtable?view=netframework-4.7.2
This script syntax is very similar to DOTNET. You can read the doc above to find the answers.

Swift Unwrapping optional class variable yields failure

In my code I have two classes: Reviews and BlogPosts:
class Review {
var author = ""
var stars = 0
}
class BlogPost {
var title = ""
var body = ""
var author = ""
var review: Review?
}
The review variable in BlogPost is optional, since not all blog posts might have a review.
I have a function which prints the amount of stars of a post:
func checkForPostStars(post: BlogPost) {
if let review = post.review {
print("\"\(post.title)\" has: \(review.stars) stars")
} else {
print("There is no review for the post.")
}
}
I then create two blog posts. The first one has no review, meaning that the function should print "There is no review for the post". For the other review I add an author and a star amount, but when I run the function it will still print "There is no review for the post".
var firstPost = BlogPost()
firstPost.title = "Famous developer has died!"
firstPost.body = "Lorem ipsum"
firstPost.author = "Riccardo Perego"
var secondPost = BlogPost()
secondPost.title = "iOS 12 is finally out!"
secondPost.body = "Lorem ipsum"
secondPost.author = "Riccardo Perego"
secondPost.review?.author = "John"
secondPost.review?.stars = 4
checkForPostStars(post: firstPost)
checkForPostStars(post: secondPost)
I have discovered that I can fix the issue by adding secondPost.review = Review() nevertheless, I would like the compiler to do it automatically as soon as it sees that I set a value for stars or author. Thanks.
The problem lies within these 2 lines:
secondPost.review?.author = "John"
secondPost.review?.stars = 4
The review is not initialized. It's like you would set some value to nil and expect it's properties to live even if it doesn't work... That's why the ? is there.
You should add constructor to the Review:
class Review {
var author: String
var stars: Int
init(author: String = "", stars: Int = 0) {
self.author = author
self.starts = stars
}
}
Also it is good practice not to assign the variables on class level scope, rather use it in initialiser.
Simply the problem is that you do not create Review instance, so you cannot add properties to it... you should handle it like this:
secondPost.review = Review(authoer: "John", stars: 4)
Also, for performance reasons, you should make the Review object struct instead of class...
So if you create a struct instead, Swift figures out the initialiser for you and life's even better:
struct Review {
var author: String
var stars: Int
}

Google sheets API script

I'm trying to use the following REST API within one of my sheets, and am struggling to return a specific result from the JSON array (first timer here!!)
Here's what I have so far....
function Bittrex_API() {
// Call the Bittrex API for market rates
var response = UrlFetchApp.fetch(
"https://bittrex.com/api/v1.1/public/getmarketsummaries");
// Parse the JSON reply
var json = response.getContentText();
var data = JSON.parse(json);
Logger.log(data);
}
This returns the full array in the Logs, but how do I get it to pull all information from a specific result in the array?
I can return specific results from the first section, by calling the index position "0" as follows:
function Bittrex_API() {
// Call the Bittrex API for market rates
var response = UrlFetchApp.fetch(
"https://bittrex.com/api/v1.1/public/getmarketsummaries");
// Parse the JSON reply
var json = response.getContentText();
var data = JSON.parse(json);
Logger.log(data["result"][0]);
}
But how do I specify a different section of the array without using the index number??
i.e. I want to return all information relating to MarketName=BTC-RCN.
There is nothing wrong with using the index nunber. Whatever notation you use you will need to find BTC-RCN. You can loop through the index number to find it. This will find it and return the results to Sheet1:
function Bittrex_API() {
// Call the Bittrex API for market rates
var response = UrlFetchApp.fetch(
"https://bittrex.com/api/v1.1/public/getmarketsummaries");
// Parse the JSON reply
var json = response.getContentText();
var data = JSON.parse(json);
var lgt=data.result.length
for(i=0;i<lgt;i++){
var test=data["result"][i]["MarketName"]
if(test=="BTC-RCN"){
var num=i;
}
}
var MarketName=data["result"][num]["MarketName"]
var High=data["result"][num]["High"]
var Low=data["result"][num]["Low"]
var Volume=data["result"][num]["Volume"]
var Last=data["result"][num]["Last"]
var BaseVolume=data["result"][num]["BaseVolume"]
var TimeStamp=data["result"][num]["TimeStamp"]
var Bid=data["result"][num]["Bid"]
var Ask=data["result"][num]["Ask"]
var OpenBuyOrders=data["result"][num]["OpenBuyOrders"]
var OpenSellOrders=data["result"][num]["OpenSellOrders"]
var PrevDay=data["result"][num]["PrevDay"]
var Created=data["result"][num]["Created"]
var ss=SpreadsheetApp.getActiveSpreadsheet()
var s=ss.getSheetByName("Sheet1")
s.getRange("A1").setValue("MarketName")
s.getRange("B1").setValue(MarketName)
s.getRange("A2").setValue("High")
s.getRange("B2").setValue(High)
s.getRange("A3").setValue("Low")
s.getRange("B3").setValue(Low)
s.getRange("A4").setValue("Volume")
s.getRange("B4").setValue(Volume)
s.getRange("A5").setValue("Last")
s.getRange("B5").setValue(Last)
s.getRange("A6").setValue("BaseVolume")
s.getRange("B6").setValue(BaseVolume)
s.getRange("A7").setValue("TimeStamp")
s.getRange("B7").setValue(TimeStamp)
s.getRange("A8").setValue("Bid")
s.getRange("B8").setValue(Bid)
s.getRange("A9").setValue("Ask")
s.getRange("B9").setValue(Ask)
s.getRange("A10").setValue("OpenBuyOrders")
s.getRange("B10").setValue(OpenBuyOrders)
s.getRange("A11").setValue("OpenSellOrders")
s.getRange("B11").setValue( OpenSellOrders)
s.getRange("A12").setValue("PrevDay")
s.getRange("B12").setValue(PrevDay)
s.getRange("A13").setValue("Created")
s.getRange("B13").setValue(Created)
}

xpages typeahead autocomplete

i couldnt do aautocopmlete edit box. i want to take names from another database. i wrote my code to typeahead's value list. but it dont work. i am using same server but different database.anybody help me ? here is my code:
//Getting the view containing a document for each of the employees
var searchView:NotesView = session.getDatabase("servername","test/application name.nsf")
.getView("viewname");
// Creating a Lotus Notes search query. Notice the reference to lupkey!
var query = "(FIELD Ad Soyad CONTAINS *" + lupkey +"*)";
// Creating an array to store hits in
var searchOutput:Array = ["å","åå"];
// Doing the actual search
var hits = searchView.FTSearch(query);
var entries = searchView.getAllEntries();
var entry = entries.getFirstEntry();
//Sort the array manually, since Notes doesn't want to sort them alphabetically
for (i=0; i<hits; i++) {
searchOutput.push(entry.getColumnValues()[0]);
entry = entries.getNextEntry();
}
searchOutput.sort();
// Build the resulting output HTML code
var result = "<ul><li><span class='informal'>Suggestions:</span></li></ul>";
var limit = Math.min(hits,20);
for (j=0; j<limit; j++) {
var name = searchOutput[j].toString();
var start = name.indexOfIgnoreCase(lupkey)
var stop = start + lupkey.length;
//Make the matching part of the name bold
name = name.insert("</b>",stop).insert("<b>",start);
result += "<li>" + name + "</li>";
}
result += "</ul>";
return result;
There are plenty of issues with your code:
the query can't return any result since your field has a space in it
Do you really need an FTSearch to return values and not a sorted view?
the typeahead -as the name suggest- presents values that match left to right and not somewhere substring. If you need that you need to roll your own typeahead function using Ajax
The typeahead function doesn't take a parameter, so your lupkey doesn't go anywhere. The function needs to return all values and XPages will do the matching
Instead of copying one by one into an array for sorting, copy the returning Vector() into a TreeSet(). This is one line, sorts it and removes duplicates
To get it working check this example based on dojo, previously asked here. You will need the REST control
i do it like that
var directoryTypeahead = function (searchValue:string) {
// update the following line to point to your real directory
//var directory:NotesDatabase = session.getDatabase(database.getServer(), "names.nsf");
var directory:NotesDatabase = session.getDatabase(database.getServer(), "org/test.nsf");
var allUsers:NotesView = directory.getView("SVFHP2");
var matches = {};
var includeForm = {
Person: true,
Group: true
}
searchValue = searchValue.replace("I","i")
var matchingEntries:NotesViewEntryCollection = allUsers.getAllEntriesByKey(searchValue, false);
var entry:NotesViewEntry = matchingEntries.getFirstEntry();
var resultCount:int = 0;
while (entry != null) {
var matchDoc:NotesDocument = entry.getDocument();
var matchType:string = matchDoc.getItemValueString("Form");
//if (includeForm[matchType]) { // ignore if not person or group
var fullName:string = matchDoc.getItemValue("Name").elementAt(0) + " " + matchDoc.getItemValue("Title").elementAt(0);
if (!(matches[fullName])) { // skip if already stored
resultCount++;
var matchName:NotesName = session.createName(fullName);
matches[fullName] = {
cn: matchName.getCommon(),
photo: matchDoc.getItemValueString("Photo"),
job: matchDoc.getItemValueString("sum"),
email: matchDoc.getItemValueString("email"),
}
}
// }
/*if (resultCount > 15) {
entry = null; // limit the results to first 10 found
}
else {*/
entry = matchingEntries.getNextEntry(entry);
//}
};
}