You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
292 lines
8.0 KiB
292 lines
8.0 KiB
import {models} from './models'
|
|
import * as fetch from 'node-fetch'
|
|
import { Op } from 'sequelize'
|
|
import * as socket from './utils/socket'
|
|
import * as jsonUtils from './utils/json'
|
|
import * as helpers from './helpers'
|
|
import {nodeinfo} from './utils/nodeinfo'
|
|
import { loadLightning } from './utils/lightning'
|
|
import * as path from 'path'
|
|
|
|
const constants = require(path.join(__dirname, '../config/constants.json'))
|
|
const env = process.env.NODE_ENV || 'development';
|
|
const config = require(path.join(__dirname,'../config/app.json'))[env];
|
|
|
|
const checkInviteHub = async (params = {}) => {
|
|
if (env != "production") {
|
|
return
|
|
}
|
|
const owner = await models.Contact.findOne({ where: { isOwner: true }})
|
|
|
|
//console.log('[hub] checking invites ping')
|
|
|
|
const inviteStrings = await models.Invite.findAll({ where: { status: { [Op.notIn]: [constants.invite_statuses.complete, constants.invite_statuses.expired] } } }).map(invite => invite.inviteString)
|
|
|
|
fetch(config.hub_api_url + '/invites/check', {
|
|
method: 'POST' ,
|
|
body: JSON.stringify({ invite_strings: inviteStrings }),
|
|
headers: { 'Content-Type': 'application/json' }
|
|
})
|
|
.then(res => res.json())
|
|
.then(json => {
|
|
if (json.object) {
|
|
json.object.invites.map(async object => {
|
|
const invite = object.invite
|
|
const pubkey = object.pubkey
|
|
const price = object.price
|
|
|
|
const dbInvite = await models.Invite.findOne({ where: { inviteString: invite.pin }})
|
|
const contact = await models.Contact.findOne({ where: { id: dbInvite.contactId } })
|
|
|
|
if (dbInvite.status != invite.invite_status) {
|
|
const updateObj:{[k:string]:any} = { status: invite.invite_status, price: price }
|
|
if(invite.invoice) updateObj.invoice = invite.invoice
|
|
|
|
dbInvite.update(updateObj)
|
|
|
|
socket.sendJson({
|
|
type: 'invite',
|
|
response: jsonUtils.inviteToJson(dbInvite)
|
|
})
|
|
|
|
if (dbInvite.status == constants.invite_statuses.ready && contact) {
|
|
sendNotification(-1, contact.alias, 'invite')
|
|
}
|
|
}
|
|
|
|
if (pubkey && dbInvite.status == constants.invite_statuses.complete && contact) {
|
|
contact.update({ publicKey: pubkey, status: constants.contact_statuses.confirmed })
|
|
|
|
var contactJson = jsonUtils.contactToJson(contact)
|
|
contactJson.invite = jsonUtils.inviteToJson(dbInvite)
|
|
|
|
socket.sendJson({
|
|
type: 'contact',
|
|
response: contactJson
|
|
})
|
|
|
|
helpers.sendContactKeys({
|
|
contactIds: [contact.id],
|
|
sender: owner,
|
|
type: constants.message_types.contact_key,
|
|
})
|
|
}
|
|
})
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.log('[hub error]', error)
|
|
})
|
|
}
|
|
|
|
const pingHub = async (params = {}) => {
|
|
if (env != "production") {
|
|
return
|
|
}
|
|
|
|
const node = await nodeinfo()
|
|
sendHubCall({ ...params, node })
|
|
}
|
|
|
|
const sendHubCall = (params) => {
|
|
// console.log('[hub] sending ping')
|
|
fetch(config.hub_api_url + '/ping', {
|
|
method: 'POST',
|
|
body: JSON.stringify(params),
|
|
headers: { 'Content-Type': 'application/json' }
|
|
})
|
|
.then(res => res.json())
|
|
.then(json => {
|
|
// ?
|
|
})
|
|
.catch(error => {
|
|
console.log('[hub error]', error)
|
|
})
|
|
}
|
|
|
|
const pingHubInterval = (ms) => {
|
|
setInterval(pingHub, ms)
|
|
}
|
|
|
|
const checkInvitesHubInterval = (ms) => {
|
|
setInterval(checkInviteHub, ms)
|
|
}
|
|
|
|
export function sendInvoice(payReq, amount) {
|
|
console.log('[hub] sending invoice')
|
|
fetch(config.hub_api_url + '/invoices', {
|
|
method: 'POST',
|
|
body: JSON.stringify({invoice:payReq, amount}),
|
|
headers: { 'Content-Type': 'application/json' }
|
|
})
|
|
.then(res => res.json())
|
|
.then(json => {
|
|
// ?
|
|
})
|
|
.catch(error => {
|
|
console.log('[hub error]', error)
|
|
})
|
|
}
|
|
|
|
const finishInviteInHub = (params, onSuccess, onFailure) => {
|
|
fetch(config.hub_api_url + '/invites/finish', {
|
|
method: 'POST' ,
|
|
body: JSON.stringify(params),
|
|
headers: { 'Content-Type': 'application/json' }
|
|
})
|
|
.then(res => res.json())
|
|
.then(json => {
|
|
console.log('[hub] finished invite to hub')
|
|
onSuccess(json)
|
|
})
|
|
.catch(e => {
|
|
console.log('[hub] fail to finish invite in hub')
|
|
onFailure(e)
|
|
})
|
|
}
|
|
|
|
const payInviteInHub = (invite_string, params, onSuccess, onFailure) => {
|
|
fetch(config.hub_api_url + '/invites/' + invite_string + '/pay', {
|
|
method: 'POST' ,
|
|
body: JSON.stringify(params),
|
|
headers: { 'Content-Type': 'application/json' }
|
|
})
|
|
.then(res => res.json())
|
|
.then(json => {
|
|
if (json.object) {
|
|
console.log('[hub] finished pay to hub')
|
|
onSuccess(json)
|
|
} else {
|
|
console.log('[hub] fail to pay invite in hub')
|
|
onFailure(json)
|
|
}
|
|
})
|
|
}
|
|
|
|
async function payInviteInvoice(invoice, onSuccess, onFailure) {
|
|
const lightning = await loadLightning()
|
|
var call = lightning.sendPayment({})
|
|
call.on('data', async response => {
|
|
onSuccess(response)
|
|
})
|
|
call.on('error', async err => {
|
|
onFailure(err)
|
|
})
|
|
call.write({ payment_request:invoice })
|
|
}
|
|
|
|
const createInviteInHub = (params, onSuccess, onFailure) => {
|
|
fetch(config.hub_api_url + '/invites_new', {
|
|
method: 'POST' ,
|
|
body: JSON.stringify(params),
|
|
headers: { 'Content-Type': 'application/json' }
|
|
})
|
|
.then(res => res.json())
|
|
.then(json => {
|
|
if (json.object) {
|
|
console.log('[hub] sent invite to be created to hub')
|
|
onSuccess(json)
|
|
} else {
|
|
console.log('[hub] fail to create invite in hub')
|
|
onFailure(json)
|
|
}
|
|
})
|
|
}
|
|
|
|
const sendNotification = async (chat, name, type) => {
|
|
|
|
let message = `You have a new message from ${name}`
|
|
if(type==='invite'){
|
|
message = `Your invite to ${name} is ready`
|
|
}
|
|
if(type==='group'){
|
|
message = `You have been added to group ${name}`
|
|
}
|
|
|
|
if(type==='message' && chat.type==constants.chat_types.group && chat.name && chat.name.length){
|
|
message += ` on ${chat.name}`
|
|
}
|
|
|
|
console.log('[send notification]', { chat_id:chat.id, message })
|
|
|
|
if (chat.isMuted) {
|
|
console.log('[send notification] skipping. chat is muted.')
|
|
return
|
|
}
|
|
|
|
const owner = await models.Contact.findOne({ where: { isOwner: true }})
|
|
|
|
if (!owner.deviceId) {
|
|
console.log('[send notification] skipping. owner.deviceId not set.')
|
|
return
|
|
}
|
|
|
|
const unseenMessages = await models.Message.count({ where: { sender: { [Op.ne]: owner.id }, seen: false } })
|
|
const device_id = owner.deviceId
|
|
|
|
const params:{[k:string]:any} = {device_id}
|
|
const notification:{[k:string]:any} = {
|
|
chat_id: chat.id,
|
|
message,
|
|
badge: unseenMessages
|
|
}
|
|
if(owner.notificationSound) {
|
|
notification.sound = owner.notificationSound
|
|
}
|
|
params.notification = notification
|
|
|
|
if(type==='message' && chat.type==constants.chat_types.tribe){
|
|
debounce(()=>{
|
|
const count = tribeCounts[chat.id]?tribeCounts[chat.id]+' ':''
|
|
params.notification.message = `You have ${count}new messages in ${chat.name}`
|
|
triggerNotification(params)
|
|
}, chat.id, 30000)
|
|
} else {
|
|
triggerNotification(params)
|
|
}
|
|
}
|
|
|
|
function triggerNotification(params){
|
|
fetch("https://hub.sphinx.chat/api/v1/nodes/notify", {
|
|
method: 'POST' ,
|
|
body: JSON.stringify(params),
|
|
headers: { 'Content-Type': 'application/json' }
|
|
})
|
|
.then(res => res.json())
|
|
.then(json => {
|
|
// console.log('[hub notification]', json)
|
|
})
|
|
}
|
|
|
|
export {
|
|
pingHubInterval,
|
|
checkInvitesHubInterval,
|
|
sendHubCall,
|
|
sendNotification,
|
|
createInviteInHub,
|
|
finishInviteInHub,
|
|
payInviteInHub,
|
|
payInviteInvoice
|
|
}
|
|
|
|
// let inDebounce
|
|
// function debounce(func, delay) {
|
|
// const context = this
|
|
// const args = arguments
|
|
// clearTimeout(inDebounce)
|
|
// inDebounce = setTimeout(() => func.apply(context, args), delay)
|
|
// }
|
|
|
|
const bounceTimeouts={}
|
|
const tribeCounts = {}
|
|
function debounce(func, id, delay) {
|
|
const context = this
|
|
const args = arguments
|
|
if(bounceTimeouts[id]) clearTimeout(bounceTimeouts[id])
|
|
if(!tribeCounts[id]) tribeCounts[id]=0
|
|
tribeCounts[id]+=1
|
|
bounceTimeouts[id] = setTimeout(() => {
|
|
func.apply(context, args)
|
|
setTimeout(()=> tribeCounts[id]=0, 15)
|
|
}, delay)
|
|
}
|
|
|