So I have built a custom pool control system in Python. I then used Flask-ask to integrate this with my Echo Dots and Show. With the Echo Show, I was using a simple_card format which reads back all my information while showing it on the screen:
#ask.intent("GetAllStats")
def get_pool_stats():
pool_current_ph = read_database("pool_chemicals", "pool_current_ph")
pool_current_orp = read_database("pool_chemicals", "pool_current_orp")
pool_current_temp = int(float(read_database("system_status", "pool_current_temp")))
pool_level_percentage = read_database("pool_level", "pool_level_percentage")
pic = 'https://richard.mydomian.net/pool_control.jpg'
msg = render_template('our_stats', temperature=pool_current_temp,
ph=pool_current_ph,
orp=pool_current_orp,
level=pool_level_percentage)
return statement(msg).simple_card(title='Pool Control', content='Pool Temperature: {0}\n Pool PH: {1}\n Pool ORP: {2}\n Water Level: {3}% .format(pool_current_temp,pool_current_ph,pool_current_orp,pool_level_percentage))
Here is my our_stats from my templates.yaml:
our_stats: |
<speak>
The pool temperature is currently {{temperature}} degrees. The P H of our pool water is currently {{ph}}, while our oxygen reduction potential
is right at {{orp}}. The level of our water is at {{level}} percent.
</speak>
This works great, but I do not have any font control (that I can find) and the background is always grey.
So I started to research using the display_render method and I was able to get it to put up a really nice background picture of my pool and still read back my stats, but now I cannot get it to display the information in printed form.
I changed my return statement above to:
return statement(msg).display_render(template='BodyTemplate3', title='Pool Control', background_image_url=pic)
Again, this works great and reads back my information, but it I try to pass any content to it via textContent, primaryText, content, or text it always fails. I have also tried various templates including BodyTemplate's and listTemplate's. All to no avail. Anytime I try to add content to the screen the skill fails. I remove the content and I get a fantastic picture and it will speak to me all of the information, but that is as far as I can get.
One of the main problems is that I just have not been able to find any pertinent kind of examples using Flask-Ask and the Echo Show with anything but the simple_card.
I am hoping someone has figured this out and can point me in the right direction.
You have to edit your flask-ask models.py.
In the method display_render delete:
,
'textContent': text
change:
def display_render(self, template=None, title=None, backButton='HIDDEN', token=None, background_image_url=None, image=None, text=None, hintText=None):
to:
def display_render(self, template=None, title=None, backButton='HIDDEN', token=None, background_image_url=None, image=None, text=None, format=None, hintText=None):
and add after:
if background_image_url is not None:
directive[0]['template']['backgroundImage'] = {
'sources': [
{'url': background_image_url}
]
}
this:
if format == None:
format = 'PlainText'
if text is not None:
directive[0]['template']['textContent'] = {
'primaryText': {
'type': format,
'text': text
},
'secondaryText': {
'type': format,
'text': None
},
'tertiaryText': {
'type': format,
'text': None
}
}
Now you should be able to use:
display_render(template='BodyTemplate6', title='Pool Control', background_image_url=pic, text='Text', format='Format')
I'm using BodyTemplate6 here because some Templates don't support text, format can be 'PlainText' or 'SSML'
Related
So this is my first time coding an actual project that isn't a small coding task. I've got a bot that runs and responds to a message if it says "hello". I've read the API documentation up and down and really only have a vague understanding of it and I'm not sure how to implement it.
My question right now is how would I go about creating a command that takes informationn from a message the command is replying to (sender's name, message content) and stores it as an object. Also, what would be the best way to store that information?
I want to learn while doing this and not just have the answers handed to me ofc, but I feel very lost. Not sure where to even begin.
I tried to find tutorials on coding discord bots that would have similar functions to what I want to do, but can't find anything.
Intro :
Hi NyssaDuke !
First of all, prefer to paste your code instead of a picture. It's easier for us to take your code and try to produce what you wish.
In second, I see an "issue" in your code since you declare twice the bot. You can specify the intents when you declare your bot as bot = commands.Bot(command_prefix="!", intents=intents)
Finally, as stated by #stijndcl , it's against TOS, but I will try to answer you at my best.
filesystem
My bot needs to store data, like users ID, language, and contents relative to a game, to get contacted further. Since we can have a quite big load of requests in a small time, I prefered to use a file to store instead of a list that would disappear on crash, and file allow us to make statistics later. So I decided to use pytables that you can get via pip install pytables. It looks like a small DB in a single file. The file format is HDF5.
Let say we want to create a table containing user name and user id in a file :
import tables
class CUsers (tables.IsDescription) :
user_name = StringCol(32)
user_id = IntCol()
with tables.open_file("UsersTable.h5", mode="w") as h5file :
groupUser = h5file.create_group("/", "Users", "users entries")
tableUser = h5file.create_table(groupUser, "Users", CUsers, "users table")
We have now a file UsersTable.h5 that has an internal table located in root/Users/Users that is accepting CUsers objects, where, therefore, user_name and user_id are the columns of that table.
getting user info and storing it
Let's now code a function that will register user infos, and i'll call it register. We will get the required data from the Context that is passed with the command, and we'll store it in file.
#bot.command(name='register')
async def FuncRegister (ctx) :
with tables.open_file("UsersTable.h5", mode="a") as h5file :
tableUser = h5file.root.Users.Users
particle = tableUser.row
particle['user_name'] = str(ctx.author)
particle['user_id'] = ctx.author.id
particle.append()
tableUser.flush()
The last two lines are sending the particle, that is the active row, so that is an object CUsers, into the file.
An issue I got here is that special characters in a nickname can make the code bug. It's true for "é", "ü", etc, but also cyrillic characters. What I did to counter is to encode the user name into bytes, you can do it by :
particle['user_name'] = str(ctx.author).encode()
reading file
It is where it starts to be interesting. The HFS5 file allows you to use kind of sql statements. Something you have to take in mind is that strings in the file are UTF-8 encoded, so when you extract them, you have to call for .decode(utf-8). Let's now code a function where a user can remove its entry, based on its id :
#bot.command(name="remove")
async def FuncRemove(ctx) :
with tables.open_file("UsersTable.h5", mode="a") as h5file :
tableUser = h5file.root.Users.Users
positions = tableUser.get_where_list("(user_id == '%d')" % ctx.author.id)
nameuser = tableUser[positions[0]]['user_name'].decode('utf-8')
tableUser.remove_row(positions[0])
.get_where_list() returns a list of positions in the file, that I later address to find the right position in the table.
bot.fetch_user(id)
If possible, prefer saving ID over name, as it complicates the code with encode() and decode(), and that bots have access to a wonderful function that is fetch_user(). Let's code a last function that will get you the last entry in your table, and with the id, print the username with the fetch method :
#bot.command(name="last")
async def FuncLast(ctx) :
with tables.open_file("UsersTable.h5", mode="r") as h5file :
tableUser = h5file.root.Users.Users
lastUserIndex = len(tableUser) - 1
iduser = tableUser[lastUserIndex]['user_id']
member = await bot.fetch_user(iduser)
await ctx.send(member.display_name)
For further documentation, check the manual of discord.py, this link to context in particular.
Is there anyway of uploading Custom Slot Types values via an API, so that you do not need to type them in manually using the new Alexa Skill Builder interface (if you have many of them):
I haven't found anything.
My recommendation is to get the model via SMAPI first, edit the json file with your new values and update it via SMAPI again.
ask api get-model -s "enter your skill id here" --stage development -l en-US > model.json
in the model.json file you can see the slots definition. Change it (with a script or manually) and update the model again
Reference to both commands:
https://developer.amazon.com/docs/smapi/ask-cli-command-reference.html#update-model-subcommand
https://developer.amazon.com/docs/smapi/ask-cli-command-reference.html#update-model-subcommand
It seems not (after searching). There is a feature request logged here with Amazon:
https://forums.developer.amazon.com/questions/9640/api-to-upload-intent-schema-and-sample-utterances.html#answer-77902
Yes you can do this via the SMAPI API/CLI. Take a look at https://developer.amazon.com/docs/smapi/ask-cli-intro.html for a full detail - it allows for full model editing via JSON.
In the left bar bellow the "Intents" and "Slot" is the option "JSON Editor". There you can write a JSON for the new intents you want to add.
Example without slot type
{
"name":"YesIntent",
"samples":[
"Yes",
"Yeah",
"I do",
"I am"
]
}
Example with slot type
{
"name":"NumberIntent",
"slots":[
{
"name":"number",
"type":"AMAZON.NUMBER"
}
],
"samples":[
"{number} is my number",
"{number}",
"my number is {number}"
]
}
As other answers suggest, you can use the SMAPI.
Alternatively, you can select the "code editor" tab on the left and drag/drop or copy/paste your schema json code.
https://github.com/williamwdu/Alexa-Custom-Slot-Generator
I wrote this to convert csv/excel to JSON format so you can paste it into code editor.
Let me know if you have any question.
There is no README for the code coz I have no time these days
When using tone analyser, I am only able to retrieve 1 result. For example, if I use the following input text.
string m_StringToAnalyse = "The World Rocks ! I Love Everything !! Bananas are awesome! Old King Cole was a merry old soul!";
The results only return the analysis for document level and sentence_id = 0, ie. "The World Rocks !". The analysis for the next 3 sentences are not returned.
Any idea what I am doing wrong or am I missing out anything? This is the case when running the provided sample code as well.
string m_StringToAnalyse = "This service enables people to discover and understand, and revise the impact of tone in their content. It uses linguistic analysis to detect and interpret emotional, social, and language cues found in text.";
Running Tone analysis using the sample code on the sample sentence provided above also return results for the document and the first sentence only.
I have tried with versions "2016-02-19" as well as "2017-03-15" with same results.
I believe that if you want sentence by sentence analysis you need to send every separate sentence as a JSON object. It will then return analysis in an array where id=SENTENCE_NUM.
Here is an example of one I did using multiple YouTube comments (using Python):
def get_comments(video):
#Get the comments from the Youtube API using requests
url = 'https://www.googleapis.com/youtube/v3/commentThreads?part=snippet&maxResults=100&videoId='+ video +'&key=' + youtube_credentials['api_key']
r = requests.get(url)
comment_dict = list()
# for item in comments, add an object to the list with the text of the comment
for item in r.json()['items']:
the_comment = {"text": item['snippet']['topLevelComment']['snippet']['textOriginal']}
comment_dict.append(the_comment)
# return the list as JSON to the sentiment_analysis function
return json.dumps(comment_dict)
def sentiment_analysis(words):
# Load Watson Credentials using Python SDK
tone_analyzer = ToneAnalyzerV3(
username=watson_credentials['username'], password=watson_credentials['password'], version='2016-02-11')
# Get the tone, based on the JSON object that is passed to sentiment_analysis
return_sentiment = json.dumps(tone_analyzer.tone(text=words), indent=2)
return_sentiment = json.loads(return_sentiment)
Afterwards you can do whatever you want with the JSON object. I would also like to note for anyone else looking at this if you want to do an analysis of many objects, you can add sentences=False in the tone_analyzer.tone function.
I'm new to Swift and followed a simple tutorial to make a magic 8 ball Cocoa App that every time I click the ball it shows a different piece of advice. I am now trying to practice my UI automated tests by asserting (XCTAssert) that the "Piece of Advice" label is equal to one of the string values in my array.
My array looks like this and is in my ViewController.swift:
var adviceList = [
"Yes",
"No",
"Tom says 'do it!'",
"Maybe",
"Try again later",
"How can I know?",
"Totally",
"Never",
]
How can I make an assertion in my UITests.swift file that asserts that the string that is shown is equal to one of the string values in the array above?
It's possible that you're asking how to access application state from a UI test, or just in general UI testing.
I think it's a pretty interesting question so I'm going to answer because it's something that I don't know a lot about and hopefully will prompt other people to chime in and correct.
Background: A basic Magic 8 Ball project
I set up a basic project with a view controller that contains two views: a label and a button. Tapping the button updates the label text with a random message:
import UIKit
struct EightBall {
static let messages = ["Yes", "No", "It's not certain"]
var newMessage: String {
let randomIndex = Int(arc4random_uniform(UInt32(EightBall.messages.count)))
return EightBall.messages[randomIndex]
}
}
class ViewController: UIViewController {
let ball = EightBall()
#IBOutlet weak var messageLabel: UILabel!
#IBAction func shakeBall(_ sender: Any) {
messageLabel.text = ball.newMessage
}
}
A basic UI test
Here's a commented UI test showing how to automate tapping on the button, and grabbing the value of the label, and then checking that the value of the label is a valid message.
import XCTest
class MagicUITests: XCTestCase {
// This method is called before the invocation of each test method in the class.
override func setUp() {
super.setUp()
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = true
// UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
XCUIApplication().launch()
}
func testValidMessage() {
// Grab reference to the application
let app = XCUIApplication()
// #1
// Grab reference to the label with the accesability identifier 'MessageLabel'
let messagelabelStaticText = app.staticTexts["MessageLabel"]
// Tap the button with the text 'Shake'
app.buttons["Shake"].tap()
// get the text of the label
let messageLabelText = messagelabelStaticText.label
// #2
// check if the text in the label matches one of the allowed messages
let isValidMessage = EightBall.messages.contains(messageLabelText)
// test will fail if the message is not valid
XCTAssert(isValidMessage)
}
}
At #1 The approach that I'm using to get the label is to access the labels accessibilityIdentifier property. For this project I entered this through storyboard, but if you're setting your views up in code you can directly set the accessibilityIdentifier property yourself.
The other thing that's confusing here is that to get access to elements in the view you're not navigating the view hierarchy, but a proxy of the hierarchy, which is why the syntax to get a label is the odd 'staticTexts' (The references at the bottom of the post explain this in more detail).
For #2 I'm inspecting the structure defined in my project. In a unit test you could access this my importing #testable import ProjectName but unfortunately this approach doesn't work for UI Test.
Instead, you'll have to make sure that any source file you want to access from the UI test is included as a target. You can do this in Xcode from this panel by checking the name of your UI test:
More UI testing references:
UI Testing Intro: http://www.mokacoding.com/blog/xcode-7-ui-testing/
UI Testing Cheat Sheet: http://masilotti.com/ui-testing-cheat-sheet/
I'm working on a data migration task, where I have to export a somewhat large Lotus Notes application into a blogging platform. My first task was to export the articles from Lotus Notes into CSV files.
I created a Agent in LotusScript to export the data into CSV files. I use a modified version of this IBM DeveloperWorks forum post. And it basically does the job. But the contents of the Rich Text field is stripped of any formatting. And this is not what I want, I want the Rich Text field rendered as HTML.
The documentation for the GetItemValue method explicitly states that the text is rendered into plain text. So I began to research for something that would retrieve the HTML. I found the NotesMIMEEntity class and some sample code in the IBM article How To Access HTML in a Rich Text Field Using LotusScript.
But for the technique described in the above article to work, the Rich Text field need to have the property "Store Contents as HTML and MIME". And this is not the case with my Lotus Notes database. I tried to set the property on the fields in question, but it didn't do the trick.
Is it possible to use the NotesMIMEEntity and set the "Store Contents as HTML and MIME" property after the content has been added, to export the field rendered as HTML?
Or what are my options for exporting the Notes database Rich Text fields as HTML?
Bonus information: I'm using IBM Lotus Domino Designer version 8.5
There is this fairly unknown command that does exactly what you want: retrieve the URL using the command OpenField.
Example that converts only the Body-field:
http://SERVER/your%5Fdatabase%5Fpath.nsf/NEW%5FVIEW/docid/Body?OpenField
Here is how I did it, using the OpenField command, see D.Bugger's post above
Function GetHtmlFromField(doc As NotesDocument, fieldname As String) As String
Dim obj
Set obj = CreateObject("Microsoft.XMLHTTP")
obj.open "GET", "http://www.mydomain.dk/database.nsf/0/" + doc.Universalid + "/" + fieldname + "?openfield&charset=utf-8", False, "", ""
obj.send("")
Dim html As String
html = Trim$(obj.responseText)
GetHtmlFromField = html
End Function
I'd suggest looking at Midas' Rich Text LSX (http://www.geniisoft.com/showcase.nsf/MidasLSX)
I haven't used the personally, but I remember them from years ago being the best option for working with Rich Text. I'd bet it saves you a lot of headaches.
As for the NotesMIMEEntity class, I don't believe there is a way to convert RichText to MIME, only MIME to RichText (or retain the MIME within the document for emailing purposes).
If you upgrade to Notes Domino 8.5.1 then you can use the new ConvertToMIME method of the NotesDocument class. See the docs. This should do what you want.
Alternativly the easiest way to get the Domino server to render the RichText will be to actually retrieve it via a url call. Set up a simple form that just has the RichText field and then use your favourite HTTP api to pull in the page. It should then be pretty straight forward to pull out the body.
Keep it simple.
Change the BODY field to Store contents as HTML and MIME
Open the doc in editmode.
Save.
Close.
You can now use the NotesMIMEEntity to get what you need from script.
You can use the NotesDXLExporter class to export the Rich Text and use an XSLT to transform the output to what you need.
I know you mentioned using LotusScript, but if you don't mind writing a small Java agent (in the Notes client), this can be done fairly easily - and there is no need to modify the existing form design.
The basic idea is to have your Java code open a particular document through a localhost http request (which is simple in Java) and to have your code capture that html output and save it back to that document. You basically allow the Domino rendering engine to do the heavy lifting.
You would want do this:
Create a form which contains only the rich-text field you want to convert, and with Content Type of HTML
Create a view with a selection formula for all of the documents you want to convert, and with a form formula which computes to the new form
Create the Java agent which just walks your view, and for each document gets its docid, opens a URL in the form http://SERVER/your_database_path.nsf/NEW_VIEW/docid?openDocument, grabs the http response and saves it.
I put up some sample code in a similar SO post here:
How to convert text and rich text fields in a document to html using lotusscript?
Works in Domino 10 (have not tested with 9)
HTMLStrings$ = NotesRichTextItem .Converttohtml([options] ) As String
See documentation :
https://help.hcltechsw.com/dom_designer/10.0.1/basic/H_CONVERTOHTML_METHOD_NOTESRICHTEXTITEM.html
UPDATE (2022)
HCL no longer support this method since version 11. The documentation does not include any info about the method.
I have made some tests and it still works in v12 but HCL recommended to not use it.
Casper's recommendation above works well, but make sure the ACL is such to allow Anonymous Access otherwise your HTML will be the HTML from your login form
If you do not need to get the Richtext from the items specifically, you can use ?OpenDocument, which is documented (at least) here: https://www.ibm.com/developerworks/lotus/library/ls-Domino_URL_cheat_sheet/
https://www.ibm.com/support/knowledgecenter/SSVRGU_9.0.1/com.ibm.designer.domino.main.doc/H_ABOUT_URL_COMMANDS_FOR_OPENING_DOCUMENTS_BY_KEY.html
OpenDocument also allows you to expand sections (I am unsure if OpenField does)
Syntax is:
http://Host/Database/View/DocumentUniversalID?OpenDocument
But be sure to include the charset parameter as well - Japanese documents were unreadable without specifying utf-8 as the charset.
Here is the method I use that takes a NotesDocument and returns the HTML for the doc as a string.
private string ConvertDocumentToHml(Domino.NotesDocument doc, string sectionList = null)
{
var server = doc.ParentDatabase.Server.Split('/')[0];
var dbPath = doc.ParentDatabase.FilePath;
string viewName = "0";
string documentId = doc.UniversalID.ToUpper();
var ub = new UriBuilder();
ub.Host = server;
ub.Path = dbPath.Replace("\\", "/") + "/" + viewName + "/" + documentId;
if (string.IsNullOrEmpty(sectionList))
{
ub.Query = "OpenDocument&charset=utf-8";
}
else
{
ub.Query = "OpenDocument&charset=utf-8&ExpandSection=" + sectionList;
}
var url = ub.ToString();
var req = HttpWebRequest.CreateHttp(url);
try
{
var resp = req.GetResponse();
string respText = null;
using (var sr = new StreamReader(resp.GetResponseStream()))
{
respText = sr.ReadToEnd();
}
return respText;
}
catch (WebException ex)
{
return "";
}
}