Error when including a contact to group using People API - google-apps-script

I need to add a single contact to all the below groups. I tried to add the contact to groups one by one, however when I tested with the first group the API gave an error
GoogleJsonResponseException: API call to people.contactGroups.members.modify failed with error: Cannot add contacts to deprecated system contact group resource name "contactGroups/chatBuddies".
I want to add the created contact to all these groups
contactGroups/chatBuddies
contactGroups/all
contactGroups/friends
contactGroups/coworkers
contactGroups/family
contactGroups/blocked
I dont see anywhere that these groups are depreciated
I have tried with
var b = {
"phoneNumbers": [{
"type": "mobile",
"value": "09876543210"
}],
"names": [{
"unstructuredName": "Test account"
}],
"urls": [],
"addresses": [{
"type": "work",
"formattedValue": "0"
}],
"organizations": [{
"name": "Organisation"
}],
"emailAddresses": [{
"type": "home",
"value": "abcd#gmail.com"
}]
}
function doGet(e) {
var resource = People.People.createContact(b);
var id = resource.metadata.sources[0].id;
var contactResourceName = resource["resourceName"];
var group = People.ContactGroups.get("contactGroups/friends");
var groupResourceName = group["resourceName"];
var membersResource = {
"resourceNamesToAdd": [
contactResourceName
]
}
People.ContactGroups.Members.modify(membersResource, groupResourceName);
return ContentService.createTextOutput(JSON.stringify(group));
}

Where was the deprecation notice?
It was on display in the bottom of a locked filing cabinet stuck in a disused lavatory with a sign on the door saying "Beware of the Leopard."
In all seriousness, advanced services are thin layers wrapping the corresponding REST APIs, in this case, People API, therefore each method of the service has a corresponding method exposed by the API, specifically contactGroups.members.modify.
The description of the method reads as follows, clearly outlining that system contact groups are, in fact, deprecated:
The only system contact groups that can have members added are contactGroups/myContacts and contactGroups/starred. Other system contact groups are deprecated and can only have contacts removed.
Can I update system groups via the API directly?
It does not seem to be possible, as adding system groups to contact when updating memberships field via the people.updateContact method is explicitly forbidden (you have to examine the ContactGroupMembership resource docs to find the info):
Any contact group membership can be removed, but only user group or "myContacts" or "starred" system group memberships can be added.

Related

Django: Send current logged in user as JSON

