Lotus notes automation from browser - javascript

I have been trying to automate Lotus Notes mail fillup from a browser interface.
After refering to Richard Schwartz's answer, i came up with this piece of code using the Lotus.NotesSession class.
function SendScriptMail() {
var mToMail = document.getElementById('txtMailId').value
var mSub = document.getElementById('txtSubject').value
var mMsg = document.getElementById('txtContent').value
var Password = "yyy"
alert("1");
var MailFileServer = "xxx.com"
var MailFile = "C:\Program Files\IBM\Lotus\Notes\mail\user.nsf"
alert("2")
var Session;
var Maildb;
var UI;
var NewMail;
var From = "user#xxx.com"
try {
alert("3")
// Create the Activex object for NotesSession
Session = new ActiveXObject("Lotus.NotesSession");
alert("4")
if (Session == null) {
throw ("NoSession");
} else {
Session.Initialize(Password);
// Get mail database
Maildb = Session.GetDatabase(MailFileServer, MailFile);
alert("5")
if (Maildb == null) {
throw ("NoMaildb");
} else {
NewMail = MailDB.CreateDocument();
if (MailDoc == null) {
throw ('NoMailDoc');
} else {
// Populate the fields
NewMail.AppendItemValue("Form", "Memo")
NewMail.AppendItemValue("SendTo", mToMail)
NewMail.AppendItemValue("From", From)
NewMail.AppendItemValue("Subject", mSub)
NewMail.AppendItemValue("Body", mMsg)
NewMail.Save(True, False)
NewMail.Send(False)
}
}
}
} catch (err) {
// feel free to improve error handling...
alert('Error while sending mail');
}
}
But now, alerts 1,2,3 are being trigerrd, and then the counter moves to the catch block. The lotus notes session is not being started.
In a powershell script that I was previously looking at there was a code regsvr32 "$NotesInstallDir\nlsxbe.dll" /s that was used before the Session = new ActiveXObject("Lotus.NotesSession");. Is there something similar in javascript too, if so how do i invoke that dll.
I think I've realised where I am going wrong. According to me, upto alert("5") things are good. But since Lotus.NotesSession doesn't have a CreateDocument() method, it is throwing the error. I am not sure how to create the document and populate the values though.

Since you've chosen to use the Notes.NotesUIWorkspace class, you are working with the Notes client front-end. It's running, and your users see what's happening on the screen. Are you aware that there's a set of back-end classes (rooted in Lotus.NotesSession) instead of Notes.NotesSession and Notes.NotesUIWorkspace) that work directly with Notes database data, without causing the Notes client to grab focus and display everything that you're doing?
Working with the front-end means that in some cases (depending on the version of Notes that you are working with) you're not going to be working directly with the field names that are standard in Notes messages as stored and as seen in the back-end. You're going to be working with names used as temporary inputs in the form that is used to view and edit the message. You can see these names by using Domino Designer to view the Memo form.
Instead of using 'SendTo', try using:
MailDoc.Fieldsettext('EnterSendTo', mToMail)
Regarding the Body field, there's no temporary field involved, however you haven't really explained the difficulty you are having. Do you not know how to display the interface that you want in the browser? Do you not know how to combine different inputs into a single FieldSetText call? Or are you just dissatisfied with the fact that FieldSetText can't do any fancy formatting? In the latter case, to get more formatting capability you may want to switch to using the back-end classes, which give you access to the NotesRichTextItem class, which has more formatting capabilities.

Related

Javascript Logging function

For a little project I'm coding besides my job I wanted to make a log function so I can output simple things into a textfile like the user input and possible errors that occured.
I wanted to make this log a simple .txt.
The problems I ran into were the following:
I want to check if the file already exists if not, create a new one;
Then when the file exists I want to write below the existing contents.
This is what I got so far:
/*
Form:
\r\n
\r\n *** logged (<dd.mm.yyyy> || <hh:mm:ss>) ***
\r\n
\r\n <pMessage>
\r\n
\r\n *** log end ***
*/
function log(pMessage)
{
var logPath = "../../Logs/SiteLog.txt";
}
I know it is not much because I haven't done anything there yet. So i basically need three things: Checking if the file exists, creating a file, editing the file.
Thanks in advance for your help.
If this is client side, the browser will prevent you from writing to the file system. If this is strictly for your own testing purposes locally, you could write to window.localStorage
https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
This would allow you to read and write from a local storage that the browser caches based on domain
function read (name) {
return window.localStorage.getItem(name)
}
function write (name, value) {
var report = window.localStorage.getItem(name) + '\n' + value
window.localStorage.setItem(name, report)
return report
}

Meteor: Best practice for modifying document data with user data

