first commit

This commit is contained in:
Dave Umrysh 2021-03-15 11:29:57 -06:00
commit ced1e97857
8 changed files with 402 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
.DS_Store
# Generated by package manager
#node_modules/
# Generated by Cordova
#/plugins/
/platforms/

12
README.md Normal file
View File

@ -0,0 +1,12 @@
sixtyfour (The App)
==============
A messaging bridge between Matrix and 8x8 utilizing Android's Notification intents and a [maubot plugin](https://git.umycode.com/dave/maubot-sixtyfour)
WARNING: This is a total hack. Consider it a proof of concept rather than a production ready app
You will need to set up a project for Google Cloud Messaging to make this work ([more information](https://cloud.ibm.com/docs/mobilepush?topic=mobilepush-push_step_1))
License
------------
Some of the code I borrowed specifies their own copy license. For any other code assume it falls under [WTFPL](http://www.wtfpl.net/txt/copying/)

31
config.xml Normal file
View File

@ -0,0 +1,31 @@
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.umycode.sixtyfour" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>SixtyFour</name>
<description>
8x8 to Matrix bridge
</description>
<author email="dave@umycode.com" href="http://cordova.io">
Dave Umrysh
</author>
<content src="index.html" />
<access origin="*" />
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<allow-intent href="tel:*" />
<allow-intent href="sms:*" />
<allow-intent href="mailto:*" />
<allow-intent href="geo:*" />
<platform name="android">
<allow-intent href="market:*" />
<resource-file src="google-services.json" target="/app/google-services.json" />
</platform>
<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
</platform>
<plugin name="cordova-plugin-reply-to-notification" spec="git+https://git.umycode.com/dave/cordova-plugin-reply-to-notification.git" />
<plugin name="cordova-plugin-background-mode" spec="git+https://git.umycode.com/dave/cordova-plugin-run-in-background.git" />
<plugin name="phonegap-plugin-push" spec="2.3.0" />
<plugin name="cordova-plugin-device" spec="2.0.3" />
<plugin name="cordova-plugin-whitelist" spec="1.3.4" />
</widget>

41
package.json Normal file
View File

@ -0,0 +1,41 @@
{
"name": "com.umycode.sixtyfour",
"displayName": "SixtyFour",
"version": "1.0.0",
"description": "An app that bridges 8x8 and Matrix",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"ecosystem:cordova"
],
"author": "Apache Cordova Team",
"license": "Apache-2.0",
"devDependencies": {
"cordova-android": "^9.0.0",
"cordova-plugin-background-mode": "git+https://git.umycode.com/dave/cordova-plugin-run-in-background.git",
"cordova-plugin-device": "^2.0.3",
"cordova-plugin-whitelist": "^1.3.4",
"cordova-support-google-services": "^1.3.2",
"phonegap-plugin-multidex": "^1.0.0",
"phonegap-plugin-push": "^2.3.0",
"cordova-plugin-reply-to-notification": "git+https://git.umycode.com/dave/cordova-plugin-reply-to-notification.git"
},
"cordova": {
"plugins": {
"cordova-plugin-whitelist": {},
"cordova-plugin-background-mode": {},
"phonegap-plugin-push": {
"ANDROID_SUPPORT_V13_VERSION": "27.+",
"FCM_VERSION": "17.0.+"
},
"cordova-plugin-device": {},
"cordova-plugin-reply-to-notification": {}
},
"platforms": [
"android"
]
},
"dependencies": {}
}

110
www/css/index.css Normal file
View File

@ -0,0 +1,110 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed 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.
*/
* {
-webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */
}
body {
-webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */
-webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */
-webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */
background-color:#E4E4E4;
background-image:linear-gradient(to bottom, #A7A7A7 0%, #E4E4E4 51%);
font-family: system-ui, -apple-system, -apple-system-font, 'Segoe UI', 'Roboto', sans-serif;
font-size:12px;
height:100vh;
margin:0px;
padding:0px;
/* Padding to avoid the "unsafe" areas behind notches in the screen */
padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
text-transform:uppercase;
width:100%;
}
/* Portrait layout (default) */
.app {
background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */
position:absolute; /* position in the center of the screen */
left:50%;
top:50%;
height:50px; /* text area height */
width:225px; /* text area width */
text-align:center;
padding:180px 0px 0px 0px; /* image height is 200px (bottom 20px are overlapped with text) */
margin:-115px 0px 0px -112px; /* offset vertical: half of image height and text area height */
/* offset horizontal: half of text area width */
}
/* Landscape layout (with min-width) */
@media screen and (min-aspect-ratio: 1/1) and (min-width:400px) {
.app {
background-position:left center;
padding:75px 0px 75px 170px; /* padding-top + padding-bottom + text area = image height */
margin:-90px 0px 0px -198px; /* offset vertical: half of image height */
/* offset horizontal: half of image width and text area width */
}
}
h1 {
font-size:24px;
font-weight:normal;
margin:0px;
overflow:visible;
padding:0px;
text-align:center;
}
.event {
border-radius:4px;
color:#FFFFFF;
font-size:12px;
margin:0px 30px;
padding:2px 0px;
}
.event.listening {
background-color:#333333;
display:block;
}
.event.received {
background-color:#4B946A;
display:none;
}
#deviceready.ready .event.listening { display: none; }
#deviceready.ready .event.received { display: block; }
@keyframes fade {
from { opacity: 1.0; }
50% { opacity: 0.4; }
to { opacity: 1.0; }
}
.blink {
animation:fade 3000ms infinite;
-webkit-animation:fade 3000ms infinite;
}
@media screen and (prefers-color-scheme: dark) {
body {
background-image:linear-gradient(to bottom, #585858 0%, #1B1B1B 51%);
}
}

BIN
www/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

24
www/index.html Normal file
View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: blob: gap://ready file://* cdvfile://* *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
<meta name="color-scheme" content="light dark">
<link rel="stylesheet" href="css/index.css">
<title>sixyfour</title>
</head>
<body>
<div class="app">
<h1>SixyFour</h1>
<div id="deviceready" class="blink">
<p class="event listening">Connecting to Device</p>
<p class="event received">Device is Ready</p>
</div>
</div>
<script src="cordova.js"></script>
<script src="js/index.js"></script>
</body>
</html>

176
www/js/index.js Normal file
View File

@ -0,0 +1,176 @@
var my_8x8_name = "Dave Umrysh";
var hostUrl = "https://matrix.example.com"; // Location of your Matrix server
var webhook_secret = "UGfmxJyv49Sus2Y32dE7juXYMvp"; // Random key you set in your sixtyfour matrix bot
var instance_name = "sixtyfourinstance";
var android_id = "";
var devicePlatform = "";
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady() {
// Cordova is now initialized. Have fun!
console.log('Running cordova-' + cordova.platformId + '@' + cordova.version);
document.getElementById('deviceready').classList.add('ready');
android_id = device.uuid;
devicePlatform = device.platform;
cordova.plugins.backgroundMode.on('activate', function() {
cordova.plugins.backgroundMode.disableWebViewOptimizations();
});
cordova.plugins.backgroundMode.enable();
cordova.plugins.backgroundMode.disableBatteryOptimizations();
// Set up the GCM
setUpGCM();
startListening();
}
function startListening(){
replyToNotification.listen(function(n){
console.log("Received notification " + JSON.stringify(n) );
if(n.package == "org.vom8x8.sipua"){
// Check for rooms
if(n.title == my_8x8_name){
// This was my message out
// Post to the bot channel
var who_sent_it = n.title.replaceAll("\r\n","").replaceAll("\r","").replaceAll("\n","").replaceAll('"','\"');
var params = JSON.stringify({ "secret": webhook_secret, "message": "**"+who_sent_it+"**: "+n.text.replaceAll("\r\n","").replaceAll("\r","").replaceAll("\n","").replaceAll('"','\"') });
postToMatrix(hostUrl+"/_matrix/maubot/plugin/"+instance_name+"/webhook/r0?room=%21aaaaaaaaaaaaaaaaaa:matrix.example.com",params);
}else if(n.title == "John Smith"){
var who_sent_it = n.title.replaceAll("\r\n","").replaceAll("\r","").replaceAll("\n","").replaceAll('"','\"');
var params = JSON.stringify({ "secret": webhook_secret, "message": "**"+who_sent_it+"**: "+n.text.replaceAll("\r\n","").replaceAll("\r","").replaceAll("\n","").replaceAll('"','\"') });
postToMatrix(hostUrl+"/_matrix/maubot/plugin/"+instance_name+"/webhook/r0?room=%21bbbbbbbbbbbbbbbbbb:matrix.example.com",params);
// Add other DM rooms here
}else if(n.conversationTitle == "Room #1"){
var who_sent_it = n.title.replaceAll("Room #1: ","").replaceAll("\r\n","").replaceAll("\r","").replaceAll("\n","").replaceAll('"','\"');
var params = JSON.stringify({ "secret": webhook_secret, "message": "**"+who_sent_it+"**: "+n.text.replaceAll("\r\n","").replaceAll("\r","").replaceAll("\n","").replaceAll('"','\"') });
postToMatrix(hostUrl+"/_matrix/maubot/plugin/"+instance_name+"/webhook/r0?room=%21ccccccccccccccccc:matrix.example.com",params);
// Add other rooms here
}else{
var who_sent_it = n.title.replaceAll("All Company: ","").replaceAll("\r\n","").replaceAll("\r","").replaceAll("\n","").replaceAll('"','\"');
var params = JSON.stringify({ "secret": webhook_secret, "message": "**"+who_sent_it+"**: "+n.text.replaceAll("\r\n","").replaceAll("\r","").replaceAll("\n","").replaceAll('"','\"') });
postToMatrix(hostUrl+"/_matrix/maubot/plugin/"+instance_name+"/webhook/r0?room=%21dddddddddddddddd:matrix.example.com",params);
}
}
}, function(e){
console.log("Notification Error " + e);
});
}
function postTo8x8(room,message){
var room_name = "";
if(room == "!bbbbbbbbbbbbbbbbbb:matrix.example.com"){
room_name = "John Smith";
// Add other DM rooms here
}else if(room == "!ccccccccccccccccc:matrix.example.com"){
room_name = "Room #1";
// Add other rooms here
}else if(room == "!dddddddddddddddd:matrix.example.com"){
room_name = "All Company";
}
if(room_name != ""){
var temp = {
"room_name":room_name,
"message":message
};
replyToNotification.replytonotification(temp, function (s) {
// Send errors to the bot channel
console.log(s);
var params = JSON.stringify({ "secret": webhook_secret, "message": "**8x8 Error**: "+s.replaceAll("\r\n","").replaceAll("\r","").replaceAll("\n","").replaceAll('"','\"') });
postToMatrix(hostUrl+"/_matrix/maubot/plugin/"+instance_name+"/webhook/r0?room=%21aaaaaaaaaaaaaaaaaa:matrix.example.com",params);
}, function (e) {
console.log(e);
});
}
}
function postToMatrix(url,message){
var http = new XMLHttpRequest();
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/json");
//http.onreadystatechange = function() {
// console.log(http.status+"|"+http.responseText);
//};
http.send(message);
console.log("sent message to matrix")
}
function setUpGCM(){
if(typeof device !== 'undefined'){
pushNotification = PushNotification.init({
android: {},
ios: {
alert: "true",
badge: "true",
sound: "true",
clearBadge: "true"
}
});
pushNotification.on('registration', function(data) {
window.localStorage.setItem("gcm_key", data.registrationId);
// Try to send it off
sendGCMtoServer();
});
pushNotification.on('notification', function(data) {
// data.message,
// data.title,
// data.count,
// data.sound,
// data.image,
// data.additionalData
postTo8x8(data.title,data.message);
});
pushNotification.on('error', function(e) {
console.log("error: "+e.message);
});
}
}
function sendGCMtoServer(){
var gcm_key = window.localStorage.getItem("gcm_key");
if(gcm_key == null || gcm_key == ""){
setUpGCM();
}
if(gcm_key != null && gcm_key != ""){
// Send to server
var params = JSON.stringify({ "secret": webhook_secret, "gcm": gcm_key });
postToMatrix(hostUrl+"/_matrix/maubot/plugin/"+instance_name+"/webhook/r1?gcm",params);
}
}