I would like to create a GET endpoint that returns the JSONResponse of the current logged-in user. Ideally, it would look like:
{
"username": "joe",
"email": "joe#plainviewhcp.com",
"first_name": "",
"last_name": "",
"last_login": "2021-09-17T17:11:00.039Z",
"is_superuser": true,
"is_active": true
}
(Note that I'm using Django 3.2, not Django REST API)
This requires serializing the current user object, but serializing a single object is... opaque in the documentation, and many similar questions have responses from 6 or more years/two major versions ago.
I've solved this problem by re-querying the user from the request.user object and singling out the first field. This has the added benefit of controlling the fields. Note that I've already tested to make sure the user is logged in at this point.
def api_current_user(request: HttpRequest):
user = (
User.objects.filter(pk=request.user.pk)
.values(
"username",
"email",
"first_name",
"last_name",
"last_login",
"is_superuser",
"is_active",
)
.first()
)
return JsonResponse(user)

People API - Update Contacts - How to update individual fields instead of all (e.g. phoneNumbers) using GAS

in order to update my contacts phone numbers, I am using People API with following code:
function updateContact(contactRn, contactEtag, contactPhone){
var bodyRequest = {
"resourceName": contactRn,
"etag": contactEtag,
"phoneNumbers": [{
'value': contactPhone,
'Type': 'googleVoice' }]
};
People.People.updateContact(bodyRequest, contactRn, {updatePersonFields: "phoneNumbers"});
}
It works. It updates the phone number of the contact.
Unfortunately, it also overwrites all other phone numbers associated with this contact, which means it deletes them.
Can you tell me how to update specific phone numbers only (like the contacts google voice number), using GAS?
Thanks, Flo
Allright, I decided to try the simplest thing, and just add more itens to the array, and what you know? It worked for me.
function updateContact(contactRn, contactEtag, contactPhone){
var bodyRequest = {
"resourceName": contactRn,
"etag": contactEtag,
"phoneNumbers": [{'value': contactPhone, 'type': 'googleVoice' },
{'value': anotherPhone,'type': 'workphone' },
{'value': thirdPhone,'type': 'homephone' }]
};
People.People.updateContact(bodyRequest, contactRn, {updatePersonFields: "phoneNumbers"});
}
My contact now has updated all his 3 phone numbers on google contacts

Sailsjs MVC map params from external API to multiple models

I need to create a database of shopify orders so I can run advanced queries and sales reports that you can't do in the shopify admin area. I'm building in Sails .12 and mysql. Shopify lets you register a webhook so that every time an order is placed, it creates a POST to the specified URL with the order data in the body as JSON. The products ordered are an array of JSON objects as one of the values in the POST:
{
"id": 123456,
"email": "jon#doe.ca",
"created_at": "2017-01-10T14:26:25-05:00",
...//many more entires
"line_items": [
{
"id": 24361829895,
"variant_id": 12345,
"title": "T-Shirt",
"quantity": 1,
"price": "140.00",
},
{
"id": 44361829895,
"variant_id": 42345,
"title": "Hat",
"quantity": 1,
"price": "40.00",
},
]
}
I need to save the order into an Orders table, and the products ordered into a line_items table that is a one to many relation; one order can have many line_items (products ordered). There are over 100 key-value pairs sent by the webhook, and I'm saving all of it. I've created my two models where I define the data type, so now i have very long Order.js and Line_item.js files, and I'm using the
line_items: {
collection: 'line_item',
via: 'order_id'
},
in my Order.js, and
order_id: {
model: 'order'
},
in my Line_item.js models to relate them. Is this the correct way to denfine my two tables? Also, where would I put the code that maps the JSON to the model parameters? If I put that code in the controllers, would I have to type another 100+ lines of code to map each json value to its correct parameter. The how would I save to the two different models/tables? Eg:
var newOrder = {};
newOrder.id =req.param('id');
newOrder.email = req.param('email');
newOrder.name = req.param('name');
...//over 100 lines more, then Order.create(newOrder, ...)
var newLine_items = req.params('line_items'); //an array
_.forEach(newLine_items, function(line_item){
var newLine_item = {};
newLine_item.id = line_item.id;
newLine_item.order_id = newOrder.id;
newLine_item.title = line_item.title;
//etc for over 20 more lines, then Line_item.create(newLine_item, ...)
});
I need to save the order into an Orders table, and the products ordered into a line_items table that is a one to many relation; one order can have many line_items (products ordered).
That sounds completely reasonable, well, besides the use of the Oxford comma :)
There are over 100 key-value pairs sent by the webhook
I'm not sure that I understand exactly what this is or what it is used for within this process.
That being said, it might help to have a single attribute in your model for this which has a JSON value, then retrieve and work with it as JSON instead of trying to manually account for each attribute if that is what you're doing over there?
It really depends on your use case and how you'll use the data though but I figure if the format changes you might have a problem, not so if it's just being stored and parsed as a JSON object?
Also, where would I put the code that maps the JSON to the model parameters
In v0.12.x take a look at Services.
In v1, Services will still work but moving this logic into Helpers might be a good option but then, it seems that a custom model method would be a better one.
Here is a shorter version of your code:
var newOrder = req.allParams();
newLine_items = {};
_.forEach(newOrder.line_items, function(line_item) {
newLine_items.push(line_item);
});
Here is what your logic might look like:
var newOrder = req.allParams();
// Store the order
Order
.create(newOrders)
.exec(function (err, result) {
if (err) // handle the error
var newLine_items = {};
_.forEach(newOrder.line_items, function(line_item) {
// Add the order id for association
line_item.order_id = result.id;
// Add the new line item with the orders id
newLine_items.push(line_item);
});
// Store the orders line items
LineItems
.create(newLine_items)
.exec(function (err, result) {
if (err) // handle the error
// Handle success
});
});
And the lifecycle callback in the Order model:
beforeCreate: function (values, cb) {
delete(values.line_items);
cb();
}
But you really should look into bluebird promises as the model methods in version one of sails have opt in support for them and it helps to negate the pyramid of doom that is starting in my example and is also something that you want to avoid :P

