Maximo 7.6.1.1:
I want to run a Maximo automation script by invoking a URL in a separate system.
Is it possible to do this?
This is a great use-case and something that we've been working through in the last few days.
Create automation script. - mine is called automation_api_test
Manually invoke it through the API using a browser to make sure that you can actually get it to run. (%servername%/maximo/oslc/script/automation_api_test?var1=1212321232&var2=1555&site=OPS&_lid=wilson&_lpwd=wilson)
Script it like you would your regular automation script. Here's one that can read in a few parameters from the URL and use those to perform operations in the core system.
importPackage(Packages.psdi.server);
importPackage(Packages.psdi.util.logging);
var resp = {};
// Get the Site ID from the Query Parameters
//var site = request.getQueryParam("site");
var var1 = request.getQueryParam("var1");
var var2 = request.getQueryParam("var2");
var site = request.getQueryParam("site");
//var zxqponum = request.getQueryParam("ponum");
//logger.debug(zxqprinter);
service.log("TESTING script Params" + request.getQueryParams());
service.log("var1 " + request.getQueryParam("var1"));
service.log("var2 " + request.getQueryParam("var2"));
//count the number of WO's in the site
var woset = MXServer.getMXServer().getMboSet("WORKORDER", request.getUserInfo());
woset.setQbe("SITEID","="+site);
var woCount = woset.count();
resp.wo_count = woCount;
woset.close();
// Get Total Count
resp.total = woCount;
//create the response - still not sure why I had to append the vars to a string.
resp.var1= "" + var1;
resp.var2= "" + var2;
resp.site= "" + site;
var responseBody = JSON.stringify(resp);
Here's an expanded version of Kasey's answer.
Create a sample automation script in Maximo:
Automation Scripts >> More Actions >> Create >> Script
Script [name]: HELLOWORLD
Script Language: js
Paste in this code:
//THIS IS JAVASCRIPT! NOT JYTHON!
//load("nashorn:mozilla_compat.js"); //More info about this here: https://stackoverflow.com/questions/57537142/maximo-js-automation-script-importpackage-is-not-defined
//importPackage(Packages.psdi.server);
//importPackage(Packages.psdi.util.logging);
var resp = {};
var var1 = request.getQueryParam("var1");
resp.var1= " " + var1 + " World!";
var responseBody = JSON.stringify(resp);
Click Create
Try out a URL:
This URL will send the word "Hello" to the automation script. The automation script will append the word " World!" onto "Hello".
The phrase, "Hello World!" is returned.
In a browser, run this URL: http://yourhostname:1234/maximo/oslc/script/helloworld?var1=Hello&_lid=wilson&_lpwd=wilson
Replace yourhostname with your host name
Replace 1234 with your port number
Replace maximo with the appropriate value.
The URL request should return this JSON object to the browser:
{"var1":" Hello World!"}
From there, create a hyperlink in a separate system (using the above URL). And click it to run the automation script.
If the last line in the script were to be deleted, nothing would be returned to the browser.
Note:
The URL only seems to work for me under the WILSON user. It doesn't work with my own user:
{"oslc:Error":{"oslc:statusCode":"401","spi:reasonCode":"BMXAA7901E","oslc:message":
"You cannot log in at this time. Contact the system administrator.","oslc:extendedError"
:{"oslc:moreInfo":{"rdf:resource":"http:\/\/something\/maximo\/oslc\
/error\/messages\/BMXAA7901E"}}}}
Best guess is: my user is not set up correctly.
Here's a really simple JavaScript example:
responseBody = "asdf";
Then just run the URL in a browser (or somewhere else like an automation script in Maximo or a Python script in GIS).
https://<<my host>>/maximo/oslc/script/testscript
It's pretty much the same for Python (no semi-colon):
responseBody = "asdf"
Related
I'm trying to parse a HTML to retrieve the value of tag, on my Google Apps Script code. contains line breaks in attributes, and appears more than once but I only want the first value. (In this case, only 'foo' is required.)
<b class="
"
>
foo
</b><b class="
"
>
var
</b>
On Google Apps Script, functions such as 'getElementByTagName' is not available. So I first though of using regexp but it's not the wise option here.
Does anyone have an idea on how I can move forward? Any comment/guess would be highly appreciated!
How about using XmlService for your situation as a workaround? At XmlService, even if there are several line breaks in the tags, the value can be retrieved. I think that there are several workarounds for your situation. So please think of this as one of them.
The flow of sample script is as follows.
Flow :
Add the header of xml and a root element tag to the html.
Parse the creates xml value using XmlService.
Retrieve the first value of tags using XmlService.
Sample script :
var html = '<b class="\n"\n>\nfoo\n</b><b class="\n"\n>\nvar\n</b>\n'; // Your sample value
var xml = '<?xml version="1.0"?><sampleContents>' + html + '</sampleContents>';
var res = XmlService.parse(xml).getRootElement().getChildren()[0].getText().trim();
Logger.log(res) // foo
Note :
In this sample script, your sample html was used. So if you use more complicated one, can you provide it? I would like to modify the script.
Reference :
XML Service
If this was not what you want, please tell me. I would like to modify it.
Edit 1 :
Unfortunately, for the value retrieved from the URL, above script cannot be used. So I used "Parser" which is a GAS library for your situation. The sample script is as follows.
Sample script :
var url = "https://www.booking.com/searchresults.ja.html?ss=kyoto&checkin_year=2018&checkin_month=10&checkin_monthday=1&checkout_year=2018&checkout_month=10&checkout_monthday=2&no_rooms=1&group_adults=1&group_children=0";
var html = UrlFetchApp.fetch(url).getContentText();
var res = Parser.data(html).from("<b class=\"\n\"\n>").to("</b>").build().trim();
Logger.log(res) // US$11
Note :
Before you run this script, please install "Parser". About the install of library, you can see it at here.
The project key of the library is M1lugvAXKKtUxn_vdAG9JZleS6DrsjUUV
References :
Parser
Managing libraries
google app script Exceeded memory limit
google script scrape parser with 2 classes with the same name
Edit 2 :
For your 2nd URL in your comment, it seems that the URL is different from your 1st one. And also your new URL has no tag of <b class=\"\n\"\n>. By this, the value you want cannot be retrieved. But from the 1st URL in your comment, I presumed about the value what you want. Please confirm the following script?
var url = "https://www.booking.com/searchresults.ja.html?ss=kyotogranvia&checkin_year=2018&checkin_month=10&checkin_monthday=1&checkout_year=2018&checkout_month=10&checkout_monthday=2&no_rooms=1&group_adults=1&group_children=0";
var html = UrlFetchApp.fetch(url).getContentText();
var res = Parser.data(html).from("<span class=\"lp-postcard-avg-price-value\">").to("</span>").build().trim();
Logger.log(res) // US$289
In my Jenkins step I have windows batch command which runs a java jar file (java -Dfile.encoding=UTF-8 -jar C:\Test1\Test.jar C:\Test\test.log) and output of which is a String value (verified Jenkins console the string is getting printed) . How will I use this string content and insert in the editable email content body so I can send this content as an email . I wouldn't want the whole Jenkins console in the email only this String. I would assume the string has to be set as an environment variable after the script runs . Not sure how exactly I can use EnvInjPlugin for my scenario if at all it can be.
Try to use pre-send script.
For example You have in log the string like: "this random integer should be in email content: 3432805"
and want to add randomly generated integer to email content.
Set the Default Content with whatever you want but add some
value which will be replaced. For example:
This is the random int from build.log: TO_REPLACE
Then click "Advanced Settings" and add Pre-send Script:
String addThisStringToContent = "";
build.getLog(1000).each() { line ->
java.util.regex.Pattern p = java.util.regex.Pattern.compile("random\\sinteger.+\\:\\s(\\d+)");
java.util.regex.Matcher m = p.matcher(line);
if (m.find()) {
addThisStringToContent = m.group(1);
}
}
if (addThisStringToContent == "") {
logger.println("Proper string not found. Email content has not been updated.");
} else {
String contentToSet = ((javax.mail.Multipart)msg.getContent()).getBodyPart(0).getContent().toString().replace("TO_REPLACE", addThisStringToContent);
msg.setContent(contentToSet, "text/plain");
}
where:
build.getLog(1000) - retrieves the last 1000 lines of build output.
Pattern.compile("random\\sinteger.+\\:\\s(\\d+)") - regex to find the proper string
"text/plain" - Content Type
String contentToSet = ((javax.mail.Multipart)msg.getContent()).getBodyPart(0).getContent().toString().replace("TO_REPLACE", addThisStringToContent); - replaces the string TO_REPLACE with your value
Hope it will help you.
Unfortunately I have not enough reputation to comment Alex' great answer, so I write a new answer. The call
msg.setContent(contentToSet, "text/plain")
has two disadvantages:
Special characters are garbled
An attachment gets lost
So I use the following call to set the modified text
((javax.mail.Multipart)msg.getContent()).getBodyPart(0).setContent(contentToSet, "text/plain;charset=UTF-8")
I can't find any reference to an API that enables Rest API clients to export an existing Google Sheet to a csv file.
https://developers.google.com/sheets/
I believe there should be a way to export them.
The following URL gives you the CSV of a Google spreadsheet per sheet. The sheet must be accessible by the public, by anyone with the link (unlisted).
The parameters you need to provide are:
sheet ID (that is simply the ID in the URL of a Google Spreadsheet https://docs.google.com/spreadsheets/d/{{ID}}/edit)
sheet name (that is simply the name of the sheet as given by the user)
https://docs.google.com/spreadsheets/d/{{ID}}/gviz/tq?tqx=out:csv&sheet={{sheet_name}}
With that URL you can run a GET-request to fetch the CSV.
Or paste it in your browser address bar.
You can use the Drive API to do this today -- see https://developers.google.com/drive/v3/web/manage-downloads#downloading_google_documents, however that will limit you to the first sheet of the document. The Sheets API doesn't expose exporting as CSV today, but may offer it in the future.
Nobody's mentioned gspread yet, so here's how I did it:
#open sheet
sheet = gc.open_by_key(sheet_id)
#select worksheet
worksheet = sheet.get_worksheet(0)
#download values into a dataframe
df = pd.DataFrame(worksheet.get_all_records())
#save dataframe as a csv, using the spreadsheet name
filename = sheet.title + '.csv'
df.to_csv(filename, index=False)
Firstly you should make document accessible for anyone. Then you get url. From this url you should extract long id composed from big and small letters and numbers. Then use this script.
#!/bin/bash
long_id="id_assigned_to_your_document"
g_id="number_assigned_to_card_in_google_sheet"
wget --output-document=temp.csv "https://docs.google.com/spreadsheets/d/$long_id/export?gid=$g_id&format=csv&id=$long_id"
If you use only one card in document, their number is: g_id="0"
The problem you will probably have is connected with strange spaces in obtained file. I use this second script to process it
#!/bin/bash
#Delete all lines beginning with a # from a file
#http://stackoverflow.com/questions/8206280/delete-all-lines-beginning-with-a-from-a-file
sed '/^#/ d' temp.csv |
# reomve spaces
# http://stackoverflow.com/questions/9953448/how-to-remove-all-white-spaces-from-a-given-text-file
tr -d "[:blank:]" |
# regexp "1,2" into 1.2
# http://www.funtoo.org/Sed_by_Example,_Part_2
sed 's/\"\([−]\?[0-9]*\),\([0-9]*\)\"/\1.\2/g' > out.csv
Update
As Sam mentioned, api is better solution. There is now great documentation on address:
https://developers.google.com/sheets/quickstart/php
With example that generate output having CSV structure.
If you don't have easy access to or familiarity with PHP, here's a very barebones Google Apps Script Web App that once deployed and the caller permission accepted, should allow clients with an appropriately scoped access token or api key to export an existing Google Sheet to a csv file. It takes a Google Sheets spreadsheet id and sheet name (and optional download filename) as query parameters, and returns the corresponding theoretically RFC 4180 compliant CSV file.
Further instructions on deploying an Apps Script project as a web app are here: https://developers.google.com/apps-script/guides/web#deploying_a_script_as_a_web_app.
You can deploy it and test it out easily in the browser just by visiting the "Current web app URL" (as provided when you publish as web app from the script editor), and accepting the consent screen, or even just visit the one that I deployed (configured to execute as the accessing user, and unverified/scary consent) at the example URL.
The tricky part (as usual) is getting the OAuth token or API key set up, but if you're already calling the Google Sheets V4 API, you've probably already got that dialed in. I used CURL to make sure that it behaved as a REST api, but the technique I used to get an OAuth token there is both a distraction and frankly a little scary to include here since it's really easy to mess up. If you don't already have a way to get one, that's probably a good topic for a separate SO question in any case.
One related (and big!) caveat: I'm not 100% sure how the consent and verification interact with a pure Rest client (i.e. how that works if you DON'T visit this in the browser first...), and/or whether this script would need to be in the same GCP project as the other code that uses the Sheets API. If there's interest, and/or it doesn't work right out of the box, please let me know and I'll happily dig deeper and follow up.
// Example URL, assuming:
// "Current web app URL": https://script.google.com/a/tillerhq.com/macros/s/AKfycbyZlWAW6bpCpnFoPjbdjznDomFRbTNluG4siCBMgOy2qU2AGoA/exec
// spreadsheetId: 1xNDWJXOekpBBV2hPseQwCRR8Qs4LcLOcSLDadVqDA0E
// sheet name: Sheet1
// (optional) filename: mycsv.csv
//
// https://script.google.com/a/tillerhq.com/macros/s/AKfycbyZlWAW6bpCpnFoPjbdjznDomFRbTNluG4siCBMgOy2qU2AGoA/exec?spreadsheetid=1xNDWJXOekpBBV2hPseQwCRR8Qs4LcLOcSLDadVqDA0E&sheetname=Sheet1&filename=mycsv.csv?spreadsheetid=1xNDWJXOekpBBV2hPseQwCRR8Qs4LcLOcSLDadVqDA0E&sheetname=Sheet1&filename=mycsv.csv
//
var REQUIRED_PARAMS = [
'spreadsheetid', // example: "1xNDWJXOekpBBV2hPseQwCRR8Qs4LcLOcSLDadVqDA0E"
'sheetname' // Case-sensitive; example: "Sheet1"
];
// Returns an RFC 4180 compliant CSV for the specified sheet in the specified spreadsheet
function doGet(e) {
REQUIRED_PARAMS.forEach(function(requiredParam) {
if (!e.parameters[requiredParam]) throw new Error('Missing required parameter ' + requiredParam);
});
var spreadsheet = SpreadsheetApp.openById(e.parameters.spreadsheetid);
var sheet = spreadsheet.getSheetByName(e.parameters.sheetname);
if (!sheet) throw new Error("Could not find sheet " + e.parameters.sheetname + " in spreadsheet " + e.parameters.spreadsheetid);
var filename = e.parameters.filename || (spreadsheet.getName() + "_" + e.parameters.sheetname + ".csv");
var numRows = sheet.getLastRow();
var numColumns = sheet.getLastColumn();
var values = sheet.getSheetValues(1, 1, numRows, numColumns);
function quote(s) {
s = s.toString();
if ((s.indexOf("\r") == -1)
&& (s.indexOf("\n") == -1)
&& (s.indexOf(",") == -1)
&& (s.indexOf("\"") == -1)) return s;
// Fields containing line breaks (CRLF)*, double quotes, and commas should be enclosed in double-quotes;
// anything other than that we already returned, so if we get here -- escape it and quote it.
// *That's what the text of the RFC says, but the ABNF (...and Excel) treat EITHER CR or LF as requiring quotes.
// Replace any double quote with a double double quote, and wrap the whole thing in quotes
return "\"" + s.replace(/"/g, '""') + "\"";
};
var csv = values.map(function(row) {
return row.map(quote).join();
}).join("\r\n") + "\r\n";
return ContentService
.createTextOutput(csv)
.setMimeType(ContentService.MimeType.CSV)
.downloadAsFile(filename);
}
I have online shop application, and I integrated it with Google AdWords, by adding proper script into web application.
Problem I have, is that Value on Google's Analysis control panel page is 0, despite the thing that I do have Conversions (many-per-click) with value of 12.
Code I integrated looks like this:
var google_conversion_id = <number is here>;
var google_conversion_language = "en";
var google_conversion_format = "3";
var google_conversion_color = "ffffff";
var google_conversion_label = "<label is here>";
var google_conversion_value = <?php echo $charge; ?>;
I added those lines (with several more JS lines required for Google AdWords) into last page, when payment has been made on my webshop.
PHP variable $charge have value of sold order.
Despite all of those, my Value is still 0. Can you help me waht I'm doing wrong, and how can I get proper value for it?
Try wrapping the PHP output with double quotes like so:
var google_conversion_value = "<?php echo $charge; ?>";
so that the rendered output looks like:
var google_conversion_value = "150";
The value can be either in quotes or not - it doesn't matter.
I am not an expert on PHP but from what little I do know is that it looks ok here. The easiest way to check is to get the Google Tag Assistant extension for Google Chrome that will let you check on the value that is being sent back to Google: https://chrome.google.com/webstore/detail/tag-assistant-by-google/kejbdjndbnbjgmefkgdddjlbokphdefk?hl=en
Using the extension when your conversion tag fires lets you see the values that are actually sent back and so you can confirm if the value is correctly being set.
If it does look like the value is being sent back ok, it would be best to wait at least 72 hours to verify that the value is appearing inside AdWords.
I'd like to write a Greasemonkey/userscript that automatically adds .compact to URLs starting with https://pay.reddit.com/ so It automatically redirects me to the mobile version.
I've been looking at similar userscripts, particularly this one: https://userscripts.org/scripts/review/112568 trying to figure out how to edit the replacement pattern, but I lack skills in this domain.
How do I write a Greasemonkey script that redirects me from https://pay.reddit.com/* to https://pay.reddit.com/*.compact ?
Thanks
The script should do these things:
Detect if the current URL is already to the compact site.
Load the compact version of the page if necessary.
Beware of "anchor" URLS (they end with "fragments" or "hashes" (#...) ) and account for them.
Keep the unwanted pages out of the browser history so that the back button works well. Only .compact URL's will be remembered.
By running at document-start, the script can give better performance in this case.
To that end, this script works:
// ==UserScript==
// #name _Reddit, ensure compact site is used
// #match *://*.reddit.com/*
// #run-at document-start
// #grant none
// ==/UserScript==
var oldUrlPath = window.location.pathname;
/*--- Test that ".compact" is at end of URL, excepting any "hashes"
or searches.
*/
if ( ! /\.compact$/.test (oldUrlPath) ) {
var newURL = window.location.protocol + "//"
+ window.location.host
+ oldUrlPath + ".compact"
+ window.location.search
+ window.location.hash
;
/*-- replace() puts the good page in the history instead of the
bad page.
*/
window.location.replace (newURL);
}
The example script you showed is using a regex to manipulate the window's location:
replace(/^https?:\/\/(www\.)?twitter.com/, 'https://mobile.twitter.com');
Unsurprisingly, this replaces https://www.twitter.com and http://twitter.com etc. with https://mobile.twitter.com.
Your situation is slightly different, because you want to append a string to your url if it matches some regex. Try:
var url = window.location.href;
var redditPattern = /^https:\/\/pay.reddit.com\/.*/;
// Edit: To prevent multiple redirects:
var compactPattern = /\.compact/;
if (redditPattern.test(url)
&& !compactPattern.test(url)) {
window.location.href = url + '.compact';
}
See: http://jsfiddle.net/RichardTowers/4VjdZ/3 for test case.