I have a web app with GAS that create folders, upload files, set permissions and save the registers on a sheet.
Ocassionally the app duplicate files when the functions finished and duplicate a register in the google sheet. I don't know how to avoid this error, and the console does not show the error either.
What could be happening? How can I prevent this problem?
This is my code for server side functions:
function fileExists(idfileexist,folderId) {
var consulta = DriveApp.getFileById(idfileexist).getName()
var files = DriveApp.getFilesByName(consulta);
while (files.hasNext()) {
var file = files.next();
var folders = file.getParents();
if (folders.hasNext()) {
var folder = folders.next();
if (folder.getId() == folderId) {
return true;
}
}
}
return false;
}
function removepermission(id, user){
DriveApp.getFileById(id).removeEditor(user)
}
function appendrow(idfile,sheet,numsip,rut,timestamp,user,idfolder,input,ticket){
var values = SpreadsheetApp.openById(idfile);
var ss= values.getSheetByName(sheet);
ss.appendRow([numsip,rut,timestamp,user,idfolder,input,ticket])
}
function setpermisoswriter(id,array){
var file = DriveApp.getFileById(id)
var editors = file.getEditors();
if (editors.length > 0) {
for (var i = 0; i < array.length; i++) {
Drive.Permissions.insert({'role': 'writer','type': 'user','value': array[i]},id,{'sendNotificationEmails': 'false' });};};
}
function setpermisosreader(id,array){
var file = DriveApp.getFileById(id)
var editors = file.getEditors();
if (editors.length > 0) {
for (var i = 0; i < array.length; i++) {
Drive.Permissions.insert({'role': 'reader','type': 'user','value': array[i]},id,{'sendNotificationEmails': 'false' });};};
}
function setownerid(id,user){
Drive.Permissions.insert({'role': 'owner','type': 'user','value': user},id,{'sendNotificationEmails': 'false'})
}
function setpermisoread(id,user){
Drive.Permissions.insert({'role': 'reader','type': 'user','value': user},id,{'sendNotificationEmails': 'false'})
}
function setpermisowrite(id,user){
Drive.Permissions.insert({'role': 'writer','type': 'user','value': user},id,{'sendNotificationEmails': 'false' })
}
function permissionstotal(){
var parentFolderId = "parentFolderId";
var idfilesheet="idfilesheet";
var useractive = Session.getActiveUser().getEmail();
var jefes = ["EMAIL#EMAIL.COM","EMAIL#EMAIL.COM", "EMAIL#EMAIL.COM","EMAIL#EMAIL.COM"]
var userviewer="EMAIL#EMAIL.COM"
setpermisosreader(parentFolderId,jefes)
setpermisosreader(idfilesheet,jefes)
setpermisoread(idfilesheet,useractive)
removepermission(parentFolderId,useractive)
setpermisoread(parentFolderId, useractive)
//setpermisowrite(idfilesheet,userviewer)
//setpermisoread(parentFolderId,userviewer)
}
function addNewRow(array,obj) {
var admin ="ADMIN"
var useractive = Session.getActiveUser().getEmail();
var timestamp = new Date();
var sheet="DATA"
var jefes = ["EMAIL#EMAIL.COM","EMAIL#EMAIL.COM", "EMAIL#EMAIL.COM","EMAIL#EMAIL.COM"]
var userviewer="EMAIL#EMAIL.COM"
var parentFolderId = "parentFolderId";
var idfile="idfile"
var parentFolder = DriveApp.getFolderById(parentFolderId);
setpermisowrite(parentFolderId,useractive)
setpermisowrite(idfile,useractive)
var folderName = "SIP "+array.numsip+"/"+array.rut;
var foldercreated = parentFolder.getFoldersByName(folderName);
foldercreated = foldercreated.hasNext() ? foldercreated.next() : parentFolder.createFolder(folderName);
var idfolder= foldercreated.getId()
appendrow(idfile,sheet,array.numsip,array.rut,timestamp,useractive,idfolder,array.input,array.ticket)
setownerid(idfolder,admin)
setpermisosreader(idfolder,jefes)
//setpermisoread(idfolder,userviewer)
return obj.map(({fileName, mimeType, data}) => {
var blob = Utilities.newBlob(Utilities.base64Decode(data), mimeType, fileName);
var foldercode = foldercreated.createFile(blob).getId();
var archivo = fileExists(foldercode,idfolder);
if (archivo==false){
console.log("archivo ya existe")
}
else{
setpermisosreader(foldercode,jefes)
//setpermisoread(foldercode,userviewer)
setownerid(foldercode,admin)
removepermission(foldercode,useractive)
setpermisoread(foldercode,useractive)
removepermission(idfolder,useractive)
setpermisoread(idfolder,useractive)
console.log("archivo creado")
return foldercode
}
});
}
function getsip(sipCode){
//var sipCode= "123"
var url ="URL SHEET";
var ss2= SpreadsheetApp.openByUrl(url);
var ws2= ss2.getSheetByName("DATA")
var data2 = ws2.getRange(2, 1, ws2.getLastRow(), 2).getDisplayValues()
var idList = data2.map(function(r) {return r[0];});
var position = idList.indexOf(sipCode)
if (position >-1){
console.log (idList[position])
return "REPETIDO";
} else{
console.log ("2")
return "NOREPETIDO"
}
}
This is the Javascript code:
function enviardatosvalidados(){
var validacion=document.getElementById("sipcode").value
if(validacion=="REPETIDO"){
$('#modal2').modal('hide')
$('#modalval').modal('show')
}
else{
try{
enviardatos()
$("#generar").attr("disabled", true)
google.script.run.permissionstotal()
setTimeout(function(){
$("#generar").attr("disabled", false) ; }, 25000)
window.reloadTheWebApp = function() {
console.log('reloadTheWebApp ran');
var linkTag = document.getElementById('testLink');
linkTag.click();
}
} catch(error){
alert("Hubo un error.")
alert(error)
}
}
}
function enviardatos(){
if(validate()){
var sip = document.getElementById("numsip")
var rut = document.getElementById("rut")
var input = document.getElementById("input")
var ticket = document.getElementById("ticket")
var array ={numsip: sip.value,rut: rut.value, input:input.value,ticket:ticket.value}
const f = document.getElementById('files');
Promise.all([...f.files].map((file, i) => {
const fr = new FileReader();
return new Promise((r, rj) => {
fr.onload = (e) => {
const data = e.target.result.split(",");
r({fileName: f.files[i].name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]});
}
fr.onerror = (e) => rj(e);
fr.readAsDataURL(file);
});
}))
.then(obj => google.script.run.withSuccessHandler(console.log).addNewRow(array, obj))
.catch(err => alert(err));
$('#modal2').modal('hide')
successnotification2()
setTimeout(function(){
$(':input').val('');
$("#modalcarpeta").modal('show'); }, 25000);
;
}
else{
$('#modal2').modal('hide')
}
}
function validate(){
var fieldsToValidate = document.querySelectorAll("#userform input, #userform select");
Array.prototype.forEach.call(fieldsToValidate, function(el){
if(el.checkValidity()){
el.classList.remove("is-invalid");
}else{
el.classList.add("is-invalid");
}
});
return Array.prototype.every.call(fieldsToValidate, function(el){
return el.checkValidity();
});
}
function checkRut(rut) {
// Despejar Puntos
var valor = rut.value.replace('.','');
// Despejar Guión
valor = valor.replace('-','');
// Aislar Cuerpo y Dígito Verificador
cuerpo = valor.slice(0,-1);
dv = valor.slice(-1).toUpperCase();
// Formatear RUN
rut.value = cuerpo + '-'+ dv
// Si no cumple con el mínimo ej. (n.nnn.nnn)
if(cuerpo.length < 7) { rut.setCustomValidity("RUT Incompleto"); return false;}
// Calcular Dígito Verificador
suma = 0;
multiplo = 2;
// Para cada dígito del Cuerpo
for(i=1;i<=cuerpo.length;i++) {
// Obtener su Producto con el Múltiplo Correspondiente
index = multiplo * valor.charAt(cuerpo.length - i);
// Sumar al Contador General
suma = suma + index;
// Consolidar Múltiplo dentro del rango [2,7]
if(multiplo < 7) { multiplo = multiplo + 1; } else { multiplo = 2; }
}
// Calcular Dígito Verificador en base al Módulo 11
dvEsperado = 11 - (suma % 11);
// Casos Especiales (0 y K)
dv = (dv == 'K')?10:dv;
dv = (dv == 0)?11:dv;
// Validar DV
if(dvEsperado != dv) { rut.setCustomValidity("RUT Inválido"); return false; }
// Validación
rut.setCustomValidity('');
}
function successnotification2(){
document.getElementById("save-success2").classList.remove("invisible");
setTimeout(function(){
document.getElementById("save-success2").classList.add("invisible")
},25000);
}
function getSip(){
var sipCode = document.getElementById("numsip").value;
google.script.run.withSuccessHandler(updatesipcode).getsip(sipCode);
}
function updatesipcode(sipCode){
document.getElementById("sipcode").value = sipCode;
}
document.getElementById("numsip").addEventListener("input",getSip)
Greetings and Thank You!
My old method it was very "heavy". When i set the permission to the folder and files, i had to call a lot of times the Driver API and the services. Other problem it was that the parent folder had a lot of folders and many files which made it take a long time to set the permissions to the user or revocate permissions.
My new method was create a folder with edit permission for the users and move the files and folder to the destiny folder for other users. My objetive was set the correct permissions for final users.This is my new code. The javascript's code doesn't have problems:
function moveFiles(sourceFileId, targetFolderId) {
var file = DriveApp.getFileById(sourceFileId);
file.getParents().next().removeFile(file);
DriveApp.getFolderById(targetFolderId).addFile(file);
}
function fileExists(idfileexist,folderId) {
var consulta = DriveApp.getFileById(idfileexist).getName()
var files = DriveApp.getFilesByName(consulta);
while (files.hasNext()) {
var file = files.next();
var folders = file.getParents();
if (folders.hasNext()) {
var folder = folders.next();
if (folder.getId() == folderId) {
return true;
}
}
}
return false;
}
function removepermission(id, user){
DriveApp.getFileById(id).removeEditor(user)
}
function appendrow(idfile,sheet,numsip,rut,timestamp,user,idfolder,exedoc,ticket){
var values = SpreadsheetApp.openById(idfile);
var ss= values.getSheetByName(sheet);
ss.appendRow([numsip,rut,timestamp,user,idfolder,exedoc,ticket])
}
function setpermisoswriter(id,array){
var file = DriveApp.getFileById(id)
var editors = file.getEditors();
if (editors.length > 0) {
for (var i = 0; i < array.length; i++) {
Drive.Permissions.insert({'role': 'writer','type': 'user','value': array[i]},id,{'sendNotificationEmails': 'false' });};};
}
function setpermisosreader(id,array){
var file = DriveApp.getFileById(id)
var editors = file.getEditors();
if (editors.length > 0) {
for (var i = 0; i < array.length; i++) {
Drive.Permissions.insert({'role': 'reader','type': 'user','value': array[i]},id,{'sendNotificationEmails': 'false' });};};
}
function setownerid(id,user){
Drive.Permissions.insert({'role': 'owner','type': 'user','value': user},id,{'sendNotificationEmails': 'false'})
}
function setpermisoread(id,user){
Drive.Permissions.insert({'role': 'reader','type': 'user','value': user},id,{'sendNotificationEmails': 'false'})
}
function setpermisowrite(id,user){
Drive.Permissions.insert({'role': 'writer','type': 'user','value': user},id,{'sendNotificationEmails': 'false' })
}
function addNewRow(array,obj) {
var admin ="ADMIN"
var useractive = Session.getActiveUser().getEmail();
var timestamp = new Date();
var sheet="DATA"
var parentFolderIdorigen ="PARENT FOLDER"
var idfile="IDSHEET"
var parentFolderorigen = DriveApp.getFolderById(parentFolderIdorigen)
var parentFolderIddestino = "ID"
setpermisowrite(idfile,useractive)
var folderName = "SIP "+array.numsip+"/"+array.rut;
var foldercreated = parentFolderorigen.getFoldersByName(folderName);
foldercreated = foldercreated.hasNext() ? foldercreated.next() : parentFolderorigen.createFolder(folderName);
var idfolder= foldercreated.getId()
appendrow(idfile,sheet,array.numsip,array.rut,timestamp,useractive,idfolder,array.input,array.ticket)
setownerid(idfolder,admin)
return obj.map(({fileName, mimeType, data}) => {
var blob = Utilities.newBlob(Utilities.base64Decode(data), mimeType, fileName);
var foldercode = foldercreated.createFile(blob).getId();
var archivo = fileExists(foldercode,idfolder);
if (archivo==false){
console.log("archivo ya existe")
}
else{
setownerid(foldercode,admin)
moveFiles(idfolder,parentFolderIddestino)
moveFiles(foldercode,idfolder)
console.log("archivo creado")
return foldercode
}
});
}
function getsip(sipCode){
var url ="URLSHEET";
var ss2= SpreadsheetApp.openByUrl(url);
var ws2= ss2.getSheetByName("DATA")
var data2 = ws2.getRange(2, 1, ws2.getLastRow(), 2).getDisplayValues()
var idList = data2.map(function(r) {return r[0];});
var position = idList.indexOf(sipCode)
if (position >-1){
console.log (idList[position])
return "REPETIDO";
} else{
console.log ("2")
return "NOREPETIDO"
}
}
Thanks to #Cooper and #ziganotschka for their comments.
Working on node.js instagram parser. At the moment I have 1 thread with proxy working code, but I'm not sure how to make multithread architecture:
'use strict';
var InstagramPrivateAPI = {};
InstagramPrivateAPI = {};
InstagramPrivateAPI.V1 = require(__dirname + '/client/v1');
InstagramPrivateAPI.Helpers = require(__dirname + '/helpers');
var acc = require(__dirname + "/client/v1/account");
var med = require(__dirname + "/client/v1/media")
var Promise = require('../bluebird');
var _ = require('../lodash/');
module.exports = InstagramPrivateAPI;
var Client = require('instagram-private-api').V1;
var device = new Client.Device('maksgmn');
var storage = new Client.CookieFileStorage(__dirname + '/cookies/maksgmn.json');
var session = new Client.Session(device, storage);
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
var fs = require('fs');
var proxyArray = fs.readFileSync('proxy.txt').toString().split("\n");
var usernamesArray = fs.readFileSync('usernames.txt').toString().split("\n");
var proxy = "http://" + proxyArray[getRandomInt(0,proxyArray.length)]
var username = usernamesArray[getRandomInt(0,usernamesArray.length)]
console.log(proxy)
console.log(username)
Client.Request.setProxy(proxy);
acc.searchForUser(session, username) //поиск id пользователя
.then(function(profile) {
return profile.id
})
.then(function(someId) { //получение промиса lenta
var feed = new Client.Feed.UserMedia(session, someId);
var lenta = Promise.mapSeries(_.range(0, 1), function() {
return feed.get();
}).then(function(lenta) {
return {id: someId, fd : lenta}
})
return lenta
})
.then(function(results) { //обработка промиса и получение ленты пользователя
// result should be Media[][]
var media1 = _.flatten(results.fd);
var urls1 = _.map(media1, function(medium) {
//var arr1 = medium.params.images[0].url;
var arr1 = []
try {
arr1 = medium.params.images[0].url
} catch (err) {
//console.log("lala")
}
return arr1;
//console.log(medium.params.carouselMedia.images[0].url)
})
//console.log(urls1)
return {id : results.id, linksNoCarousel : urls1, med : media1}
})
.then(function(res){
var urls2 = _.map(res.med, function(medium) {
var arr2 = []
try {
arr2 = medium.params.images[0][0].url
//console.log(arr2)
} catch (err) {
}
return arr2
})
for (var i = 0; i < 5; i++) {
if (typeof res.linksNoCarousel[i] == "undefined")
res.linksNoCarousel[i] = urls2[i];
}
var arr3 = []
for (var i = 0; i < 5; i++) {
arr3[i] = res.linksNoCarousel[i]
}
return {id : res.id, links : arr3}
})
.then(function(mediaAndId) {
acc = acc.getById(session, mediaAndId.id)
.then(function(account) {
//console.log(account.params)
let avatar = account.params.profilePicUrl;
let fullName = account.params.fullName;
let bio = account.params.biography;
let media0 = mediaAndId.links[0];
let media1 = mediaAndId.links[1];
let media2 = mediaAndId.links[2];
let media3 = mediaAndId.links[3];
let media4 = mediaAndId.links[4];
console.log(avatar);
console.log(fullName);
console.log(bio);
console.log(media0);
console.log(media1);
console.log(media2);
console.log(media3);
console.log(media4);
})
})
I would like it to work like multithread to be much more faster with proxies. As far as I'm working with node.js 2nd day, asking that question: how to do that?
I have the following code which reads information from a sharepoint list and renders fine in google chrome, but when tested in IE 11 (Corporate Browser), then I get the following exception:
ReferenceError: 'Promise' is undefined
at getContentTypeOfCurrentItem (https://ourserver.com/sites/billing/Style%20Library/xxx/Angular/related-billing-documents-controller.js:209:5)
at addContentType (https://ourserver.com/sites/billing/Style.com/sites/billing/Style%20Library/xxx/Angular/related-billing-documents-controller.js:201:5)
at Anonymous function (https://ourserver.com/sites/billing/Style%20Library/xxx/Angular/related-billing-documents-controller.js:163:7)
at Anonymous function (https://ourserver.com/sites/billing/Style%20Library/xxx/Angular/angular.min.js:130:399)
at m.prototype.$eval (https://ourserver.com/sites/billing/Style%20Library/xxx/Angular/angular.min.js:145:96)
at m.prototype.$digest (https://ourserver.com/sites/billing/Style%20Library/xxx/Angular/angular.min.js:142:165)
at Anonymous function (https://ourserver.com/sites/billing/Style%20Library/xxx
(function () {
angular
.module('BillCycleApp')
.controller('relatedBillingDocumentsController', ['$scope', '$log', '$q', 'spService', 'BillingDocuments', 'General',
function ($scope, $log, $q, spService, config, generalConfig) {
var vm = this;
var tableSelector = "#related-billing-documents-table";
var componentSelector = ".related-billing-documents";
function GetContext() {
vm.Name = config.Name;
var dataTableColumns = spService.TransformFieldsToDataTableColumns(config.FieldsToShow);
$.fn.dataTable.moment( generalConfig.DateTimeFormat );
// Initialize with empty data
$(tableSelector).DataTable({
data : [],
columns : dataTableColumns,
order : config.SortOrder,
deferRender : true
}).on( 'draw.dt', function ( e, settings, processing ) {
// Make sure the UserPresence is added every time the DataTable's data changes (paging, sorting, search,..)
spService.UserPresenceComponent.AddPresence();
});
// Make component visible
$(componentSelector).css("visibility", "visible");
// SP.js function
// Get Bill Cycle list & id
var listItemId = GetUrlKeyValue('ID', true, window.location.search, true);
var listId = "{" + GetUrlKeyValue('List', true, window.location.search, true) + "}";
var propertiesToLoad = ["FileRef","PwC_ClientCode","PwC_JobCodesMulti","PwC_EngagementCode"];
spService.GetListItem(listId, listItemId, propertiesToLoad)
.then(function(billCycle) {
var listItemValues = [];
propertiesToLoad
.forEach(function(propertyName) {
var value = billCycle.get_item(propertyName);
listItemValues[propertyName] = value;
});
var billCyclePath = _spPageContextInfo.siteAbsoluteUrl;
billCyclePath += listItemValues["FileRef"];
var clientCode = listItemValues["PwC_ClientCode"]
var jobCodesLookups = listItemValues["PwC_JobCodesMulti"];
var engagementCode = listItemValues["PwC_EngagementCode"]
var jobCodes = [];
if(jobCodesLookups) {
jobCodesLookups.forEach(function(lookup) {
jobCodes.push(lookup.get_lookupValue());
});
}
// Get data with parameters
GetData(billCyclePath, clientCode, jobCodes, engagementCode);
});
}
function GetData(billCyclePath, clientCode, jobCodes, engagementCode) {
var enhanceFunctions = [
function(searchResultRow) {
return spService.AddHyperLinkOnFields(searchResultRow, config.HyperLinks);
},
function(searchResultRow) {
return spService.AddPresenceOnFields(searchResultRow, config.UserFields);
},
function(searchResultRow) {
return spService.FormatDateFields(searchResultRow, config.DateFields, generalConfig.DateTimeFormat);
},
function(searchResultRow) {
return spService.AddImageMapping(searchResultRow, config.ImageFields);
},
function(searchResultRow) {
return spService.FormatNumberFields(searchResultRow, config.NumberFields);
},
function(searchResultRow) {
// Put link to parent Bill Cycle with name = folder name
//var parentLink = searchResultRow["FileRef"];
//arrayofstrings = parentLink.split("/");
//var billCycleFolderName = arrayofstrings[arrayofstrings.length-2];
//arrayofstrings.pop();
//var hyperLink = '' + billCycleFolderName + '';
//searchResultRow["Bill Cycle"] = hyperLink;
}
];
// Get data from SP
var selectProperties = spService.TransformFieldsToSelectProperties(config.Fields); // copy array
var selectPropertiesToShow = spService.TransformFieldsToSelectProperties(config.FieldsToShow); // copy array
var extendedSelectProperties = selectProperties.slice();
var hyperLinkedProperties = spService.TransformFieldsToSelectProperties(config.HyperLinks)
extendedSelectProperties = extendedSelectProperties.concat(hyperLinkedProperties);
GetRelatedBillingDocumentsFromList(extendedSelectProperties, billCyclePath, clientCode, jobCodes, engagementCode, enhanceFunctions)
.then(function (data) {
var trimmedData = spService.SpSearchQuery.TrimSearchResultsToSelectProperties(data, selectPropertiesToShow);
// Add data to dataTable
var dataTable = $(tableSelector).DataTable();
dataTable.clear().rows.add(trimmedData).columns.adjust().draw(); // Resize columns based on new data sizes
vm.ValidDataLoaded = true;
})
.catch (function (message) {
vm.Name = "Error";
vm.ValidDataLoaded = true;
});
}
function GetRelatedBillingDocumentsFromList(selectProperties, currentBillCyclePath, clientCode, jobCodes, engagementCode, enhanceFunctions) {
$log.info("Retrieving related billing documents for bill cycle with name [" + currentBillCyclePath + "]");
var deferred = $q.defer();
var webUrl = _spPageContextInfo.webAbsoluteUrl;
selectProperties = selectProperties.concat("ContentTypeId");
var viewFields = spService.ConvertSelectPropertiesToViewFields(selectProperties);
// query must return the documents for the same client but in other bill cycles not the current one
var camlQuery = '<View Scope="RecursiveAll">' + viewFields +
'<Query>' +
'<Where>' +
'<And>' +
'<Eq>' +
'<FieldRef Name="PwC_ClientCode" />' +
'<Value Type="Text">'+ clientCode + '</Value>' +
'</Eq>' +
'<Neq>' +
'<FieldRef Name="ContentType" />' +
'<Value Type="Computed">Bill Cycle</Value>' +
'</Neq>' +
'</And>' +
'</Where>' +
'</Query>' +
'</View>';
var billCyclesListId = "{c23bbae4-34f7-494c-8f67-acece3ba60da}";
spService.GetListItems(billCyclesListId, camlQuery, selectProperties)
.then(function(listItems) {
var listItemsWithValues = [];
if(listItems) {
var enumerator = listItems.getEnumerator();
var promises = [];
while (enumerator.moveNext()) {
var listItem = enumerator.get_current();
var listItemValues = [];
selectProperties
.forEach(function(propertyName) {
var value = listItem.get_item(propertyName);
if(propertyName === "PwC_JobCodesMulti"){
jobvalue = "";
value.forEach(function(jobvalues){
jobvalue+= jobvalues.get_lookupValue() +";";
})
listItemValues[propertyName] = jobvalue;
}else{
listItemValues[propertyName] = value;
}
});
listItemsWithValues.push(listItemValues);
}
var promises = listItemsWithValues.map(addContentType);
Promise.all(promises).then(youCanUseTheData);
function youCanUseTheData(){
/*
At this point, each listItem holds the 'Document Type' info
*/
listItemsWithValues.forEach(function(listItem) {
var fileDirRef = listItem["FileRef"];
var id = listItem["ID"];
var title = listItem["Title"];
var serverUrl = _spPageContextInfo.webAbsoluteUrl.replace(_spPageContextInfo.webServerRelativeUrl,"");
var dispFormUrl = serverUrl + "/sites/billing/_layouts/15/DocSetHome.aspx?id="+fileDirRef;
var parentLink = listItem["FileRef"];
arrayofstrings = parentLink.split("/");
var billCycleFolderName = arrayofstrings[arrayofstrings.length-2];
arrayofstrings.pop();
var hyperLink = '' + billCycleFolderName + '';
listItem["Bill Cycle"] = hyperLink;
listItemsWithValues["Document Type"] = getContentTypeOfCurrentItem(listItem.ID.toString());
});
var enhancedListItemValues = spService.SpSearchQuery.EnhanceSearchResults(listItemsWithValues, enhanceFunctions);
deferred.resolve(listItemsWithValues);
}
}
})
.catch (function (message) {
deferred.reject();
});
return deferred.promise;
}
function addContentType(listItem){
//return getContentTypeOfCurrentItem(listItem.ID.toString());
return getContentTypeOfCurrentItem(listItem.ID.toString()).then(function(cname) {
listItem['Document Type'] = cname; //we add the doc type to each listItem, not only the last one
}).catch(function(error) {
$log.warn("Server error");
});
}
function getContentTypeOfCurrentItem(id) {
return new Promise(function (resolve, reject) {
var clientContext = new SP.ClientContext.get_current();
var oList = clientContext.get_web().get_lists().getByTitle("Bill Cycles");
var listItem2 = oList.getItemById(id);
listContentTypes = oList.get_contentTypes();
clientContext.load(listContentTypes);
clientContext.load(listItem2, 'ContentTypeId');
clientContext.executeQueryAsync(
function() {
$log.info("Successfully retrieved getContentTypeOfCurrentItemt");
var ctid = listItem2.get_item("ContentTypeId").toString();
var ct_enumerator = listContentTypes.getEnumerator();
while (ct_enumerator.moveNext()) {
var ct = ct_enumerator.get_current();
if (ct.get_id().toString() == ctid) {
var contentTypeName = ct.get_name();
}
}
return resolve(contentTypeName);
},
function(error, errorInfo) {
$log.warn("Retrieving getContentTypeOfCurrentItem failed");
return reject(errorInfo);
}
);
});
}
function GetRelatedBillingDocuments(selectProperties, currentBillCyclePath, clientCode, jobCodes, engagementCode, enhanceFunctions) {
$log.info("Retrieving related billing documents for bill cycle with path [" + currentBillCyclePath + "]");
var deferred = $q.defer();
var webUrl = _spPageContextInfo.webAbsoluteUrl;
// TODO: AND or OR?
var jobCodesFilter = spService.ExpandSearchFilterForEachValue("JobCodes", ":", jobCodes, false, false);
var engagementCodeFilter = "";
if (engagementCode != undefined && engagementCode != "") {
engagementCodeFilter = "EngagementCode:" + engagementCode;
}
if(jobCodesFilter && engagementCodeFilter) {
jobCodesFilter += " OR ";
}
// TODO: Add use of result source?
var queryText = "-Path:" + spService.AddQuotes(currentBillCyclePath) + ' AND -ContentType:"Bill Cycle" AND ClientCode:' + clientCode + " AND (" + jobCodesFilter + engagementCodeFilter + ")";
var searchQuery = new spService.SpSearchQuery(webUrl, queryText, selectProperties, config.ResultSourceName, config.ResultSourceLevel);
searchQuery
.ExecuteSearchQueryFetchAll() // returns deferred
.then(function (results) {
$log.info("Successfully retrieved search results");
var searchResults = spService.SpSearchQuery.EnhanceSearchResults(results, enhanceFunctions);
deferred.resolve(searchResults);
});
return deferred.promise;
}
ExecuteOrDelayUntilScriptLoaded(GetContext, 'sp.js');
}
]); // End Controller()
}()); // End IFFE
Promise is part of ES6 standard that is not fully supported by IE11, you can use babel-polyfill instead or use another librairy like q which is part of angularjs
In my web application, I have a requirement to play part of mp3 file. This is a local web app, so I don't care about downloads etc, everything is stored locally.
My use case is as follows:
determine file to play
determine start and stop of the sound
load the file [I use BufferLoader]
play
Quite simple.
Right now I just grab the mp3 file, decode it in memory for use with WebAudio API, and play it.
Unfortunately, because the mp3 files can get quite long [30minutes of audio for example] the decoded file in memory can take up to 900MB. That's a bit too much to handle.
Is there any option, where I could decode only part of the file? How could I detect where to start and how far to go?
I cannot anticipate the bitrate, it can be constant, but I would expect variable as well.
Here's an example of what I did:
http://tinyurl.com/z9vjy34
The code [I've tried to make it as compact as possible]:
var MediaPlayerAudioContext = window.AudioContext || window.webkitAudioContext;
var MediaPlayer = function () {
this.mediaPlayerAudioContext = new MediaPlayerAudioContext();
this.currentTextItem = 0;
this.playing = false;
this.active = false;
this.currentPage = null;
this.currentAudioTrack = 0;
};
MediaPlayer.prototype.setPageNumber = function (page_number) {
this.pageTotalNumber = page_number
};
MediaPlayer.prototype.generateAudioTracks = function () {
var audioTracks = [];
var currentBegin;
var currentEnd;
var currentPath;
audioTracks[0] = {
begin: 4.300,
end: 10.000,
path: "example.mp3"
};
this.currentPageAudioTracks = audioTracks;
};
MediaPlayer.prototype.show = function () {
this.mediaPlayerAudioContext = new MediaPlayerAudioContext();
};
MediaPlayer.prototype.hide = function () {
if (this.playing) {
this.stop();
}
this.mediaPlayerAudioContext = null;
this.active = false;
};
MediaPlayer.prototype.play = function () {
this.stopped = false;
console.trace();
this.playMediaPlayer();
};
MediaPlayer.prototype.playbackStarted = function() {
this.playing = true;
};
MediaPlayer.prototype.playMediaPlayer = function () {
var instance = this;
var audioTrack = this.currentPageAudioTracks[this.currentAudioTrack];
var newBufferPath = audioTrack.path;
if (this.mediaPlayerBufferPath && this.mediaPlayerBufferPath === newBufferPath) {
this.currentBufferSource = this.mediaPlayerAudioContext.createBufferSource();
this.currentBufferSource.buffer = this.mediaPlayerBuffer;
this.currentBufferSource.connect(this.mediaPlayerAudioContext.destination);
this.currentBufferSource.onended = function () {
instance.currentBufferSource.disconnect(0);
instance.audioTrackFinishedPlaying()
};
this.playing = true;
this.currentBufferSource.start(0, audioTrack.begin, audioTrack.end - audioTrack.begin);
this.currentAudioStartTimeInAudioContext = this.mediaPlayerAudioContext.currentTime;
this.currentAudioStartTimeOffset = audioTrack.begin;
this.currentTrackStartTime = this.mediaPlayerAudioContext.currentTime - (this.currentTrackResumeOffset || 0);
this.currentTrackResumeOffset = null;
}
else {
function finishedLoading(bufferList) {
instance.mediaPlayerBuffer = bufferList[0];
instance.playMediaPlayer();
}
if (this.currentBufferSource){
this.currentBufferSource.disconnect(0);
this.currentBufferSource.stop(0);
this.currentBufferSource = null;
}
this.mediaPlayerBuffer = null;
this.mediaPlayerBufferPath = newBufferPath;
this.bufferLoader = new BufferLoader(this.mediaPlayerAudioContext, [this.mediaPlayerBufferPath], finishedLoading);
this.bufferLoader.load();
}
};
MediaPlayer.prototype.stop = function () {
this.stopped = true;
if (this.currentBufferSource) {
this.currentBufferSource.onended = null;
this.currentBufferSource.disconnect(0);
this.currentBufferSource.stop(0);
this.currentBufferSource = null;
}
this.bufferLoader = null;
this.mediaPlayerBuffer = null;
this.mediaPlayerBufferPath = null;
this.currentTrackStartTime = null;
this.currentTrackResumeOffset = null;
this.currentAudioTrack = 0;
if (this.currentTextTimeout) {
clearTimeout(this.currentTextTimeout);
this.textHighlightFinished();
this.currentTextTimeout = null;
this.currentTextItem = null;
}
this.playing = false;
};
MediaPlayer.prototype.getNumberOfPages = function () {
return this.pageTotalNumber;
};
MediaPlayer.prototype.playbackFinished = function () {
this.currentAudioTrack = 0;
this.playing = false;
};
MediaPlayer.prototype.audioTrackFinishedPlaying = function () {
this.currentAudioTrack++;
if (this.currentAudioTrack >= this.currentPageAudioTracks.length) {
this.playbackFinished();
} else {
this.playMediaPlayer();
}
};
//
//
// Buffered Loader
//
// Class used to get the sound files
//
function BufferLoader(context, urlList, callback) {
this.context = context;
this.urlList = urlList;
this.onload = callback;
this.bufferList = [];
this.loadCount = 0;
}
// this allows us to handle media files with embedded artwork/id3 tags
function syncStream(node) { // should be done by api itself. and hopefully will.
var buf8 = new Uint8Array(node.buf);
buf8.indexOf = Array.prototype.indexOf;
var i = node.sync, b = buf8;
while (1) {
node.retry++;
i = b.indexOf(0xFF, i);
if (i == -1 || (b[i + 1] & 0xE0 == 0xE0 )) break;
i++;
}
if (i != -1) {
var tmp = node.buf.slice(i); //carefull there it returns copy
delete(node.buf);
node.buf = null;
node.buf = tmp;
node.sync = i;
return true;
}
return false;
}
BufferLoader.prototype.loadBuffer = function (url, index) {
// Load buffer asynchronously
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.responseType = "arraybuffer";
var loader = this;
function decode(sound) {
loader.context.decodeAudioData(
sound.buf,
function (buffer) {
if (!buffer) {
alert('error decoding file data');
return
}
loader.bufferList[index] = buffer;
if (++loader.loadCount == loader.urlList.length)
loader.onload(loader.bufferList);
},
function (error) {
if (syncStream(sound)) {
decode(sound);
} else {
console.error('decodeAudioData error', error);
}
}
);
}
request.onload = function () {
// Asynchronously decode the audio file data in request.response
var sound = {};
sound.buf = request.response;
sound.sync = 0;
sound.retry = 0;
decode(sound);
};
request.onerror = function () {
alert('BufferLoader: XHR error');
};
request.send();
};
BufferLoader.prototype.load = function () {
for (var i = 0; i < this.urlList.length; ++i)
this.loadBuffer(this.urlList[i], i);
};
There is no way of streaming with decodeAudioData(), you need to use MediaElement with createMediaStreamSource and run your stuff then. decodeAudioData() cannot stream on a part.#zre00ne And mp3 will be decoded big!!! Verybig!!!
My idea is download chunks a huge file from server.
Chunks stored into an IndexedDB.
After download all chunks, merge all records into one (as SQL SELECT * FROM XXX ...).
Save into disk "saveAs()" or create URL to IndexedDB...
(Or any idea?)
I do not know how to do step 2. and 3.
(Below is an example of storing 10,000 records in the DB and the expected output after step 2. should be SusanSusanSusanSusanSusan...)
if (transaction) {
transaction.oncomplete = function () {
}
transaction.onabort = function () {
writeToConsoleScreen("transaction aborted.");
localDatabase.db.close();
}
transaction.ontimeout = function () {
writeToConsoleScreen("transaction timeout.");
localDatabase.db.close();
}
var store = transaction.objectStore(osTableName);
if (store) {
var req;
var customer = {};
// create ten thousand records
for (var loop = 0; loop < 10000; loop++) {
customer = {};
customer.fname = 'Susan';
req = store.add(customer);
req.onsuccess = function (ev) {
}
req.onerror = function (ev) {
writeToConsoleScreen("Failed to add record." + " Error: " + ev.message);
}
}
}
}
<!DOCTYPE html>
<script>
var open = indexedDB.open('chunks-example');
open.onupgradeneeded = function() {
// Create schema if necessary
var db = open.result;
db.createObjectStore('chunks');
};
// 1. Chunks stored into an IndexedDB.
open.onsuccess = function() {
var db = open.result;
var tx = db.transaction('chunks', 'readwrite');
var store = tx.objectStore('chunks');
for (var i = 0; i < 10; ++i) {
// For realz, this would be via
// XMLHttpRequest.response and async.
var chunk = new Blob(['chunk ' + i + '\n'],
{type: 'application/octet-stream'});
store.put(chunk, i);
}
tx.oncomplete = function() { merge(db); };
};
// 2. After "download" all chunks, merge all records into one
function merge(db) {
var tx = db.transaction('chunks');
var store = tx.objectStore('chunks');
var chunks = [];
var request = store.openCursor();
request.onsuccess = function() {
var cursor = request.result;
if (cursor) {
chunks.push(cursor.value);
cursor.continue();
} else {
saveAs('myfile', new Blob(chunks,
{type: 'application/octet-stream'}));
}
};
}
// 3. Save into disk "saveAs()"
function saveAs(filename, blob) {
var a = document.documentElement.appendChild(document.createElement('a'));
a.href = URL.createObjectURL(blob);
a.download = filename;
a.click();
a.parentElement.remove(a);
}
</script>