Using REST design properly - Categories and Subcategories

I have two question on basic REST concepts.
QUESTION 1: Categories
So I have a list of Categories I want to show from a database.
SELECT * from categories
Currently, I use this REST desgin: /api/v1/categories/
Is that proper?
I have also seen /api/v1/categories/list/ -- or is this preferred? (If so, then what would a simple /categories call display then? (Or would the proper way then be /api/v1/category/list where category is singular and adding list will show you all categories -- this way a call to /category would allow veiwing info on just one?)
QUESTION 2: Subcategories. (Think "Seinfeld" as a subcategory of "Television".)
SELECT * FROM subcategories" WHERE category_id = {id}
The id above might be the Television Category where I want to get specific shows listed.
Would I do /api/v1/categories/{id}/ for the Subcategory with the subcat_id? Would I have to use parameters instead like /Categories?id={id}/
How would this relationship work?
My answers are based on "pragmatic REST".
QUESTION 1: Categories
If you go with plural or singular form then I would suggest sticking with it and not jump between singular and plural... this is subjective.
If you go with singular form, then the list path action sounds applicable. If you go with plural then I think it is more subjective... IMHO list removes ambiguity and I would prefer it.
QUESTION 2: Subcategories. (Think "Seinfeld" as a subcategory of "Television".)
IMHO sub-category sounds like a separate resource. I think it should have its own path element.
Would I do /api/v1/categories/{id}/ for the Subcategory with the subcat_id? Would I have to use parameters instead like /Categories?id={id}/
I think that /api/v1/subcategories/{id}/ is more popular. But one thing that is becoming more popular is searching criteria. ID might just be one of many search criteria. If you see yourself adding search criteria then /api/v1/subcategories/?id={id} or /api/v1/subcategories/?filter={some_search_string} where you decide how that search string is parsed.
The most important thing to consider is that you are able to grow (extend) your API without changing these initial decisions you are making now. Its easy to add to an API but harder to alter existing API design once it is being used.
The URI structure is an implementation detail, it does not matter by REST as long as your service fulfills the uniform interface constraint, which is about applying the relevant standards. In your case the URI structure must fulfill the URI standard and you have to use a hypermedia format, which contains hyperlinks. So in your case /api/v1/sdfh34gsv/123regf3 would be completely okay as long as it is in a hyperlink and there is sufficient metadata available to understand what that hyperlink does. E.g. with HAL+JSON:
{
"_links": {
"/api/v1/docs/rels/category": {
"href": "/api/v1/sdfh34gsv/123regf3",
"title": "Television"
}
}
}
By processing such a response the client will recognize the "/api/v1/docs/rels/category" link relation, so it will know that it is a hyperlink to a category, which title is "Television" and the details of the category can be retrieved by following the link. If the client does not know the /api/v1/docs/rels/category link relation, then it can dereference the URI and and probably it will get some description in RDF, which it can use to display the hyperlink in a more basic form. Ofc, if developers dereference the same URI, they can get a HTML description of the link relation.
By most of the REST services this does not happen, because they use vendor specific MIME types and probably plain JSON, which violates the HATEOAS constraint, but I guess it is more practical in some cases.
async getAllCategorySubCategoryAndGroupCategoryDetail(): Promise < CategoryDetails[] > {
try {
let categoryGroupQuery = `SELECT shrt_category_groups.id as categoryGroupId,
shrt_category_groups.category_group_name as categoryGroupName,
concat('${ENV.IMG_SERVER}',shrt_category_groups.category_group_image) AS categoryGroupImage,
shrt_category_groups.is_active as isActive,
shrt_category_groups.sort_order as sortOrder
FROM shrt_category_groups where shrt_category_groups.is_active = '1' `;
let categoryGroupList = await pool.query(categoryGroupQuery);
if (categoryGroupList.length > 0) {
let categoryListQuery = `SELECT shrt_categories.id as categoryId,
shrt_categories.category_name as categoryName,
shrt_categories.category_image as categoryImage,
shrt_categories.is_active as isActive,
shrt_categories.category_group_id as categoryGroupId
FROM shrt_categories where shrt_categories.is_active = '1'`;
let categoryList = await pool.query(categoryListQuery);
let subcategoryQuery = `SELECT shrt_sub_categories.id as subCategoryId,
shrt_sub_categories.is_active as isActive,
shrt_sub_categories.subcategory_commission as commission,
shrt_sub_categories.commission_type as commissionType,
shrt_sub_categories.sub_category_name as subCategoryName,
shrt_sub_categories.category_id as categoryId
FROM shrt_sub_categories where shrt_sub_categories.is_active = '1'`;
let subCategoryList = await pool.query(subcategoryQuery);
const getCategory = (categoryGroupId: any) => {
return categoryList.filter((cat: any) => cat.categoryGroupId == categoryGroupId)
}
const getSubCategory = (categoryId: any) => {
return subCategoryList.filter((subCategory: any) => subCategory.categoryId == categoryId)
}
let mergeData = categoryGroupList.map((catG: any) => {
return { ...catG,
category: getCategory(catG.categoryGroupId).map((cat) => {
return { ...cat,
subCategory: getSubCategory(cat.categoryId)
}
})
}
})
return mergeData;
} else {
return categoryGroupList;
}
} catch (error) {
throw error;
}
}
{
"data": [
{
"categoryGroupId": 1,
"categoryGroupName": "Cloud",
"categoryGroupImage": null,
"isActive": "1",
"sortOrder": null,
"category": [
{
"categoryId": 1,
"categoryName": "Kinder & Baby",
"categoryImage": null,
"isActive": "1",
"categoryGroupId": 1,
"subCategory": [
{
"subCategoryId": 17,
"isActive": "1",
"commission": null,
"commissionType": null,
"subCategoryName": "Shirts",
"categoryId": 1
},
{
"subCategoryId": 20,
"isActive": "1",
"commission": null,
"commissionType": null,
"subCategoryName": "Jacken",
"categoryId": 1
},
{
"subCategoryId": 21,
"isActive": "1",
"commission": null,
"commissionType": null,
"subCategoryName": "Organic Collection",
"categoryId": 1
},
{
"subCategoryId": 22,
"isActive": "1",
"commission": null,
"commissionType": null,
"subCategoryName": "Baby",
"categoryId": 1
},
{
"subCategoryId": 23,
"isActive": "1",
"commission": null,
"commissionType": null,
"subCategoryName": "Hoodies & Sweatshirts",
"categoryId": 1
}
]
}
]
}
]
}

access another model within ng-repeat

This seems to me like it should be painfully obvious but I've not found an example anywhere.
I have two models, sessions and users:
$scope.sessions =
[{
"sessionId":"1",
"userId":"12345",
"date": "17/07/2014",
"test_name":"2014beta",
"status": "new",
"assigned_to":""
}]
$scope.users =
[{
"userId":"12345",
"name":"Frank Tester",
"dob": "17/07/1967",
"eyes":"blue"
}]
A session belongs to a user, so in the database, the user ID is saved within the session model (over-simplified models above).
In a listing of sessions, I'd like to include the user name and other user detail, both of which are accessed via the user model.
I have both users and sessions available within the scope. I use an ng-repeat to list all sessions (and show things like session.name, session.time etc), how do I access the user name from the other model by it's ID? ie. I'd would think I should be able to access session.user.name
I'll need to do this in a couple of different places and will need to access different bits of cross-referenced data - Is there a simple way to do this within the template or do I need to build a service for this? A directive? A filter?
You can put another ng-repeat inside session ng-repeat and filter it by session.userId
please see that demo: http://plnkr.co/edit/BOITOEEYDM9tFH3zbMIW
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<ul>
<li ng-repeat="session in sessions">
{{session.date}}
<ul>
<li ng-repeat="user in users | filter: session.userId ">
{{user.name}}
</li>
</ul>
</li>
</ul>
</body>
js:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.sessions =
[{
"sessionId":"1",
"userId":"12345",
"date": "17/07/2014",
"test_name":"2014beta",
"status": "new",
"assigned_to":""
}]
$scope.users =
[{
"userId":"12345",
"name":"Frank Tester",
"dob": "17/07/1967",
"eyes":"blue"
}]
});