I want to create a line notify which can send the event detail from my google calendar everyday.
I can get the title, description, location...etc, but I don't see the conference data in calendar API.
I use Google Apps Script to run the code.
Here is my code.
const Now = new Date();
const Start = new Date(new Date().setHours(0, 0, 0, 0));
const End = new Date(new Date().setHours(23, 59, 59, 999));
const calendarData = calendar.getEvents(Start, End);
function Notify() {
var NotifyContents = '';
var i = 1;
calendarData.forEach(item =>{
if (Now <= item.getStartTime()) {
NotifyContents += (item.getTitle() != "") ? ("\n" + i+". "+ item.getTitle() + "\n") : ("\n\nNo Title\n");
NotifyContents += (item.getDescription() != "") ? item.getDescription() + "\n" : "";
NotifyContents += (item.getStartTime() != "" && item.getEndTime() != "") ? "Time:" + item.getStartTime().toLocaleTimeString() + "-" + item.getEndTime().toLocaleTimeString() + "\n": "";
NotifyContents += (item.getconferencedata() != "") ? ("\n" + i+". "+ item.getconferencedata()) : ("No Conference\n");
i++;
}
}
)
if (typeof NotifyContents === 'string' && NotifyContents.length === 0) {
return;
}
NotifyTokens.forEach(function(value){
UrlFetchApp.fetch("https://notify-api.line.me/api/notify", {
"method" : "post",
"payload" : {"message" : NotifyContents},
"headers" : {"Authorization" : "Bearer " + value}
});
});
}
Reference - Calendar API Link
In order to retrieve the meet link from the event, it seems that in the current stage, Calendar API is required to be used. When this is reflected in your script, how about the following modification?
Modified script:
Before you use this script, please enable Calendar API at Advanced Google services.
From:
var NotifyContents = '';
var i = 1;
calendarData.forEach(item => {
if (Now <= item.getStartTime()) {
NotifyContents += (item.getTitle() != "") ? ("\n" + i + ". " + item.getTitle() + "\n") : ("\n\nNo Title\n");
NotifyContents += (item.getDescription() != "") ? item.getDescription() + "\n" : "";
NotifyContents += (item.getStartTime() != "" && item.getEndTime() != "") ? "Time:" + item.getStartTime().toLocaleTimeString() + "-" + item.getEndTime().toLocaleTimeString() + "\n" : "";
NotifyContents += (item.getconferencedata() != "") ? ("\n" + i + ". " + item.getconferencedata()) : ("No Conference\n");
i++;
}
}
)
To:
const eventList = Calendar.Events.list(calendar.getId(), { timeMin: Start.toISOString(), timeMax: End.toISOString(), maxResults: 2500 }).items.reduce((o, e) => (o[e.id] = e.conferenceData.entryPoints.map(({ uri }) => uri).join(","), o), {});
var NotifyContents = '';
var i = 1;
calendarData.forEach(item => {
if (Now <= item.getStartTime()) {
NotifyContents += (item.getTitle() != "") ? ("\n" + i + ". " + item.getTitle() + "\n") : ("\n\nNo Title\n");
NotifyContents += (item.getDescription() != "") ? item.getDescription() + "\n" : "";
NotifyContents += (item.getStartTime() != "" && item.getEndTime() != "") ? "Time:" + item.getStartTime().toLocaleTimeString() + "-" + item.getEndTime().toLocaleTimeString() + "\n" : "";
var eventId = item.getId().split("#")[0];
NotifyContents += eventList[eventId] != "" ? ("\n" + i + ". " + eventList[eventId]) : ("No Conference\n");
i++;
}
});
In this modification, it supposes that calendar has already been declaread. Please be careful about this.
Reference:
Events: list
Related
I'm using the following script to export Google Ads data from my account, but I am stuck with Google's pre-set date ranges and can't figure out how/if it's possible to jimmy these. Ideal date range would be year to date, with the report refreshing each day and adding on a fresh day's data, but would also be interested if we can get all time to work.
I'm a coding novice, so apologies in advance.
Script:
function main() {
var currentSetting = new Object();
currentSetting.ss = SPREADSHEET_URL;
// Read Settings Sheet
var settingsSheet = SpreadsheetApp.openByUrl(currentSetting.ss).getSheetByName(SETTINGS_SHEET_NAME);
var rows = settingsSheet.getDataRange();
var numRows = rows.getNumRows();
var numCols = rows.getNumColumns();
var values = rows.getValues();
var numSettingsRows = numRows - 1;
var sortString = "";
var filters = new Array();
for(var i = 0; i < numRows; i++) {
var row = values[i];
var settingName = row[0];
var settingOperator = row[1];
var settingValue = row[2];
var dataType = row[3];
debug(settingName + " " + settingOperator + " " + settingValue);
if(settingName.toLowerCase().indexOf("report type") != -1) {
var reportType = settingValue;
} else if(settingName.toLowerCase().indexOf("date range") != -1) {
var dateRange = settingValue;
} else if(settingName.toLowerCase().indexOf("sort order") != -1) {
var sortDirection = dataType || "DESC";
if(settingValue) var sortString = "ORDER BY " + settingValue + " " + sortDirection;
var sortColumnIndex = 1;
}else {
if(settingOperator && settingValue) {
if(dataType.toLowerCase().indexOf("long") != -1 || dataType.toLowerCase().indexOf("double") != -1 || dataType.toLowerCase().indexOf("money") != -1 || dataType.toLowerCase().indexOf("integer") != -1) {
var filter = settingName + " " + settingOperator + " " + settingValue;
} else {
if(settingValue.indexOf("'") != -1) {
var filter = settingName + " " + settingOperator + ' "' + settingValue + '"';
} else if(settingValue.indexOf("'") != -1) {
var filter = settingName + " " + settingOperator + " '" + settingValue + "'";
} else {
var filter = settingName + " " + settingOperator + " '" + settingValue + "'";
}
}
debug("filter: " + filter)
filters.push(filter);
}
}
}
// Process the report sheet and fill in the data
var reportSheet = SpreadsheetApp.openByUrl(currentSetting.ss).getSheetByName(REPORT_SHEET_NAME);
var rows = reportSheet.getDataRange();
var numRows = rows.getNumRows();
var numCols = rows.getNumColumns();
var values = rows.getValues();
var numSettingsRows = numRows - 1;
// Read Header Row and match names to settings
var headerNames = new Array();
var row = values[0];
for(var i = 0; i < numCols; i++) {
var value = row[i];
headerNames.push(value);
//debug(value);
}
if(reportType.toLowerCase().indexOf("performance") != -1) {
var dateString = ' DURING ' + dateRange;
} else {
var dateString = "";
}
if(filters.length) {
var query = 'SELECT ' + headerNames.join(",") + ' FROM ' + reportType + ' WHERE ' + filters.join(" AND ") + dateString + " " + sortString;
} else {
var query = 'SELECT ' + headerNames.join(",") + ' FROM ' + reportType + dateString + " " + sortString;
}
debug(query);
var report = AdWordsApp.report(query);
try {
report.exportToSheet(reportSheet);
var subject = "Your " + reportType + " for " + dateRange + " for " + AdWordsApp.currentAccount().getName() + " is ready";
var body = currentSetting.ss + "<br>You can now add this data to <a href='https://www.optmyzr.com'>Optmyzr</a> or another reporting system.";
MailApp.sendEmail(EMAIL_ADDRESSES, subject, body);
Logger.log("Your report is ready at " + currentSetting.ss);
Logger.log("You can include this in your scheduled Optmyzr reports or another reporting tool.");
} catch (e) {
debug("error: " + e);
}
}
function debug(text) {
if(DEBUG) Logger.log(text);
}
I've tried overwriting the data validation in the host spreadsheet, but think I need to amend the script itself also.
I'm doing an API and the following code is used to retrieve users depending on filter. ( POST /users/search )
At the end of the function, I'm working with "LIMIT" and "OFFSET" in SQL because I want that nobody can retrieve more than 10 entries.
The code to generate the SQL query from WHERE is terrible. I am looking to improve it but I can't find a more effective way. Do you have any ideas?
function getSqlFilter(filter) {
var filterSql = '';
if (!util.isEmpty(filter)) {
var isFiltered = false;
if (filter.userId != null) {
if (!isFiltered) filterSql += ' WHERE ';
if (isFiltered) filterSql += ' AND ';
filterSql += 'pk_user in (' + filter.userId.toString() + ')';
isFiltered = true;
}
if (filter.username != null) {
if (!isFiltered) filterSql += ' WHERE ';
if (isFiltered) filterSql += ' AND ';
filterSql += 'username in (' + filter.username.toString() + ')';
isFiltered = true;
}
if (filter.email != null) {
if (!isFiltered) filterSql += ' WHERE ';
if (isFiltered) filterSql += ' AND ';
filterSql += 'email in (' + filter.email.toString() + ')';
isFiltered = true;
}
if (filter.society != null) {
if (!isFiltered) filterSql += ' WHERE ';
if (isFiltered) filterSql += ' AND ';
filterSql += 'society in (' + filter.society.toString() + ')';
isFiltered = true;
}
if (filter.firstname != null) {
if (!isFiltered) filterSql += ' WHERE ';
if (isFiltered) filterSql += ' AND ';
filterSql += 'firstname in (' + filter.firstname.toString() + ')';
isFiltered = true;
}
if ((filter.start != null) && (filter.end != null)) {
filter.start -= 1;
var limit = filter.end - filter.start;
if (limit <= 10) {
filterSql += 'LIMIT ' + limit + ' OFFSET ' + filter.start;
}
} else if (filter.start != null) {
filterSql += 'LIMIT 10 OFFSET ' + filter.start;
} else {
filterSql += 'LIMIT 10 OFFSET 0';
}
} else {
filterSql += 'LIMIT 10 OFFSET 0';
}
return filterSql;
}
Thanks for helping
You can simplify the redundant logic and utilize ES6 features for shorter syntax.
function getSqlFilter(filter = {}) {
const searches = Object.keys(filter);
const sLength = searches.length
let filterSql = sLength === 0 ? "LIMIT 10 OFFSET 0" : "WHERE ";
const map = {
userId: "pk_user",
username: "username",
email: "email",
society: "society"
}
const { start, end } = filter;
const hasOnlyStart = start !== undefined && end === undefined;
const hasStartAndEnd = start !== undefined && end !== undefined;
if (sLength) {
filterSql += searches.map(search => {
if(search === "start") {
return hasOnlyStart ? `LIMIT ${filter[search]} OFFSET 10` : "";
}
if(search === "end") {
return hasStartAndEnd ? `LIMIT ${filter[search]} OFFSET ${end - start}` : "";
}
return `${map[search]} in (${filter[search].toString()})`;
}).join(' AND ');
}
return filterSql;
}
I normally do this by starting with an always true condition
let filter= `...
WHERE 1 = 1`
Then you can simply append the filter
if (filter.username != null) {
filter += ' AND username in (' + filter.username.toString() + ')'
}
...
Hope this helps.
It is my anwser:
function getSqlFilter(filter) {
let sql = '';
let start = parseInt(filter.start);
let end = parseInt(filter.end);
delete filter.start;
delete filter.end;
const conditions = [];
const validKey = [...your key];
for (const key in filter){
if(validKey.indexOf(key) !== -1){
if(key === 'userId') conditions.push(`pk_user in (${filter[key].toString()})`);
else conditions.push(`${key} in (${filter[key].toString()})`);
}
}
if(conditions.length){
sql = ` WHERE ${conditions.join(' AND ')}`;
}
let limit = 10;
if (start) {
if(start < 0) start = 0;
if (end) {
let be_limit = start - end + 1;
if(be_limit <= 10 && be_limit >= 0) limit = be_limit;
}
} else {
start = 0;
}
sql += ` LIMIT ${limit} OFFSET ${start}`;
return sql;
}
If you don't want to change filter, please clone it before delete props.
Does the p:calendar component in Primefaces support sorting the year dropdownlist? By default, it is sorted by ascending, but how about if I want to sort it by descending? I've tried to implement it by using javascript but unfortunately the sort was gone after I selected an option in the dropdownlist.
You can use yearrange attribute. But you need to change/override something to make it works.
I see Primefaces calendar which is using datepicker and datepicker just support yearrange ascending. So I think you can do like that.
<p:calendar yearrange="2027:2017"... />
And override something that datapicker can support new yearrange, like (just my short sample)
$.datepicker._generateMonthYearHeader = function(inst, drawMonth, drawYear, minDate, maxDate,
secondary, monthNames, monthNamesShort) {
var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
changeMonth = this._get(inst, "changeMonth"),
changeYear = this._get(inst, "changeYear"),
showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
html = "<div class='ui-datepicker-title'>",
monthHtml = "";
// month selection
if (secondary || !changeMonth) {
monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
} else {
inMinYear = (minDate && minDate.getFullYear() === drawYear);
inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
for (month = 0; month < 12; month++) {
if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
monthHtml += "<option value='" + month + "'" +
(month === drawMonth ? " selected='selected'" : "") +
">" + monthNamesShort[month] + "</option>";
}
}
monthHtml += "</select>";
}
if (!showMonthAfterYear) {
html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : "");
}
// year selection
if (!inst.yearshtml) {
inst.yearshtml = "";
if (secondary || !changeYear) {
html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
} else {
// determine range of years to display
years = this._get(inst, "yearRange").split(":");
thisYear = new Date().getFullYear();
determineYear = function(value) {
var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
(value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
parseInt(value, 10)));
return (isNaN(year) ? thisYear : year);
};
year = determineYear(years[0]);
endYear = Math.max(year, determineYear(years[1] || ""));
year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
var startYear = determineYear(years[0]);
var absoluteEndYear = determineYear(years[1]);
if (startYear <= absoluteEndYear) {
for (; year <= endYear; year++) {
inst.yearshtml += "<option value='" + year + "'" +
(year === drawYear ? " selected='selected'" : "") +
">" + year + "</option>";
}
} else {
for (; startYear >= absoluteEndYear; startYear--) {
inst.yearshtml += "<option value='" + startYear + "'" +
(startYear === drawYear ? " selected='selected'" : "") +
">" + startYear + "</option>";
}
}
inst.yearshtml += "</select>";
html += inst.yearshtml;
inst.yearshtml = null;
}
}
html += this._get(inst, "yearSuffix");
if (showMonthAfterYear) {
html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml;
}
html += "</div>";
return html;}
Or you can write or extends more p:calendar component.
Hope that helps.
I wrote this code for application which is using nodejs:
socket.on('daneTury', function (dataa){
var gracze = "";
$("#informacje").hide("slow");
$("#odpowiedziGraczy").empty();
for(i = 0; i < $scope.gracze.length; i++){
var lp = i + 1;
var panstwo = typeof dataa[$scope.gracze[i].text].panstwo !== 'undefined' ? dataa[$scope.gracze[i].text].panstwo : "";
var miasto = typeof dataa[$scope.gracze[i].text].miasto !== 'undefined' ? dataa[$scope.gracze[i].text].miasto : "";
var imie = typeof dataa[$scope.gracze[i].text].imie !== 'undefined' ? dataa[$scope.gracze[i].text].imie : "";
var rzecz = typeof dataa[$scope.gracze[i].text].rzecz !== 'undefined' ? dataa[$scope.gracze[i].text].rzecz : "";
var samochod = typeof dataa[$scope.gracze[i].text].samochod !== 'undefined' ? dataa[$scope.gracze[i].text].samochod : "";
gracze += "<tr><td>" + lp + "</td>" + "<td>" + $scope.gracze[i].text + "</td><td>" + panstwo + "</td><td><img id='wrong' src='img/wrong.png' data-ng-click='zle()' alt='wrong'></td><td>" + miasto + "</td><td><img id='wrong' src='img/wrong.png' alt='wrong'></td><td>" + rzecz + "</td><td><img id='wrong' src='img/wrong.png' alt='wrong'></td><td>" + imie + "</td><td><img id='wrong' src='img/wrong.png' alt='wrong'></td><td>" + samochod + "</td><td><img id='wrong' src='img/wrong.png' alt='wrong'></td></tr>";
}
$("#odpowiedziGraczy").append("<strong>Odpowiedzi reszty graczy:</strong><div class='table-responsive'><table class='table table-striped'><thead><tr><th>#</th><th>Nik</th><th>Panstwo</th><th></th><th>Misato</th><th></th><th>Rzecz</th><th></th><th>Imie</th><th></th><th>Samochod</th><th></th></tr></thead><tbody>" + gracze + "</tbody></table></div>");
$("#odpowiedziGraczy").show("slow");
});
My question is about: <img id='wrong' src='img/wrong.png' alt='wrong'>. Why when i clicked on this image function "zle" doesn't work?
You have to $compile elements you create dynamically, to make ng-click or other angular directives work.
After $("#odpowiedziGraczy").show("slow"); you should use:
$compile(angular.element("#odpowiedziGraczy").contents())(scope);
Don't forget to inject $compile service into your directive/controller.
More about $compile: https://docs.angularjs.org/api/ng/service/%24compile
Here's what I hope is a quick question...
I am trying to set a cookie that can be used sitewide. I'm creating a lead generation type site. I want users to fill out a form in order to access exclusive information. Once they fill out the form, they have access to the info.
I am dropping a cookie when they user submits the form so that they can just get straight to the content the next time they visit the site. The form they fill out is in the sidebar of every page on the site. When the user fills out the form on one page, they shouldn't see it on ANY page of the site.
Everything is working, except for the sitewide bit. I think the issue is in this bit of code:
function set_cookie(name, value, expires, path, domain, secure){
if (!expires){expires = new Date()}
document.cookie = name + "=" + escape(value) +
((expires == null) ? "" : "; expires=" + expires.toGMTString()) +
((path == null) ? "" : "; path=" + path) +
((domain == null) ? "" : "; domain=" + domain) +
((secure == null) ? "" : "; secure");
}
But here's the full code below. THANKS SO MUCH!
<script type="text/javascript">
<!--
cookie_name="landasp"
expdays=365
// An adaptation of Dorcht's cookie functions.
function set_cookie(name, value, expires, path, domain, secure){
if (!expires){expires = new Date()}
document.cookie = name + "=" + escape(value) +
((expires == null) ? "" : "; expires=" + expires.toGMTString()) +
((path == null) ? "" : "; path=" + path) +
((domain == null) ? "" : "; domain=" + domain) +
((secure == null) ? "" : "; secure");
}
function get_cookie(name) {
var arg = name + "=";
var alen = arg.length;
var clen = document.cookie.length;
var i = 0;
while (i < clen) {
var j = i + alen;
if (document.cookie.substring(i, j) == arg){
return get_cookie_val(j);
}
i = document.cookie.indexOf(" ", i) + 1;
if (i == 0) break;
}
return null;
}
function get_cookie_val(offset){
var endstr = document.cookie.indexOf (";", offset);
if (endstr == -1)
endstr = document.cookie.length;
return unescape(document.cookie.substring(offset, endstr));
}
function delete_cookie(name,path,domain){
document.cookie = name + "=" +
((path == null) ? "" : "; path=" + path) +
((domain == null) ? "" : "; domain=" + domain) +
"; expires=Thu, 01-Jan-00 00:00:01 GMT";
}
function saving_cookie(){
var expdate = new Date ();
expdate.setTime (expdate.getTime() + (expdays*24*60*60*1000*30)); //set for one month
Data="cooked"
set_cookie(cookie_name,Data,expdate)
}
function get_cookie_data(){
inf=get_cookie(cookie_name)
if(!inf){
document.getElementById("display1").style.display="block"
}
else{
document.getElementById("display2").style.display="block"
}
}
// -->
</script>
You should specify a site wide path, if the path is not given:
((path == null) ? "; path=/" : "; path=" + path) +
You can debug the cookies using Firebug, just have a look at the set cookies.