I am experiencing some strange behaviour in the Windows Universal Contacts API. Consider the following method:
public async Task TestContactStore()
{
//Fetch store and create custom contact list
ContactStore localStore = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AppContactsReadWrite);
var list = await localStore.CreateContactListAsync("Contact Store Test");
//Create new contact in custom contact list
await list.SaveContactAsync(new Contact() { Name = "Test", LastName = "Contact"});
ContactStore allAccessStore = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AllContactsReadOnly);
//Print all available contact lists
Debug.WriteLine("All Contact Lists");
var contactLists = await allAccessStore.FindContactListsAsync();
foreach (var contactList in contactLists)
{
Debug.WriteLine(contactList.DisplayName + ": " + contactList.Id);
}
//Print all available contacts
Debug.WriteLine("All Contacts");
var contacts = await allAccessStore.FindContactsAsync();
foreach (var contact in contacts)
{
Debug.WriteLine(contact.Name + " " + contact.LastName + ": " + contact.ContactListId);
}
}
It creates a contact list for my app ("Contact Store Test"). Then it saves a new Contact to this list ("Test Contact"). After this it prints all available contact lists and then all contacts.
The output is:
All Contact Lists
Hotmail: 24,5,5
Contact Store Test: 24,11,11
All Contacts
Hotmail Contact: 24,5,5
Test Contact: 24,5,5
Why does the Test Contact show up with the same ContactListId as the Hotmail-list? In the contacts app on the phone it shows up as belonging to the Contact Store Test-list. What am I missing?
I have now done some further research regarding this behavior. In the latest build 10.0.10512.1000, this behavior has changed. All ContactListId return empty string now.
When fetching contacts the way I did in my example above
var contactLists = await allAccessStore.FindContactListsAsync();
foreach (var contact in contactLists)
{
Debug.WriteLine(contactList.DisplayName + ": " + contactList.Id);
}
It seems as though the contacts in the list are always aggregated contacts (even if they are not linked in the address book). Aggregated contacts (apparently) always has empty ContactListId and AggregateId. The Id-property always matches the AggregateId-property of the corresponding raw contacts.
To get the corresponding contact list id, the raw contacts for that aggregate needs to be fetched:
var contactLists = await allAccessStore.FindContactListsAsync();
foreach (var contact in contactLists)
{
var rawContacts = await allAccessStore.AggregateContactManager.FindRawContactsAsync(aggregateContact);
foreach (var raw in rawContacts)
{
Debug.WriteLine(contactList.DisplayName + ": " + contactList.Id);
}
}
This gives expected ContactListId.
Related
I'm using Microsoft Bot Framework using the channel registration product and the REST API. I have setup the "messaging endpoint" and everything works fine for sending and receiving messages.
But I don't just want to send/receive messages. Something as simple as setting up a welcome message seems impossible because my endpoint receives nothing other than messaging events (when the bot is in the channel / conversation.)
Is there something I have missed?
I would like to setup several endpoints, or use the same, whatever, to listen to other types of events.
You need to implement in the MessageController something like these:
Pay attention in the else if. The funcition in the controller is HandleSystemMessage.
else if (message.Type == ActivityTypes.ConversationUpdate)
{
// Handle conversation state changes, like members being added and removed
// Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
// Not available in all channels
IConversationUpdateActivity update = message;
var cliente = new ConnectorClient(new System.Uri(message.ServiceUrl), new MicrosoftAppCredentials());
if (update.MembersAdded != null && update.MembersAdded.Count > 0)
{
foreach(var member in update.MembersAdded)
{
if(member.Id != message.Recipient.Id)
{
//var username = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
var username = message.From.Name;
var reply = message.CreateReply();
//string dir = System.AppDomain.CurrentDomain.BaseDirectory + "Images" + Path.DirectorySeparatorChar + "cajamar.png";
string dir = HttpRuntime.AppDomainAppPath + "Images" + Path.DirectorySeparatorChar + "cajamar.png";
reply.Attachments.Add(new Attachment(
contentUrl: dir,
contentType: "image/png",
name: "cajamar.png"
));
reply.Text = $"Bienvenido {username} al ChatBot de convenios:";
cliente.Conversations.ReplyToActivity(reply);
//var reply = message.CreateReply();
//reply.Text = $"El directorio base es: {HttpRuntime.AppDomainAppPath}";
//cliente.Conversations.ReplyToActivityAsync(reply);
}
}
}
}
I have a code to discover room occupants like this :
public List<String> getRoomOccupants() {
List<String> occupants = new ArrayList<>();
DiscoverItems discoItems = null;
DiscoverItems.Item item = null;
try {
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
discoItems = discoManager.discoverItems(zipWhipNumber+"#"+roomService);
Iterator<DiscoverItems.Item> occupantsItems = discoItems.getItems().iterator();
while(occupantsItems.hasNext())
{
item = occupantsItems.next();
occupants.add(item.getName());
System.out.println(" EntityID : " + item.getEntityID() + "\n EntityName : " + item.getName());
}
} catch (NoResponseException | XMPPErrorException
| NotConnectedException e1) {
e1.printStackTrace();
}
return occupants;
}
But the EntityID is the name of the User in the room Not the full JID. So if the user by any chance changes the name to another nickname I won't be able to find his full JID.
Can anyone tell me how to get the full JID from the room ?
Thanks.
Discovery service must to be enabled to show such infos, and depends by implementations and and MultiUserChat configuration.
Probably you are not able to get this informations with a standard Discovery Operation.
You can try to pass through MultiUserChat item like this:
RoomInfo ri = MultiUserChatManager.getInstanceFor(connection).getRoomInfo("zipWhipNumber+"#"+roomService");
List<String> jidUsers = ri.getContactJids());
or like this:
MultiUserChat muc = MultiUserChatManager.getInstance().getMultiUserChat("zipWhipNumber+"#"+roomService");
List<String> jidUsers = muc.getOccupants();
*RoomInformation* it's more or less a DiscoveryService sized on MultiUserChat. Without right configuration, getContactJids() will return null.
*getOccupants()* of a MultiUserChat reply with a List of jids, but it's possible it sends a bad-request if user didn't previously joined the given *MultiUserChat*
I can get all the contacts from a windows phone 10 device.
I want to know if a contact is local contact or an online contact.
I used this code to indicate:
ContactStore contactstore = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AllContactsReadOnly);
ContactList = await contactstore.FindContactsAsync();
if (ContactList.Count > 0)
{
ienum = ContactList.GetEnumerator();
ienum.MoveNext();
IEnumerator<ContactConnectedServiceAccount> enum2 = ienum.Current.ConnectedServiceAccounts.GetEnumerator();
enum2.MoveNext();
string id = enum2.Current.ServiceName;
but it get to the catch exception scope..
I also tried to change the access type from AllContactsReadOnly to AppContactsReadWrite and it doesn't work and does the same.
I'm using google apps script to get the responses of a specific form in an specific e-mail,
What I'm trying to do is use a google form to open support tickets, so people need fill some fields like, title, description and e-mail,
And when they submit the form, it will automatically open a ticket, but the e-mail will be always from the owner of the form, and this was a problem because we want that the person who opened the ticket receives email updates, so what I'm trying to do is this:
I put a field in the form asking the persons email, and I'm trying to put that e-mail into the reply-to...
And apparently I'm in the right way to catch that e-mail but the reply-to don't show the email that the persons filled the box, it appears an error: [Ljava.lang.Object;#34dfe075
Does any one can help me?
Here is my script:
function Initialize() {
var triggers = ScriptApp.getProjectTriggers();
for(var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
ScriptApp.newTrigger("SendGoogleForm")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit()
.create();
}
function SendGoogleForm(e)
{
try
{
var email = "support#email.com";
var form = e.namedValues;
var subject = form["Title"];
var s = SpreadsheetApp.getActiveSheet();
var columns = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
for ( var keys in columns ) {
var key = columns[keys];
if ( e.namedValues[key] && (e.namedValues[key] != "") ) {
message += key + ' :: '+ e.namedValues[key] + "\n\n";
}
}
GmailApp.sendEmail(email, subject, message, {replyTo: form["E-mail"], from: "support#email.com"});
} catch (e) {
Logger.log(e.toString());
}
}
And here is the output of this:
from: support#email.com
reply-to: [Ljava.lang.Object;#34dfe075
to: support#email.com
date: Fri, Oct 17, 2014 at 10:55 AM
subject: New Test
The reply to, is broken :(
The values returned in the e.namedValues property are arrays, so you must access them as such.
Modify your sendEmail line as follows:
GmailApp.sendEmail(email, subject, message, {replyTo: form["E-mail"][0], from: "support#email.com"});
Note the [0] array index on the form["E-Mail"] field, indicating you want the first value in that array, which will be the email address entered.
See the example next to "e.namedValues" here: https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events
I am retrieving the complete list of a friend's likes(the list of pages that the user likes) using the code bellow:
Uri ex_a = new System.Uri("https://graph.facebook.com/" + friend_id + "/likes? access_token=" + token);
WebClient WC_a = new WebClient();
WC_a.DownloadStringCompleted += new System.Net.DownloadStringCompletedEventHandler(list_likes);
WC_a.DownloadStringAsync(ex_a);
private void list_likes(object ob, DownloadStringCompletedEventArgs e)
{
JsonObject jo = new JsonObject(e.Result);
JsonArray dataArray = (JsonArray)jo["data"];
if (dataArray.ToString().Length > 2)
{
foreach (JsonObject account in dataArray)
{
list_of_likes.Add(new class_of_likes("http://graph.facebook.com/" + (string)account["id"] + "/picture?type=small", (string)account["name"]));
}
}
}
However, in October 2013, this approach will only retrieve 25 results/request.
I need to know how to create a loop to get the remaining results because facebook uses pagination like:
"paging": {
"next": "https://graph.facebook.com/user_id/likes?limit=25&offset=25&__after_id=last_page_id"
Thank you.
Get pagination section, and parse it to get next_page value, then send a query for it. There's no automatic process or get all method , otherwise spams/bots would be the happiest creature in this world.