I have figured out how to send tweets and how to return the users Home Timeline.
To return the timeline you just do the following :-
timeline = t4j.getHomeTimeline();
( where t4j is the twitter4j java object )
However in order to automate this ( i.e. call the timeline every 5 mins) i need to pass the last twitter ID to getHomeTimeline.
In the twitter4j JAVA examples there is the following java :-
Paging paging = new Paging(2, 40);
List statuses = twitter.getHomeTimeline(paging);
so I tried :-
timeline = t4j.getHomeTimeline(sid); throws a method not found or overloaded error
timeline = t4j.getHomeTimeline(1, sid); throws a method not found or overloaded error
sid = JavaCast("long", session.homeTimeline_sid);
timeline = t4j.getHomeTimeline(sid); throws a method not found or overloaded error
timeline = t4j.getHomeTimeline().Paging('sinceID',sid); Again an error
Does anyone know the correct syntax for this ???
I figured out the syntax :-
sid = JavaCast("long", session.homeTimeline_sid);
tPaging = createObject("java", "twitter4j.Paging");
tPaging.setSinceId(sid);
timeline = t4j.getHomeTimeline(tPaging);
Related
I've been using Instagram's undocumented API https://www.instagram.com/<user>/?__a=1 to get a public user feed on a website. Since a while now, this is not working anymore, probably because Facebook removed it. Is there an other way to get the data of an instagram account in a easy way?
I built a small server which does that transformation. You'll receive the instagram data as before with ?__a=1 (as JSON ) - have fun 😊
https://www.instapi.io/u/<username>
https://www.instapi.io/u/appwithus
EDIT 12/2020: Unfortunately the service is no longer available
Edit 15/03 NOT WORKING ANYMORE Seems like instagram changed again their API, now it gives a CORS error.
As of 2 february 2021, I have found a solution
Instead of using https://www.instagram.com/username/?__a=1 which it asks for a login.
Justing adding a /channel seems to make it work, like so:
https://www.instagram.com/username/channel/?__a=1
There is a JSON data in https://www.instagram.com/<user>/.
You can use regexp to find what you need.
Sample
// This regexp gets widest possible dict around "profile_pic_url"
// but inside tag <script type="text/javascript">...</script>
let r = new RegExp('<script type="text\/javascript">' +
'([^{]+?({.*profile_pic_url.*})[^}]+?)' +
'<\/script>');
let source = document.documentElement.outerHTML;
let jsonStr = source.match(r)[2];
let data = JSON.parse(jsonStr);
console.log('data', data);
let oldVariantOfData = data['entry_data']['ProfilePage'][0];
console.log('oldVariantOfData', oldVariantOfData);
The same response is attached in the html response of the profile url, I perform this temporal solution (when I can't use the API) in python:
url_recent_media = 'https://www.instagram.com/%s/' % instagram_id
response = urllib2.urlopen(url_recent_media)
insta_html = response.read()
insta_html_split = insta_html.split('"ProfilePage":[')
if len(insta_html_split) > 1:
insta_html_split_2 = insta_html_split[1].split(']},"gatekeepers"')
if len(insta_html_split_2) > 1:
json_dict = json.loads(insta_html_split_2[0])
I hope this help you.
you can try without using instagram API.
import json, urllib2
img_dicts = []
url = 'https://www.instagram.com/{}/'.format(instagram_username)
try:
r = urllib2.urlopen(url, timeout=10.0)
instagram_html = r.read()
instagram_html_data = instagram_html.split('"ProfilePage":[')
if len(instagram_html_data) > 1:
instagram_html_final_data = instagram_html_data[1].split(']},"gatekeepers"')
if len(instagram_html_final_data) > 1:
json_dict = json.loads(instagram_html_final_data[0])
media = json_dict['graphql']['user']['edge_owner_to_timeline_media']['edges']
for obj in media:
img_dicts.append({
'id': obj['node']['id'],
'caption': obj['node']['edge_media_to_caption']['edges'][0]['node']['text'],
'imgurl_standard': obj['node']['display_url'],
'imgurl_lower': obj['node']['thumbnail_resources'][4]['src'],
'imgurl_thumb': obj['node']['thumbnail_resources'][3]['src']
})
img_dicts will give you images in different quality and caption of instagram post.
I'm working on converting my old Sitecore (< 8) code to work with Sitecore EXM. I'm having a hard time adding users to Recipient Lists from code. The answers in this post: Sitecore 8 EXM add a contact to list from listmanager don't answer my questions completely, and since I cannot comment, I've decided to start a new topic.
My first problem is that my EcmFactory.GetDefaultFactory().Bl.RecipientCollectionRepository.GetEditableRecipientCollection(recipientListId) gives a compilation error on the RecipientCollectionRepository, it says it does not exist. So I've used slightly different code. My code now, is as follows:
var contactRepository = new ContactRepository();
var contactName = this.Email.Text;
var contact = contactRepository.LoadContactReadOnly(contactName);
contact = contactRepository.CreateContact(Sitecore.Data.ID.NewID);
contact.Identifiers.AuthenticationLevel = Sitecore.Analytics.Model.AuthenticationLevel.None;
contact.System.Classification = 0;
contact.ContactSaveMode = ContactSaveMode.AlwaysSave;
contact.Identifiers.Identifier = contactName;
contact.System.OverrideClassification = 0;
contact.System.Value = 0;
contact.System.VisitCount = 0;
var contactPreferences = contact.GetFacet<IContactPreferences>("Preferences");
contactPreferences.Language = "nl-NL";
var contactEmailAddresses = contact.GetFacet<IContactEmailAddresses>("Emails");
contactEmailAddresses.Entries.Create("test").SmtpAddress = this.Email.Text;
contactEmailAddresses.Preferred = "test";
var contactPersonalInfo = contact.GetFacet<IContactPersonalInfo>("Personal");
contactPersonalInfo.FirstName = contactName;
contactPersonalInfo.Surname = "recipient";
if (recipientList != null)
{
var xdbContact = new XdbContactId(contact.ContactId);
if (!recipientList.Contains(xdbContact, true).Value)
{
recipientList.AddRecipient(xdbContact);
}
contactRepository.SaveContact(contact, new ContactSaveOptions(true, null));
}
So the recipientList is found, and the first time I add a contact to it, it increases the "Recipients" to 1 (checked using the /sitecore/system/List Manager/All Lists/E-mail Campaign Manager/Custom/RecipientList).
I also have a message which has this Opt-in recipient list, but when I check that message, it says it will be sent to 0 subscribers.
Any thoughts on this?
See this article listing known issues in Sitecore EXM:
https://kb.sitecore.net/articles/149565
"The recipient list shows "0" total recipients after recipients have been subscribed to the list. (62217)"
I got around this in a sandbox environment by adding a simple list (from csv, one contact) to the message. This upped the total recipient count from 0 to 1 which allows the message to be activated. All recipients in the composite list were sent a message.
Do you have a distributed environment? If so the RecipientCollectionRepository will not work as it is only available on a Content Management server. You could try using the ClientApi:
ClientApi.UpdateSubscriptions(RecipientId recipientId, string[] listsToSubscribe, string[] listsToUnsubscribe, string managerRootId, bool confirmSubscription)
and just add the id of the list you want to subscribe people to in the first string array.
Just a quick note with this option, listToUnsubscribe does not actually remove a contact from a list. You are meant to pass through the ID of the opt out list. This basically excludes them from any future emails. One draw back is that you will no longer be able to resubscribe them.
If this does not work for you you will need to create your own API between your CD server and your CM server where the CM server uses the recipientCollectionRepository to subscribe and unsubscribe
I am using parse sdk for backend management for my game. For user signup/login parse api ask for parameter tokenExpiration. I have no idea how to get it from facebook unity sdk.
https://www.parse.com/docs/unity_guide#fbusers-signup
Task<ParseUser> logInTask = ParseFacebookUtils.LogInAsync(accessToken, userId, tokenExpiration);
Got this problem solved by myself using debug_token. Here is the right code on how to do it.
FB.API("/debug_token?input_token="+FB.AccessToken+"&access_token="+FB.AccessToken,Facebook.HttpMethod.GET, AccessTokenCallback);
function AccessTokenCallback(response:String){
Debug.Log(response);
var access = JSON.Parse(response);
Debug.Log("Token Expiration is: "+access["data"]["expires_at"].Value);
}
If you will print the response it will give you a JSON with all information about the access token and you can take whatever info you need about an access token.
Open FacebookAccessTokenEditor.cs and replace original line 81:
formData["batch"] = "[{\"method\":\"GET\", \"relative_url\":\"me?fields=id\"},{\"method\":\"GET\", \"relative_url\":\"app?fields=id\"}]";
by these two:
string getExpiresAt = ",{\"method\":\"GET\", \"relative_url\":\"debug_token?input_token="+accessToken+"\"}";
formData["batch"] = "[{\"method\":\"GET\", \"relative_url\":\"me?fields=id\"},{\"method\":\"GET\", \"relative_url\":\"app?fields=id\"}"+getExpiresAt+"]";
Then open FacebookEditor.cs and in method MockLoginCallback, just before line 220:
isLoggedIn = true;
insert the following lines:
var tokenData = (Dictionary<string, object>)MiniJSON.Json.Deserialize(responses[2]);
var expiresAt = (long)((Dictionary<string, object>)tokenData["data"])["expires_at"];
accessTokenExpiresAt = FromTimestamp((int)expiresAt);
also, add the missing function FromTimestamp which you can copy from AndroidFacebook.cs or IOSFacebook.cs or jus copy from here:
private DateTime FromTimestamp(int timestamp)
{
return new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(timestamp);
}
Finally, you can call the parse method like you do on IOS or Android or Web:
Task<ParseUser> logInTask = ParseFacebookUtils.LogInAsync(FB.UserId, FB.AccessToken, FB.AccessTokenExpiresAt);
Note: As I have worked on the code, I am not sure of the original line numbers, but I think they are correct. Also, this does not reflect the best coding practices, but since it is used only in a debug context, they're good enough for me.
I am using CFML and Twitter4j to return timelines and lists.
I want to return the data from a call to lookupUsers(java.lang.String[] screenNames)
via Twitter4j.
I have tried the :-
strList = createObject("java", "java.util.ArrayList");
strList.add(strOriginUser);
originUser = t4j.lookupUsers(strList);
And :-
strUserString = JavaCast("String", strOriginUser);
originUser = t4j.lookupUsers(strUserString);
I know the t4j Object is working as I already use it to get timelines etc but here it is for completeness :-
public function init_twitter() {
//CONFIGURE twitter4j
configBuilder = createObject("java", "twitter4j.conf.ConfigurationBuilder");
configBuilder.setOAuthConsumerKey(#application.twitter_consumer_key#);
configBuilder.setOAuthConsumerSecret(#application.twitter_consumer_secret#);
configBuilder.setOAuthAccessToken(#application.twitter_access_token#);
configBuilder.setOAuthAccessTokenSecret(#application.twitter_access_token_secret#);
configBuilder.setIncludeEntitiesEnabled(true);
configBuilder.setJSONStoreEnabled(true);
config = configBuilder.build();
twitterFactory = createObject("java", "twitter4j.TwitterFactory").init(config);
variables.t4j = twitterFactory.getInstance();
return this;
}
The twitter4j documentations is:-
ResponseList<User> lookupUsers(java.lang.String[] screenNames) throws TwitterException
Return up to 100 users worth of extended information, specified by either ID, screen name, or combination of the two. The author's most recent status (if the authenticating user has permission) will be returned inline.
This method calls http://api.twitter.com/1.1/users/lookup.json
Parameters:
screenNames - Specifies the screen names of the users to return.
Returns:
users
It looks like you are trying to pass an ArrayList object into lookupUsers but that method only accepts String[] (an array of Strings) as an argument. So unless CFML does the conversion, I don't think it's going to work.
From a cursory glance at the ColdFusion docs, it looks like CFML can implicitly convert a CFML Array to a Java array, so perhaps the following would work:
screenNames = arrayNew(1);
screenNames[1] = 'Fry';
originUser = t4j.lookupUsers(screenNames);
Alternatively, if you want to keep on using a list there is an ArrayList#toArray(T[]) which could be useful, although I can't say how useful that would be in the CFML.
N.B. Please excuse my CFML code snippet.
I'm trying to resolve/close Dynamics CRM4 cases/incidents through webservices.
A single SetStateIncidentRequest is not enough and returns a Server was unable to process request error message. I think it has something to do with active workflows that trigger on case's attribute changes. I don't know if there's anything else preventing the request to work.
Since it is possible to close those cases through the GUI, I guess there's a "correct" set of steps to follow in order to achieve it through CrmService; unfortunately, I've been googleing it for a while without finding what I want. Could anybody help me, please?
To resolve a case in CRM (in VB.NET), I do the following:
Try
Dim activity As New incidentresolution
Dim closeRequest As New CloseIncidentRequest
Dim closeResponse As New CloseIncidentResponse
Dim strErrors As String = String.Empty()
activity.incidentid = New Lookup
activity.incidentid.type = EntityName.incident.ToString
activity.incidentid.Value = //[GUID OF INCIDENT]
activity.ownerid = New Owner
activity.ownerid.type = EntityName.systemuser.ToString
activity.ownerid.Value = //[GUID OF USER PERFORMING ACTION]
activity.statecode = New IncidentResolutionStateInfo
activity.statecode.Value = 1 //Resolved
activity.statuscode = New Status
activity.statuscode.Value = 5 //Problem Solved
closeRequest.IncidentResolution = activity
closeRequest.Status = 5 //Problem Solved
// IF REQUIRED:
activity.timespent = New CrmNumber
activity.timespent.Value = //[INTEGER REPRESENTING No. OF MIN SPENT ON CASE]
closeResponse = objCrm.Execute(closeRequest)
Catch ex As System.Web.Services.Protocols.SoapException
Dim root As XmlElement = ex.Detail
strErrors = strErrors & vbCrLf & vbCrLf & root.ChildNodes(0).ChildNodes(3).InnerText
Return False
End Try
Here's a tip - catch the SoapException and examine the Detail.OuterXML property and you will get a more detailed error message. It's possible you're not building your request correctly.
Indeed, I didn't know that there exists a CloseIncidentRequest class to use with the CrmService.Execute() method. Most probably the SetStateIncidentRequeset won't work because it's expected that incident resolutions are created that way. Pity that names for classes and actions aren't used consistently (case/incident, resolution/closing)...