How to get AVERAGE VIEW DURATION on youtube api
Slightly modified from the YouTube Analytics API's Sample Application
var request = gapi.client.youtubeAnalytics.reports.query({
// The start-date and end-date parameters must be YYYY-MM-DD strings.
'start-date': formatDateString(lastMonth),
'end-date': formatDateString(today),
// At this time, you need to explicitly specify channel==channelId.
// See https://developers.google.com/youtube/analytics/v1/#ids
ids: 'channel==' + channelId,
dimensions: 'day',
sort: 'day',
// See https://developers.google.com/youtube/analytics/v1/available_reports
// for details about the different filters and metrics you can request
// if the "dimensions" parameter value is "day".
metrics: 'averageViewDuration',
filters: 'video==' + videoId
});
Of course this assumes you have done the work of authenticating and retrieving the videoid.
Related
I have a question regarding a small issue that I'm having. I've created a widget that will live on the Service Portal to allow an admin to Accept or Reject requests.
The data for the widget is pulling from the Approvals (approval_approver) table. Under my GlideRecord, I have a query that checks for the state as requested. (Ex. addQuery('state', 'requested'))
To narrow down the search, I tried entering addQuery('sys_id', current.sys_id). When I use this query, my script breaks and I get an error on the Service Portal end.
Here's a sample of the GlideRecord script I've written to Accept.
[//Accept Request
if(input && input.action=="acceptApproval") {
var inRec1 = new GlideRecord('sysapproval_approver');
inRec1.addQuery('state', 'requested');
//inRec1.get('sys_id', current.sys_id);
inRec1.query();
if(inRec1.next()) {
inRec1.setValue('state', 'Approved');
inRec1.setValue('approver', gs.getUserID());
gs.addInfoMessage("Accept Approval Processed");
inRec1.update();
}
}][1]
I've research the web, tried using $sp.getParameter() as a work-around and no change.
I would really appreciate any help or insight on what I can do different to get script to work and filter the right records.
If I understand your question correctly, you are asking how to get the sysId of the sysapproval_approver record from the client-side in a widget.
Unless you have defined current elsewhere in your server script, current is undefined. Secondly, $sp.getParameter() is used to retrieve URL parameters. So unless you've included the sysId as a URL parameter, that will not get you what you are looking for.
One pattern that I've used is to pass an object to the client after the initial query that gets the list of requests.
When you're ready to send input to the server from the client, you can add relevant information to the input object. See the simplified example below. For the sake of brevity, the code below does not include error handling.
// Client-side function
approveRequest = function(sysId) {
$scope.server.get({
action: "requestApproval",
sysId: sysId
})
.then(function(response) {
console.log("Request approved");
});
};
// Server-side
var requestGr = new GlideRecord();
requestGr.addQuery("SOME_QUERY");
requestGr.query(); // Retrieve initial list of requests to display in the template
data.requests = []; // Add array of requests to data object to be passed to the client via the controller
while(requestsGr.next()) {
data.requests.push({
"number": requestsGr.getValue("number");
"state" : requestsGr.getValue("state");
"sysId" : requestsGr.getValue("sys_id");
});
}
if(input && input.action=="acceptApproval") {
var sysapprovalGr = new GlideRecord('sysapproval_approver');
if(sysapprovalGr.get(input.sysId)) {
sysapprovalGr.setValue('state', 'Approved');
sysapprovalGr.setValue('approver', gs.getUserID());
sysapprovalGr.update();
gs.addInfoMessage("Accept Approval Processed");
}
...
When setting the timestamp format to 'absolute', the webchat with locale set to fr-FR prints the time portion of the timestamp using the 'short' time format of globalizejs library as 8:36 AM. See: https://github.com/globalizejs/globalize/blob/master/doc/api/date/date-formatter.md.
Can I override the time format to display the time in 24-hour notation, i.e. instead of 8:36 AM to print 8h 36?
Web Chat is integrated into a webpage using JavaScript (not React):
v. 4.8.1, https://cdn.botframework.com/botframework-webchat/latest/webchat.js
If you are using the non-React version of Web Chat, then, no, there isn't an in-built method for updating or changing the timestamp.
However, you can use Web Chat's store for accessing the activity's timestamp to overwrite the HTML element, as shown below. My example is updating the element with only the time. You will want to add functionality to capture any other bits (date, day, time offsets, etc.).
Also, you will need to account for the in-built auto-updating of the time element by Web Chat. For instance, when a minute has passed following an activity's arrival, the time element changes to "1 minute ago", then to "2 minutes ago", and so on.
You may be able to utilize an event listener that looks for changes to the time element which, when triggered, continues to update the time element to fit your needs.
Please note: There are inherent risks in manipulating the DOM directly. The biggest risk is your bot becomes subject to breaking changes should the Web Chat team decide to update, remove, or otherwise alter some underlying component in the future. I would recommended you consider switching to the React version of Web Chat that, among many other features, allows this change while functioning within Web Chat's space.
Lastly, any refreshing of the page will reset the time elements back to Web Chat defaults (in case you have your bot setup for persistent chat across sessions).
<script>
( async function () {
const store = window.WebChat.createStore( {}, ({dispatch}) => next => action => {
if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
const { activity } = action.payload;
if (activity.type === 'message') {
console.log('MESSAGE ', activity);
setTimeout(() => {
const webChatRow = document.querySelectorAll('.webchat__row');
const rowLen = webChatRow.length;
const timeParent = webChatRow[ rowLen - 1 ].children;
let timeText = timeParent[ 0 ].children[ 1 ].innerText;
let time = new Date(activity.timestamp);
let hours = time.getHours();
let mins = time.getMinutes();
timeParent[ 0 ].children[ 1 ].innerText = `${hours}:${mins}`
console.log(timeText)
}, 300);
}
}
next(action);
} );
const res = await fetch( 'http://localhost:3500/directline/token', { method: 'POST' } );
const { token } = await res.json();
window.WebChat.renderWebChat(
{
directLine: window.WebChat.createDirectLine( {
token: token
} ),
store: store
},
document.getElementById( 'webchat' )
);
document.querySelector( '#webchat > *' ).focus();
} )().catch( err => console.error( err ) );
</script>
Hope of help!
Take a look at the Customize activity status Web Chat sample. It shows how you can use the activityStatusMiddleware to customize the timestamp.
I'm trying to filter contents of an album (to get photos only) coming form Google Photos API, but the docs say that:
Filters shouldn't be used in a mediaItems:search request if the
albumId is set. If a filter is used when the albumId is set, an
INVALID_ARGUMENT error (400) is returned.
Does this mean that I have to download all files, than filter the response my self using the MIME type? Or can it still be done directly in the request?
Thanks!
My code:
var params = JSON.parse(localStorage.getItem('oauth2-params'));
var xhr = new XMLHttpRequest();
xhr.open('POST',
'https://photoslibrary.googleapis.com/v1/mediaItems:search?' +
'access_token=' + params['access_token'] +
'&pageSize=25' +
'&albumId=' + albumId +
'&pageToken=' + this.albums[albumId].photos.nextPagination);
xhr.responseType = "json";
xhr.onreadystatechange = (e) => {
if (xhr.readyState === 4 && xhr.status === 200) {
// handling the respons...
} else if(xhr.readyState === 4) {
console.log(xhr.status, xhr.response);
}
};
xhr.send(null);
Unfortunately, you can't specify both a media type and album as a parameter for a search request at the moment. There's a request for this on the issue tracker here. You can 'star' the issue to be notified of any updates.
For now, you can do the filtering on your side, without needing to download the files themselves: Check the mimeType and the mediaMetadata properties of a media item. The mimeType field indicates what kind of file it is (for example, image/jpeg or image/png). Alternatively, you can also check whether the mediaMetadata property contains a photo.
I want to make a map marker which will move whenever it gets updates from server. Each map marker is described by a latitude and longitude.
var url = '/tracking/records/fetch'+ '&id=' + user_id +'&type='+type;
This endpoint returns a set of latitude,longitude in JSON format.
How to move the marker when browser get updates from server ?
It sounds like your /tracking/records/fetch endpoint is set up for polling: your webpage can repeatedly fetch a whole set of coordinates from the server, then update a map view of those coordinates. To make this realtime, you need to move away from pure polling to pushing.
First, sign up for a Pusher account. Then have your webpage connect to your Pusher app and subscribe to a channel for new coordinates:
<script src="//js.pusher.com/4.0/pusher.min.js"></script>
<script>
var pusher = new Pusher('YOUR_APP_KEY', {
cluster: 'YOUR_APP_CLUSTER'
});
var tracking-records = pusher.subscribe('tracking-records-' + type + '-' + user_id); // Channel specific to this user
tracking-records.bind('new-tracking-record', function(data) {
console.log('A new tracking record with latitude', data.latitude, 'and longitude', data.longitude);
// Update your Google Map view here using data.latitude, data.longitude
});
</script>
Then on your server, identify where the tracking records are created (probably a database insert). At that point, publish the new coordinate to the tracking-records channel. Here's an example in Node.js:
var Pusher = require('pusher');
var pusher = new Pusher({
appId: 'APP_ID',
key: 'APP_KEY',
secret: 'APP_SECRET',
cluster: 'APP_CLUSTER'
});
pusher.trigger(
'tracking-records-' + type + '-' + user_id, // The channel name
'new-tracking-record', // The event type
{latitude: 51, longitude: 3} // The coordinate data
);
For more detailed examples, Pusher have a tutorial on how to track our pizza in realtime with Pusher and Google Maps, and another tutorial on how to build a realtime map using Laravel.
I want to get the list of popular events in San Francisco through
ajax request to Eventbrite API. Here's the code.
var city = 'San Francisco';
var query = "token=" + token + "&venue.city=" + city + "&popular=" + true + "&location.within=" + "10mi"
var $events = $("#events");
var settings = {
"async": true,
"crossDomain": true,
"url": "https://www.eventbriteapi.com/v3/events/?" + query,
"method": "GET",
"headers":{}
}
I'm getting results from other cities too. How can I set parameters to get results from San Francisco only? Also, I'm getting multiple copies of a single event. Is there any way to prevent this?
Your Query is Incorrect for API v3: When testing your query I received errors from the Eventbrite API. These errors are due to using the incorrect query parameters. For example 'popular' does not exist as a parameter. Make sure to test your queries via their playground https://www.eventbriteapi.com/v3/events/search?token='YOUR-OAUTH-TOKEN'.
SF Only Events: There is no way to set parameters in the Eventbrite query for events only in SF unless you include a small search radius around the latitude and longitude. That method could possibly exclude some popular SF events. The best way is to query all SF area events and then manipulate the data you get back by filtering out events whose Venue city is not San Francisco.
Popular Events: To truly get popular events you'd need to know how many tickets have been sold for each event (private data.) Instead, we need to use the sort_by parameter in our initial query to get the 'best' events. Unfortunately, 'best' is very vague in the API but all we have to work with.
Duplicate Events: Given the below query you will not get duplicate events.
Try the below jQuery AJAX method:
const sfSettings = {
url: 'https://www.eventbriteapi.com/v3/events/search/',
data: {token: 'YOUR-OAUTH-TOKEN', sort_by: 'best', 'location.latitude': 37.7749, 'location.longitude': -122.4194, expand: 'venue'},
crossDomain: true,
method: 'GET'
}
$.ajax(sfSettings).done(function(eventObject){
// All SF Area Events (Paginated by 50. Will only return first page.)
const events = eventObject.events;
// Create a new array of events whose venue is specifically in SF
const sfEvents = events.filter(function(event){
return event.venue.address.city === 'San Francisco';
});
});