Files
companion-module-toggl-track/index.js
2022-07-16 11:53:27 +00:00

409 lines
8.8 KiB
JavaScript

var instance_skel = require('../../instance_skel')
var debug
var log
function instance(system, id, config) {
var self = this
// super-constructor
instance_skel.apply(this, arguments)
return self
}
instance.prototype.updateConfig = function (config) {
var self = this
self.config = config
self.auth()
self.getWorkspace()
self.actions()
}
instance.prototype.init = function () {
var self = this
debug = self.debug
log = self.log
self.workspace = null
self.workspaceName = null
self.projects = [{ id: '0', label: 'None' }]
self.init_presets()
self.auth()
self.getWorkspace()
self.getCurrentTimer().then((result) => {
self.log('debug', 'Current timer id ' + result)
})
self.actions()
}
instance.prototype.auth = function () {
var self = this
auth = Buffer.from(self.config.apiToken + ':' + 'api_token').toString('base64')
self.header = []
self.header['Content-Type'] = 'application/json'
self.header['Authorization'] = 'Basic ' + auth
// console.log(self.header)
}
instance.prototype.config_fields = function () {
var self = this
return [
{
type: 'text',
id: 'info',
width: 12,
label: 'Information',
value: 'This module is for the toggl track service',
},
{
type: 'textinput',
id: 'apiToken',
label: 'Personal API Token from your Toggl user profile (required)',
width: 12,
default: '',
},
{
type: 'checkbox',
id: 'alwaysStart',
label: 'Enable',
width: 1,
default: false,
},
{
type: 'text',
id: 'alwaysStartTxt',
label: 'Always start a new timer even if there is one already running',
width: 11,
},
{
type: 'text',
id: 'break',
label: '',
width: 12,
},
]
}
instance.prototype.destroy = function () {
var self = this
debug('destroy', self.id)
}
instance.prototype.init_presets = function () {
var self = this
var presets = []
presets.push({
category: 'Timer',
label: 'Start',
bank: {
style: 'text',
text: 'Start Timer',
size: '18',
color: 16777215,
bgcolor: 0,
},
actions: [
{
action: 'startNewTimer',
options: {
description: '',
project: '0',
},
},
],
})
presets.push({
category: 'Timer',
label: 'Stop',
bank: {
style: 'text',
text: 'Stop Timer',
size: '18',
color: 16777215,
bgcolor: 0,
},
actions: [
{
action: 'stopCurrentTimer',
},
],
})
self.setPresetDefinitions(presets)
}
instance.prototype.actions = function (system) {
var self = this
self.setActions({
startNewTimer: {
label: 'Start New Timer',
options: [
{
type: 'textinput',
label: 'Description',
id: 'description',
default: '',
},
{
type: 'dropdown',
label: 'Project',
id: 'project',
default: '0',
choices: self.projects,
},
],
},
getCurrentTimer: {
label: 'Get Current Timer',
},
stopCurrentTimer: {
label: 'Stop Current Timer',
},
refreshProjects: {
label: 'Refresh Project List',
},
})
}
instance.prototype.action = function (action) {
var self = this
const opt = action.options
switch (action.action) {
case 'startNewTimer': {
self.getCurrentTimer().then((timerId) => {
self.log('debug', 'Current timer id ' + timerId)
if (timerId === undefined || timerId == null || self.config.alwaysStart == true) {
var cmd = 'https://api.track.toggl.com/api/v8/time_entries/start'
if (opt.project == '0') {
var body = '{"time_entry":{"description":"' + opt.description + '","created_with":"companion"}}'
} else {
var body =
'{"time_entry":{"description":"' +
opt.description +
'","created_with":"companion","pid":"' +
opt.project +
'"}}'
}
self.sendCommand('rest', cmd, body).then((result) => {
if (typeof result == 'object' && result.data !== null && result.data !== undefined) {
self.log('debug', 'New timer started ' + result.data.id)
} else {
self.log('warn', 'Error starting timer')
}
})
} else {
self.log('debug', 'A timer is already running')
}
})
break
}
case 'stopCurrentTimer': {
self.getCurrentTimer().then((timerId) => {
self.log('debug', 'Current timer id ' + timerId)
if (timerId !== null && timerId !== undefined) {
var cmd = 'https://api.track.toggl.com/api/v8/time_entries/' + timerId + '/stop'
self.sendCommand('rest_put', cmd).then((result) => {
if (typeof result == 'object' && result.data !== null && result.data !== undefined) {
self.log('debug', 'Stopped ' + result.data.id + ', duration ' + result.data.duration)
} else {
self.log('warn', 'Error stopping timer')
}
})
} else {
self.log('warn', 'No running timer to stop or running timer id unknown')
}
})
break
}
case 'getCurrentTimer': {
self.getCurrentTimer().then((result) => {
self.log('debug', 'Current timer id ' + result)
})
break
}
case 'refreshProjects': {
self.getWorkspace()
break
}
default:
break
}
}
instance.prototype.getWorkspace = function () {
var self = this
var cmd = 'https://api.track.toggl.com/api/v8/workspaces'
// console.log('getWorkspace')
// reset
self.workspace = null
// get workspace ID
self.sendCommand('rest_get', cmd).then(
(result) => {
// console.log('result ' + JSON.stringify(result, null, 4))
if (typeof result === 'object' && result !== null) {
console.log('Found ' + result.length + ' workspace')
// only interested in first workspace
if ('id' in result[0]) {
self.workspace = result[0].id
self.workspaceName = result[0].name
console.log('Workspace ' + self.workspace + ' ' + self.workspaceName)
self.log('debug', 'Workspace ' + self.workspace + ':' + self.workspaceName)
self.getProjects()
}
} else {
console.log('result ' + JSON.stringify(result, null, 4))
self.log('debug', 'No workspace')
}
},
(error) => {
console.log('error ' + error)
self.log('debug', 'Error getting workspace')
}
)
}
instance.prototype.getProjects = function () {
var self = this
if (self.workspace !== null) {
var cmd = 'https://api.track.toggl.com/api/v8/workspaces/' + self.workspace + '/projects'
self.sendCommand('rest_get', cmd).then(
(result) => {
// console.log('result ' + JSON.stringify(result, null, 4))
if (typeof result === 'object' && result !== null) {
// reset
self.projects = []
for (p = 0; p < result.length; p++) {
if ('id' in result[p]) {
self.projects.push({
id: result[p].id.toString(),
label: result[p].name,
})
self.log('debug', 'Project ' + result[p].id + ':' + result[p].name)
}
}
self.projects.sort((a, b) => {
fa = a.label.toLowerCase()
fb = b.label.toLowerCase()
if (fa < fb) {
return -1
}
if (fa > fb) {
return 1
}
return 0
})
self.projects.unshift({ id: '0', label: 'None' })
console.log('Projects:')
console.log(self.projects)
self.actions()
} else {
console.log(result)
self.log('debug', 'No projects')
}
},
(error) => {
console.log('error ' + error)
self.log('debug', 'Error getting projects')
}
)
}
}
instance.prototype.getCurrentTimer = function () {
var self = this
var cmd = 'https://api.track.toggl.com/api/v8/time_entries/current'
return new Promise((resolve, reject) => {
self.sendCommand('rest_get', cmd).then(
(result) => {
if (typeof result === 'object' && result.data !== null && result.data !== undefined) {
if ('id' in result.data) {
console.log('current timer: ' + result.data.id)
resolve(result.data.id)
} else {
console.log('getCurrentTimer: No timer id found')
resolve(null)
}
} else {
console.log('getCurrentTimer: No timer running')
resolve(null)
}
},
(error) => {
console.log('error ' + error)
self.log('debug', 'Error getting current timer')
}
)
})
}
instance.prototype.sendCommand = function (mode, command, body = '') {
var self = this
console.log(mode + ' : ' + command)
switch (mode) {
case 'rest_get': {
return new Promise((resolve, reject) => {
self.system.emit(
mode,
command,
(err, { data, error, response }) => {
if (err) {
self.status(self.STATUS_ERROR)
console.log(error)
reject(error)
return
}
self.status(self.STATUS_OK)
resolve(data)
},
self.header
)
})
break
}
case 'rest':
case 'rest_put': {
return new Promise((resolve, reject) => {
self.system.emit(
mode,
command,
body,
(err, { data, error, response }) => {
if (err) {
self.status(self.STATUS_ERROR)
console.log(error)
reject(error)
return
}
self.status(self.STATUS_OK)
resolve(data)
},
self.header
)
})
break
}
}
}
instance_skel.extendedBy(instance)
exports = module.exports = instance