Thanks for looking at my question. It should be easy for anyone who has used Meteor in production, I am still at the learning stage.
So my meteor setup is I have a bunch of documents with ownedBy _id's reflecting which user owns each document (https://github.com/rgstephens/base/tree/extendDoc is the full github, note that it is the extendDoc branch and not the master branch).
I now want to modify my API such that I can display the real name of each owner of the document. On the server side I can access this with Meteor.users.findOne({ownedBy}) but on the client side I have discovered that I cannot do this due to Meteor security protocols (a user doesnt have access to another user's data).
So I have two options:
somehow modify the result of what I am publishing to include the user's real name on the server side
somehow push the full user data to the clientside and do the mapping of the _id to the real names on the clientside
what is the best practice here? I have tried both and here are my results so far:
I have failed here. This is very 'Node' thinking I know. I can access user data on clientside but Meteor insists that my publications must return cursors and not JSON objects. How do I transform JSON objects into cursors or otherwise circumvent this publish restriction? Google is strangely silent on this topic.
Meteor.publish('documents.listAll', function docPub() {
let documents = Documents.find({}).fetch();
documents = documents.map((x) => {
const userobject = Meteor.users.findOne({ _id: x.ownedBy });
const x2 = x;
if (userobject) {
x2.userobject = userobject.profile;
}
return x2;
});
return documents; //this causes error due to not being a cursor
}
I have succeeded here but I suspect at the cost of a massive security hole. I simply modified my publish to be an array of cursors, as below:
Meteor.publish('documents.listAll', function docPub() {
return [Documents.find({}),
Meteor.users.find({}),
];
});
I would really like to do 1 because I sense there is a big security hole in 2, but please advise on how I should do it? thanks very much.
yes, you are right to not want to publish full user objects to the client. but you can certainly publish a subset of the full user object, using the "fields" on the options, which is the 2nd argument of find(). on my project, i created a "public profile" area on each user; that makes it easy to know what things about a user we can publish to other users.
there are several ways to approach getting this data to the client. you've already found one: returning multiple cursors from a publish.
in the example below, i'm returning all the documents, and a subset of all the user object who own those documents. this example assumes that the user's name, and whatever other info you decide is "public," is in a field called publicInfo that's part of the Meteor.user object:
Meteor.publish('documents.listAll', function() {
let documentCursor = Documents.find({});
let ownerIds = documentCursor.map(function(d) {
return d.ownedBy;
});
let uniqueOwnerIds = _.uniq(ownerIds);
let profileCursor = Meteor.users.find(
{
_id: {$in: uniqueOwnerIds}
},
{
fields: {publicInfo: 1}
});
return [documentCursor, profileCursor];
});
In the MeteorChef slack channel, #distalx responded thusly:
Hi, you are using fetch and fetch return all matching documents as an Array.
I think if you just use find - w/o fetch it will do it.
Meteor.publish('documents.listAll', function docPub() {
let cursor = Documents.find({});
let DocsWithUserObject = cursor.filter((doc) => {
const userobject = Meteor.users.findOne({ _id: doc.ownedBy });
if (userobject) {
doc.userobject = userobject.profile;
return doc
}
});
return DocsWithUserObject;
}
I am going to try this.

Restrict number of users in a session in vline

Can I restrict the number of users in a session? Is there any option in vline.session? Please guide if this can be done by writing custom javascript.
EDIT:
Referring to https://vline.com/developer/docs/vline.js/vline.MediaSession#examples, a two party call controller is explained. I want to ask is there any way to restrict number of users in a session? There is no such option present in session's docs. Is it supported as a part of the API?
If this can be done using custom javascript, how?
As a part of my effort, I have tried to implement vline-django examples, but could not find a section in documentation that addresses this issue.
EDIT 2: The code that is working for me.
var vlineClient = (function(){
var client, session,
authToken = {{ user|vline_auth_token|safe }},
serviceId = {% vline_service_id %},
profile = {{ user|vline_user_profile|safe }};
// Create vLine client
window.vlineClient = client = vline.Client.create({"serviceId": serviceId, "ui": true});
// Add login event handler
client.on('login', onLogin);
// Do login
client.login(serviceId, profile, authToken);
function onLogin(event) {
session = event.target;
// Find and init call buttons
var callButtons = document.getElementsByClassName('callbutton');
for (var i=0; i < callButtons.length; ++i) {
initCallButton(callButtons[i]);
}
}
// add event handlers for call button
function initCallButton(button) {
var userId = button.getAttribute('data-userid');
// fetch person object associated with username
session.getPerson(userId).done(function(person) {
// update button state with presence
function onPresenceChange() {
button.setAttribute('data-presence', person.getPresenceState());
}
// set current presence
onPresenceChange();
// handle presence changes
person.on('change:presenceState', onPresenceChange);
// start a call when button is clicked
button.addEventListener('click', function() {
person.startMedia();
});
});
}
return client;
})();
How do I move ahead?
Reference: https://vline.com/developer/docs/vline.js/
if i understand correctly the OP is trying to make a multi-user chat room - this is also what i wanted to do with vline and because i wanted a/v chat as well the number of participants should obviously be capped - it appears that the term 'session' is causing the confusion here so i will refrain from using it
i worked around this by creating a fixed number of users in a db and handling authentication
myself before actually associating a visitor with one of the prepared users - so some javascript logs in each visitor as one of those existing 'anonymous' users and sets only a logged_in? flag in the db so that the next visitor will log in as the next vacant user slot and when all slots are occupied the visitor gets a "chat room full - try again later" response
probably not the most elegant solution - for example the visitor chosen usernames are stored client-side and must be re-assigned to one of the user-definable vline session vars so it can be passed along with each message and the logged_in? db flag needs to be reset when the user exits
note that this was almost a year ago so im a bit foggy on exactly what i did but my app (rails) in up on github if youre interested to fork it - also i should add that although this sort of thing wasnt strictly supported by the vline API at the time there were at least some hints that some analogous feature was being prepared for so there may be some API support for this now - i did notice since then that they have released a "chat room demo" app on github and i would expect that their implementation is more concise than mine so you may want to look at that first - my app tho does have a mostly complete UI with gravatars and collaboration is welcomed

'POST 400 bad request' error when updating parse.com table

I am getting a 'POST 400 bad request' error when trying to update a table on parse.com using JS SDK.
var Gallery = Parse.Object.extend("Gallery");
var gallery = new Gallery();
var activeArtworks = 0;
gallery.save(null, {
success: function(gallery) {
gallery.set("activeArtworks", activeArtworks);
gallery.save();
}
});
Please help!
I can't see how this is any different to the sample code provided by parse here
The sample code you reference creates all of its parameters before setting up the save() method. This is the step you're missing; you need to create the activeArtworks parameter on your gallery instance. Your update is failing because you're trying to update a property that was never created.
I would expect this code to work, though I didn't test it because parse.com requires you to set up an account to run any code, which is silly, and I didn't feel like creating one:
var Gallery = Parse.Object.extend("Gallery");
var gallery = new Gallery();
var activeArtworks = 0;
gallery.activeArtworks = []; // or some more appropriate default if you have one.
gallery.save(null, {
success: function(gallery) {
gallery.set("activeArtworks", activeArtworks);
gallery.save();
}
});
It might also be worth checking if there's any info in the headers of the 400 error (the debug console in your browser will show these in its Network tab). I would expect Parse to give you some sort of information to help you debug issues, and that's the only place it would fit for an HTTP error.
If you had use user.logIn(callback) function with Parse JS, maybe your session invalid. Please check your callback function error code, if error.code==209 (invalid session token), use Parse.User.logOut() and re-login again.
Like this:
if (error.code == 209) {
Parse.User.logOut();
user.logIn(loginCallback);
return;
}
I had this same issue and it was resolved after realising that the data type that I was posting was different to that specified in the columns that I had created.
In my case, I was trying to save an object when I had specified an array when creating the column in the class.

delete row from result set in web sql with javascript

I understand that the result set from web sql isn't quite an array, more of an object? I'm cycling through a result set and to speed things up I'd like to remove a row once it's been found. I've tried "delete" and "splice", the former does nothing and the latter throws an error. Here's a piece of what I'm trying to do, notice the delete on line 18:
function selectFromReverse(reverseRay,suggRay){
var reverseString = reverseRay.toString();
db.transaction(function (tx) {
tx.executeSql('SELECT votecount, comboid FROM counterCombos WHERE comboid IN ('+reverseString+') AND votecount>0', [], function(tx, results){
processSelectFromReverse(results,suggRay);
});
}, function(){onError});
}
function processSelectFromReverse(results,suggRay){
var i = suggRay.length;
while(i--){
var j = results.rows.length;
while(j--){
console.log('searching');
var found = 0;
if(suggRay[i].reverse == results.rows.item(j).comboid){
delete results.rows.item(j);
console.log('found');
found++;
break;
}
}
if(found == 0){
console.log('lost');
}
}
}
Actually you use DELETE sql command to delete the record from the database. For example:
tx.executeSql('DELETE FROM counterCombos WHERE comboid = ?', [comboid], success, error);
processSelectFromReverse could modified to include tx as input like
processSelectFromReverse(results,suggRay,tx)
Web SQL has been dropped from the HTML5 workup for almost 2 years now and isn't supported. Web Storage and Indexed DB have taken its place.
Your syntax for deleting objects: delete object; is correct. It's not used often in JavaScript but I have used it and that is the correct usage.
Using web-storage (more commonly called local storage) you would instansiate a localStorage object which comes with the method removeItem(item key), already built in.
You can see more at the above link on webstorage or go here for a tutorial.
If your concern is IOS or Android, making an application that is wrapped natively would allow you to create a javascript interface. From this interface you can access (for android) sqlite and create a nice, query0able solution. The downside is this would require people downloading your application rather then accessing a site.
http://caniuse.com/indexeddb
indexeddb support is growing rather slowly. With a proper coding style you could probably use local storage (as mentioned in the above comments) with pretty respectable speeds.

Categories