Code by Scott שאול בן ישוע
Unverified Commit 70ca7f98 authored by Stephan Hackett's avatar Stephan Hackett Committed by GitHub
Browse files

Update Join API Driver.groovy

- added Notification category
- switch From GET requests to POST for added security
- switched to asynch calls for efficiency
- added multiple inline options (Title, Devices, Category, SMS#, Actions)
parent 4176a6b3
......@@ -13,24 +13,30 @@
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
* This driver uses sections of code derived from the original Pushover Driver that @ogiewon and I worked on. Thanks for you contributions Dan.
*
* 06/04/19 - added Notification category
* - switch From GET requests to POST for added security
- switched to asynch calls for efficiency
- added multiple inline options (Title, Devices, Category, SMS#, Actions)
*/
def version() {"v1.0.20190603b"}
def version() {"v1.0.20190608"}
preferences {
input("apiKey", "text", title: "Join API Key:", description: "")
input("apikey", "text", title: "Join API Key: <small><a href='https://joaoapps.com/join/api/' target='_blank'>[api docs here]</a></small>", description: "")
if(getValidated()){
input("deviceName", "enum", title: "Select Device:", description: "", multiple: true, required: false, options: getValidated("deviceList"))
input("myTitle", "text", title: "Notification Title:", description: "")
input("myImage", "text", title: "Status Bar Icon URI:", description: "(Image to be displayed in the status bar)")
input("deviceNames", "enum", title: "Select Device <b>[D]</b>:", description: "", multiple: true, required: false, options: getValidated("deviceList"))
input("title", "text", title: "Notification Title <b>[T]</b>:", description: "")
input("smallicon", "text", title: "Status Bar Icon URI:", description: "(Image to be displayed in the status bar)")
input("url", "text", title: "URL:", description: "(URL to be opened when Notification is clicked)")
input("category", "text", title: "Notification Category <b>[C]</b>:", description: "(Android 8+ allows custom notication handling)")
input("sound", "text", title: "Sound URI:", description: "(URL of notification sound to be played)")
input("image", "text", title: "Image URI:", description: "(URL of image to be displayed in the notification body)")
input("myApp", "text", title: "Open App by Name:", description: "(Name of Android app to open)")
input("myPackage", "text", title: "Open App by Package:", description: "(Name of Android Package to open)")
input("smsnumber", "number", title: "Phone # to send SMS text TO:", description: "(Text will be sent FROM the Join Device selected above)")
input("action", "text", title: "Actions for Notification:", description: "(separate multiple actions with commas)")
input("appPackage", "text", title: "Open App by Package:", description: "(Name of Android Package to open)")
input("smsnumber", "number", title: "Phone # to send SMS text TO <b>[S]</b>:", description: "(Text will be sent FROM the Join Device selected above)")
input("actions", "text", title: "Actions for Notification <b>[A]</b>:", description: "(separate multiple actions with commas)")
input("logEnable", "bool", title: "Enable Debug Logging?:", required: true)
}
......@@ -54,23 +60,29 @@ def updated() {
def initialize() {
state.version = version()
state.devices = deviceName
state.devices = deviceNames
//if(myPackage) device.updateSetting("appPackage","test")
device.removeSetting("deviceName")
device.removeSetting("myImage")
device.removeSetting("myTitle")
device.removeSetting("apiKey")
device.removeSetting("myPackage")
device.removeSetting("action")
}
def getValidated(type){
if(apiKey){
if(apikey){
if(type=="deviceList" && logEnable){log.debug "Generating Device List..."}
else if(logEnable) log.debug "Validating Key..."
def validated = false
def params = [
uri: "https://joinjoaomgcd.appspot.com/_ah/api/registration/v1/listDevices?apikey=${apiKey}",
uri: "https://joinjoaomgcd.appspot.com/_ah/api/registration/v1/listDevices?apikey=${apikey}",
]
if(logEnable) log.debug "Validation params: ${params}"
if ((apiKey =~ /[A-Za-z0-9]{30}/)) {
if ((apikey =~ /[A-Za-z0-9]{30}/)) {
try{
httpGet(params){response ->
if(response.status != 200) {
......@@ -94,7 +106,7 @@ def getValidated(type){
}
}
else {
log.error "API key '${apiKey}' is not properly formatted!"
log.error "API key '${apikey}' is not properly formatted!"
}
if(type=="deviceList") return deviceOptions
return validated
......@@ -102,94 +114,106 @@ def getValidated(type){
}
def speak(message) {
if (deviceName) { log.info "Sending Speech Request: ${message} to Device: $deviceName"}
def apiUri = "https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPush?apikey=${apiKey}"
def apiParams = ""
if (deviceNames) { log.info "Sending Speech Request: '${message}' to Device: $deviceNames"}
if(deviceName && deviceName instanceof List) {
deviceName = deviceName.join(',')
if(deviceNames && deviceNames instanceof List) {
deviceNames = deviceNames.join(',')
}
def apiParams = ["apikey":apikey,"deviceNames":deviceNames, "say":message]
if(deviceName) apiParams += "&deviceNames=" + URLEncoder.encode(deviceName, "UTF-8")
if(message) apiParams += "&say=" + URLEncoder.encode(message, "UTF-8")
def params = [
uri: apiUri + apiParams,
uri: "https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPush?",
requestContentType: 'application/json',
contentType: 'application/json',
body : apiParams
]
if(logEnable) log.debug "Speak params: ${params}"
if ((apiKey =~ /[A-Za-z0-9]{30}/)) {
httpGet(params){response ->
if(response.status != 200) {
log.error "Received HTTP error ${response.status}. Check your keys!"
}
else {
if(logEnable) log.debug "Message Received by Join API Server"
}
}
if ((apikey =~ /[A-Za-z0-9]{30}/)) {
asynchttpPost('myPostResponse', params)
}
else {
log.error "API key '${apiKey}' is not properly formatted!"
log.error "API key '${apikey}' is not properly formatted!"
}
}
def deviceNotification(message) {
def actionInline = ""
if(message.contains("[A]")) {
def multiMessage = message.split("\\[A\\]")
message = multiMessage[0]
actionInline = multiMessage[1]
if(message.startsWith("[") || message.endsWith("]")|| message.contains("][")){
log.warn "Improperly formatted message!"
return
}
if (deviceName) { log.info "Sending Message: ${message} to Device: $deviceName"}
def apiUri = "https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPush?apikey=${apiKey}"
def apiParams = ""
if(deviceName && deviceName instanceof List) {
deviceName = deviceName.join(',')
def apiParams = buildMessage(message)
if(logEnable) log.debug "Merged Settings: " + apiParams
if (apiParams.deviceNames) { log.info "Sending Message: '${apiParams.text}' to Device: $apiParams.deviceNames"}
if(apiParams.deviceNames && apiParams.deviceNames instanceof List) { //if multiple devices selected, convert list to string
apiParams.deviceNames = apiParams.deviceNames.join(',')
}
if(deviceName) apiParams += "&deviceNames=${deviceName}"
if(myTitle) apiParams += "&title=" + URLEncoder.encode(myTitle, "UTF-8")
if(message) apiParams += "&text=" + URLEncoder.encode(message, "UTF-8")
if(myImage) apiParams += "&smallicon=" + URLEncoder.encode(myImage, "UTF-8")
if(url) apiParams += "&url=" + URLEncoder.encode(url, "UTF-8")
if(sound) apiParams += "&sound=" + URLEncoder.encode(sound, "UTF-8")
if(image) apiParams += "&image=" + URLEncoder.encode(image, "UTF-8")
if(myApp) apiParams += "&app=" + URLEncoder.encode(myApp, "UTF-8")
if(myPackage) apiParams += "&appPackage=" + URLEncoder.encode(myPackage, "UTF-8")
if(smsnumber) apiParams += "&smsnumber=" + smsnumber + "&smstext=" + URLEncoder.encode(message, "UTF-8")
//Inline action overide actions listed in the preferences
if(actionInline != ""){
if(logEnable) log.debug "Inline actions found. Over-riding driver preferences."
action = actionInline.replace(",", "|||")
apiParams += "&actions=" + URLEncoder.encode(action, "UTF-8")
}
else if(action){
action = action.replace(",", "|||")
apiParams += "&actions=" + URLEncoder.encode(action, "UTF-8")
}
def params = [
uri: apiUri + apiParams,
uri: "https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPush?",
requestContentType: 'application/json',
contentType: 'application/json',
body : apiParams
]
if(logEnable) log.debug params
if ((apiKey =~ /[A-Za-z0-9]{30}/)) {
httpGet(params){response ->
if(response.status != 200) {
log.error "Received HTTP error ${response.status}. Check your keys!"
}
else {
if(logEnable) log.debug "Message Received by Join API Server"
}
}
if ((apikey =~ /[A-Za-z0-9]{30}/)) {
asynchttpPost('myPostResponse', params)
}
else {
log.error "API key '${apiKey}' is not properly formatted!"
log.error "API key '${apikey}' is not properly formatted!"
}
}
def myPostResponse(response,data){
if(response.status != 200) {
log.error "Received HTTP error ${response.status}. Check your keys!"
}
else {
if(logEnable) log.debug "Message Received by Join API Server"
}
}
def buildMessage(message){
def current = settings
if(logEnable) log.debug "Settings: " + current
def currentList = message.tokenize("[]") //separate complete message into a list with shortcut,value
if(logEnable) log.debug "Current Split List: " + currentList
def currentSize = currentList.size()
def myMap = [:]
myMap["text"] = currentList[0]
if(currentSize > 1){
def count = 1
def totalPairs = currentSize / 2 //get the total number of key value pairs to create
for (i in 1..totalPairs){
def myKey = getPrefName()[currentList[count]] //set key to actual preference name : eg. A=actions or D=deviceNames
def myVal = currentList[count+1]
myMap[myKey] = myVal
count = count + 2
}
}
if(logEnable) log.debug "Custom Settings: " + myMap
current << myMap //merge driver settings with custom setting
current.remove("logEnable") //remove uneeded preferences
if(current.actions){ //format actions using ||| delimiter as per api
log.info current.actions
log.info current.actions.replace(",", "|||")
current["actions"] = current.actions.replace(",", "|||")
}
return current
}
def getPrefName(){ //convert inline shortcut to preference name
return [
"D":"deviceNames",
"T":"title",
"C":"category",
"A":"actions",
"S":"smsnumber"
]
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment