2015-08-29 02:38:59 +02:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
|
|
|
var os = require('os')
|
|
|
|
var fs = require('fs')
|
2015-08-30 01:49:03 +02:00
|
|
|
var moment = require('moment')
|
2015-08-29 02:38:59 +02:00
|
|
|
var blessed = require('blessed')
|
|
|
|
|
2015-08-31 14:04:32 +02:00
|
|
|
var data = {} // Hold all global data
|
|
|
|
require('./lib/util.js')(data) // Load utils
|
|
|
|
require('./lib/ui.js')(data) // Load ui
|
|
|
|
|
|
|
|
var path = require('path')
|
|
|
|
|
|
|
|
data.cfgDir = path.join(process.env.XDG_CONFIG_HOME || (path.join(process.env.HOME || process.env.USERPROFILE, '/.config/')), 'telecommander/')
|
|
|
|
process.env.LOGGER_FILE = data.cfgDir+'log'
|
|
|
|
|
2015-08-30 16:40:01 +02:00
|
|
|
/* IF YOU FORK THE APP PLEASE CHANGE THE ID
|
|
|
|
* AND HASH IN THE APP OBJECT! THEY IDENTIFY
|
|
|
|
* THE APPLICATION CREATOR AND YOU CAN
|
|
|
|
* OBTAIN YOURS FROM http://my.telegram.org
|
|
|
|
*/
|
2015-08-31 14:04:32 +02:00
|
|
|
data.app = {
|
2015-08-30 16:40:01 +02:00
|
|
|
id: '42419',
|
|
|
|
hash: '90a3c2cdbf9b391d9ed72c0639dc0786',
|
|
|
|
version: require('./package.json').version,
|
|
|
|
lang: 'en',
|
|
|
|
deviceModel: os.type(),
|
|
|
|
systemVersion: os.platform()+'/'+os.release()
|
|
|
|
}
|
|
|
|
|
2015-08-29 02:38:59 +02:00
|
|
|
try { fs.makeDirSync(cfgDir,'0770') } catch (e) { }
|
|
|
|
|
2015-08-31 14:04:32 +02:00
|
|
|
// Logger
|
2015-08-29 02:38:59 +02:00
|
|
|
var getLogger = require('get-log')
|
|
|
|
getLogger.PROJECT_NAME = 'telecommander'
|
2015-08-31 14:04:32 +02:00
|
|
|
data.logger = getLogger('main')
|
2015-08-29 02:38:59 +02:00
|
|
|
|
2015-08-31 14:04:32 +02:00
|
|
|
data.telegramLink = require('telegram.link')()
|
|
|
|
data.authKey // our authorization key to access telegram
|
|
|
|
data.connected = false // keep track of wether we are good to go and logged in
|
2015-08-29 02:38:59 +02:00
|
|
|
|
2015-08-31 00:19:30 +02:00
|
|
|
// Write something in the Status box
|
2015-08-31 14:04:32 +02:00
|
|
|
data.log = function(){
|
2015-08-31 00:19:30 +02:00
|
|
|
args = Array.prototype.slice.call(arguments)
|
|
|
|
var msg = args.join(' ')
|
2015-08-31 14:04:32 +02:00
|
|
|
data.getMsgBox(data.statusWindow).add(msg)
|
|
|
|
data.logger.info(msg)
|
2015-08-31 00:19:30 +02:00
|
|
|
}
|
|
|
|
|
2015-08-31 14:04:32 +02:00
|
|
|
data.command = function(cmd){
|
2015-08-29 04:09:03 +02:00
|
|
|
cmdl = cmd.split(' ')
|
|
|
|
cmdname = cmdl[0]
|
2015-08-29 02:38:59 +02:00
|
|
|
|
2015-08-29 13:51:14 +02:00
|
|
|
if(cmdname === 'phone'){ // So the user can provide his phone numbah
|
|
|
|
if(connected){
|
|
|
|
return log("Silly user, you're already connected! We don't need that phone number")
|
|
|
|
}
|
2015-08-30 12:16:41 +02:00
|
|
|
user.phone = cmd.split(' ')[1]
|
|
|
|
var mindate = moment()
|
2015-08-31 00:47:36 +02:00
|
|
|
log('Checking your phone number with Telegram...')
|
2015-08-30 12:16:41 +02:00
|
|
|
client.auth.sendCode(user.phone,5,'en',function(result){
|
|
|
|
if(result.err_code){
|
|
|
|
return log('Errors:',result.error_code,result.error_message)
|
|
|
|
}
|
|
|
|
//log('Res:',JSON.stringify(result))
|
|
|
|
user.registered = result.phone_registered
|
|
|
|
user.phoneCodeHash = result.phone_code_hash
|
|
|
|
function gmd(){
|
|
|
|
var m = moment()
|
|
|
|
m = m.subtract(m.diff(mindate))
|
|
|
|
return 'Please use a telegram code not older than '+m.fromNow(true)
|
|
|
|
}
|
|
|
|
if(!user.registered){
|
2015-08-31 00:47:36 +02:00
|
|
|
log("Your number is not registered. Telecommander will register your account with the Telegram service")
|
2015-08-30 12:38:02 +02:00
|
|
|
log(gmd())
|
2015-08-29 02:38:59 +02:00
|
|
|
log('Ready for phone code, use command: "code <code> <name> <lastname>" to register')
|
2015-08-31 00:47:36 +02:00
|
|
|
log("If you don't want to sign up, just don't enter the code and press ESC to exit. No data was saved to the file system")
|
2015-08-29 02:38:59 +02:00
|
|
|
} else {
|
2015-08-31 00:47:36 +02:00
|
|
|
log("Your number is already assigned to a Telegram account. Telecommander will log you in.")
|
2015-08-30 12:38:02 +02:00
|
|
|
log(gmd())
|
2015-08-31 00:47:36 +02:00
|
|
|
log("If you don't want to sign in, just don't enter the code and press ESC to exit. No data was saved to the file system")
|
2015-08-29 02:38:59 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2015-08-29 13:51:14 +02:00
|
|
|
} else if(cmdname === 'code'){ // So the user can provide his phone code
|
|
|
|
if(connected){
|
|
|
|
return log("Silly user, you're already connected! We don't need that phone code")
|
|
|
|
}
|
2015-08-29 02:38:59 +02:00
|
|
|
code = cmdl[1]
|
|
|
|
name = cmdl[2]
|
|
|
|
lastname = cmdl[3]
|
2015-08-30 12:16:41 +02:00
|
|
|
if(((!name || !lastname) && !user.registered) || !code)
|
2015-08-29 02:38:59 +02:00
|
|
|
return log('insufficient arguments:',cmd)
|
|
|
|
cb = function(result){
|
2015-08-30 12:16:41 +02:00
|
|
|
user.id = ''+result.user.id
|
|
|
|
user.phone = result.user.phone
|
|
|
|
user.phoneCodeHash = result.phone_code_hash
|
|
|
|
user.username = result.user.username
|
|
|
|
user.first_name = result.user.first_name
|
|
|
|
user.last_name = result.user.last_name
|
|
|
|
// Done, write user data and key to disk
|
2015-08-31 00:47:36 +02:00
|
|
|
log('Writing Log In token and user data to',cfgDir)
|
2015-08-30 12:16:41 +02:00
|
|
|
fs.writeFile(cfgDir+'key',authKey,function(err){
|
2015-08-31 00:47:36 +02:00
|
|
|
if(err) log('FATAL: Could not write key to disk:',err)
|
2015-08-30 12:16:41 +02:00
|
|
|
})
|
|
|
|
fs.writeFile(cfgDir+'user_data.json',JSON.stringify(user),function(err){
|
2015-08-31 00:47:36 +02:00
|
|
|
if(err) log("FATAL: couldn't write user_data.json:",err)
|
2015-08-30 12:16:41 +02:00
|
|
|
})
|
2015-08-29 02:38:59 +02:00
|
|
|
whenReady()
|
|
|
|
}
|
|
|
|
// Log in finally
|
2015-08-30 12:16:41 +02:00
|
|
|
if(user.registered) client.auth.signIn(user.phone,user.phoneCodeHash,code,cb)
|
|
|
|
else client.auth.signUp(user.phone,user.phoneCodeHash,code,name,lastname,cb)
|
2015-08-31 00:19:30 +02:00
|
|
|
} else {
|
|
|
|
log('Command not found.')
|
2015-08-29 02:38:59 +02:00
|
|
|
}
|
|
|
|
}
|
2015-08-29 13:51:14 +02:00
|
|
|
|
|
|
|
// Send a message
|
2015-08-31 14:04:32 +02:00
|
|
|
data.sendMsg = function(name,str){
|
|
|
|
if(!data.connected){
|
2015-08-29 13:51:14 +02:00
|
|
|
return log('Error: not ready to send messages')
|
|
|
|
}
|
2015-08-31 14:04:32 +02:00
|
|
|
var obj = data.nameToObj(name)
|
|
|
|
var peer = data.idToPeer(obj.id,obj.title?'group':'user')
|
2015-08-29 13:51:14 +02:00
|
|
|
var randid = parseInt(Math.random() * 1000000000)
|
2015-08-31 03:03:28 +02:00
|
|
|
//log('Sending Message to:',peer.toPrintable())
|
2015-08-31 14:04:32 +02:00
|
|
|
data.client.messages.sendMessage(peer,str,randid,function(sent){
|
2015-08-31 03:03:28 +02:00
|
|
|
//log('Sent message:','"'+str+'"','to:',selectedWindow+':',sent.toPrintable())
|
2015-08-29 13:51:14 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-08-29 02:38:59 +02:00
|
|
|
// Connects to telegram
|
2015-08-31 14:04:32 +02:00
|
|
|
data.connect = function(){
|
|
|
|
data.client = data.telegramLink.createClient(data.app, data.telegramLink.PROD_PRIMARY_DC, function(){
|
|
|
|
if(!data.app.authKey){
|
2015-08-31 00:47:36 +02:00
|
|
|
log('Downloading Authorization Key...')
|
2015-08-31 14:04:32 +02:00
|
|
|
data.client.createAuthKey(function(auth){
|
|
|
|
data.app.authKey = auth.key.encrypt('password') // Will add security later, I promise
|
2015-08-30 12:38:02 +02:00
|
|
|
// Writes the new encrypted key to disk
|
2015-08-31 14:04:32 +02:00
|
|
|
data.log('Ready for phone number, use command: phone <number>')
|
2015-08-29 02:38:59 +02:00
|
|
|
})
|
|
|
|
} else {
|
2015-08-31 14:04:32 +02:00
|
|
|
data.whenReady()
|
2015-08-29 02:38:59 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2015-08-31 14:04:32 +02:00
|
|
|
data.client.once('dataCenter',function(dcs){
|
|
|
|
data.log('Datacenters:',dcs.toPrintable())
|
2015-08-29 02:38:59 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-08-29 13:51:14 +02:00
|
|
|
// Executed when connected and logged in
|
2015-08-31 14:04:32 +02:00
|
|
|
data.whenReady = function(){
|
2015-08-31 14:35:08 +02:00
|
|
|
data.log('Connected')
|
2015-08-31 14:04:32 +02:00
|
|
|
data.connected = true
|
|
|
|
data.downloadData()
|
2015-08-31 16:53:38 +02:00
|
|
|
data.chats.focus()
|
2015-08-29 02:38:59 +02:00
|
|
|
}
|
|
|
|
|
2015-08-29 13:51:14 +02:00
|
|
|
// Downloads stuff
|
2015-08-31 14:04:32 +02:00
|
|
|
data.downloadData = function(){
|
|
|
|
data.log('Downloading data...')
|
|
|
|
data.client.contacts.getContacts('',function(cont){
|
|
|
|
data.chats.clearItems()
|
|
|
|
data.chats.add(data.statusWindow)
|
|
|
|
cont.users.list.forEach(data.addUser)
|
2015-08-29 02:38:59 +02:00
|
|
|
})
|
2015-08-30 01:49:03 +02:00
|
|
|
|
2015-08-31 14:04:32 +02:00
|
|
|
data.client.messages.getDialogs(0,0,10,function(dialogs){
|
2015-08-31 00:47:36 +02:00
|
|
|
if(dialogs && dialogs.chats && dialogs.chats.list)
|
2015-08-31 14:04:32 +02:00
|
|
|
dialogs.chats.list.forEach(data.addGroup)
|
2015-08-30 01:49:03 +02:00
|
|
|
})
|
|
|
|
|
2015-08-31 14:04:32 +02:00
|
|
|
data.client.updates.getState(function(astate){
|
|
|
|
data.updateState(astate)
|
|
|
|
data.log(data.state.unreadCount,'unread messages')
|
2015-08-31 14:35:08 +02:00
|
|
|
//data.log('Started receiving updates')
|
2015-08-30 12:16:41 +02:00
|
|
|
// Can't use registerOnUpdates because it's apparently broken
|
|
|
|
//client.registerOnUpdates(onUpdate)
|
2015-08-31 14:04:32 +02:00
|
|
|
setTimeout(data.downloadUpdates,1000)
|
2015-08-29 13:51:14 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-08-31 14:04:32 +02:00
|
|
|
data.downloadUpdates = function(){
|
|
|
|
data.client.updates.getDifference(data.state.pts,data.state.date,data.state.qts,function(res){
|
2015-08-30 16:40:01 +02:00
|
|
|
if(!res.instanceOf('api.type.updates.DifferenceEmpty')){
|
2015-08-31 03:08:44 +02:00
|
|
|
//log('Got Diff: ',res.toPrintable())
|
2015-08-30 16:40:01 +02:00
|
|
|
if(res.state){
|
2015-08-31 14:04:32 +02:00
|
|
|
data.updateState(res.state)
|
2015-08-30 16:40:01 +02:00
|
|
|
}
|
2015-08-31 03:37:34 +02:00
|
|
|
if(res.chats)
|
2015-08-31 14:04:32 +02:00
|
|
|
for(c in res.chats.list) data.addGroup(c)
|
2015-08-31 03:37:34 +02:00
|
|
|
if(res.users)
|
2015-08-31 14:04:32 +02:00
|
|
|
for(c in res.users.list) data.addUser(c)
|
2015-08-30 16:40:01 +02:00
|
|
|
if(res.new_messages){
|
|
|
|
res.new_messages.list.forEach(function(msg){
|
2015-08-31 14:04:32 +02:00
|
|
|
data.appendMsg(msg,undefined,false,true)
|
2015-08-30 16:40:01 +02:00
|
|
|
})
|
|
|
|
}
|
2015-08-30 12:16:41 +02:00
|
|
|
}
|
2015-08-31 14:04:32 +02:00
|
|
|
setTimeout(data.downloadUpdates,1000)
|
2015-08-30 12:16:41 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-08-30 20:29:02 +02:00
|
|
|
// Get message history with given name in the given box
|
2015-08-31 14:04:32 +02:00
|
|
|
data.getMessages = function(name,box){
|
|
|
|
if(!data.connected){
|
2015-08-29 13:51:14 +02:00
|
|
|
return log('Uh cant get messages cuz not connected.....')
|
|
|
|
}
|
2015-08-30 20:29:02 +02:00
|
|
|
//log('Name to obj:',name)
|
2015-08-31 14:04:32 +02:00
|
|
|
var obj = data.nameToObj(name)
|
2015-08-30 20:29:02 +02:00
|
|
|
if(!obj || !obj.id){
|
2015-08-31 14:04:32 +02:00
|
|
|
return data.log("Can't get messages",obj,obj.id,obj.title)
|
2015-08-30 20:29:02 +02:00
|
|
|
}
|
|
|
|
var type = obj.title?'group':'user'
|
2015-08-31 14:04:32 +02:00
|
|
|
var peer = data.idToPeer(obj.id,type)
|
2015-08-30 20:29:02 +02:00
|
|
|
box.add('Downloading message history for '+name)
|
|
|
|
if(!peer) return log('Could not find peer:',name)
|
2015-08-31 16:53:38 +02:00
|
|
|
data.client.messages.getHistory(peer,0,-1,100,function(res){
|
2015-08-30 01:49:03 +02:00
|
|
|
//log(res.toPrintable())
|
2015-08-31 03:03:28 +02:00
|
|
|
//log('Got history for: '+getName(peer.user_id||peer.chat_id,peer.chat_id?'group':'user'))
|
2015-08-30 16:40:01 +02:00
|
|
|
if(!res.messages){
|
|
|
|
return box.add(res.toPrintable())
|
|
|
|
}
|
2015-08-30 01:49:03 +02:00
|
|
|
res.messages.list.sort(function(msg1,msg2){
|
|
|
|
return msg1.date - msg2.date
|
|
|
|
})
|
|
|
|
if(res.messages.list.length === 0)
|
2015-08-31 14:04:32 +02:00
|
|
|
return data.appendToUserBox('No messages.',res)
|
2015-08-29 13:51:14 +02:00
|
|
|
res.messages.list.forEach(function(msg){
|
2015-08-31 03:03:28 +02:00
|
|
|
//if(!msg.message) return log('Empty message!',msg.toPrintable())
|
2015-08-30 20:29:02 +02:00
|
|
|
//log('Scheduling message: '+msg.toPrintable())
|
2015-08-31 14:04:32 +02:00
|
|
|
data.appendMsg(msg)
|
2015-08-29 13:51:14 +02:00
|
|
|
})
|
2015-08-29 02:38:59 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-08-31 14:04:32 +02:00
|
|
|
data.appendToUserBox = function(msg,context){
|
2015-08-30 12:16:41 +02:00
|
|
|
var goesto
|
|
|
|
if(context.messages.list.length > 0){
|
|
|
|
if(context.messages.list[0].to_id.chat_id){
|
|
|
|
// Group message
|
2015-08-31 14:04:32 +02:00
|
|
|
data.log('Chose',data.getName(context.messages.list[0].to_id.chat_id,'group'))
|
|
|
|
goesto = data.getMsgBox(data.getName(context.messages.list[0].to_id.chat_id))
|
2015-08-30 12:16:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(goesto === undefined){
|
2015-08-31 15:32:39 +02:00
|
|
|
if(context.users.list[0].user_id == data.user.id){
|
|
|
|
goesto = data.getMsgBox(data.getName(context.users.list[1].id,'user'))
|
2015-08-30 12:16:41 +02:00
|
|
|
} else{
|
2015-08-31 15:32:39 +02:00
|
|
|
goesto = data.getMsgBox(data.getName(context.users.list[0].id,'user'))
|
2015-08-30 12:16:41 +02:00
|
|
|
}
|
|
|
|
}
|
2015-08-31 14:04:32 +02:00
|
|
|
data.appendMsg(msg,goesto,true)
|
2015-08-30 12:16:41 +02:00
|
|
|
}
|
|
|
|
|
2015-08-30 01:49:03 +02:00
|
|
|
// Writes given telegram.link "message" object to given boxId
|
2015-08-31 14:04:32 +02:00
|
|
|
data.appendMsg = function(msg,toBoxId,bare,smartmode){
|
2015-08-30 12:38:02 +02:00
|
|
|
var box,param
|
2015-08-30 12:16:41 +02:00
|
|
|
if(toBoxId != undefined){
|
|
|
|
box = toBoxId
|
|
|
|
} else {
|
2015-08-30 20:29:02 +02:00
|
|
|
if(msg.to_id.chat_id != undefined){
|
|
|
|
// Is a group
|
2015-08-31 14:04:32 +02:00
|
|
|
param = data.getName(msg.to_id.chat_id,'group')
|
2015-08-31 14:35:08 +02:00
|
|
|
} else if(msg.from_id === msg.to_id.user_id || msg.from_id != data.user.id){
|
2015-08-31 14:04:32 +02:00
|
|
|
param = data.getName(msg.from_id,'user')
|
2015-08-31 14:35:08 +02:00
|
|
|
} else if(msg.to_id.user_id != undefined && msg.to_id.user_id != data.user.id) {
|
2015-08-30 12:16:41 +02:00
|
|
|
// don't forget dat .user_id! don't need it in from_id...
|
2015-08-31 14:04:32 +02:00
|
|
|
param = data.getName(msg.to_id.user_id,'user')
|
2015-08-30 12:38:02 +02:00
|
|
|
}
|
|
|
|
if(smartmode && !bare){
|
|
|
|
// Smart mode doesn't append the message to the box if it doesn't exist
|
|
|
|
// because when created, the box will download message history
|
2015-08-31 14:04:32 +02:00
|
|
|
if(data.msgBox[param] === undefined) return;
|
2015-08-30 12:16:41 +02:00
|
|
|
}
|
2015-08-31 14:04:32 +02:00
|
|
|
box = data.getMsgBox(param)
|
2015-08-30 12:16:41 +02:00
|
|
|
}
|
|
|
|
if(bare)
|
|
|
|
box.add(msg)
|
|
|
|
else {
|
|
|
|
var from = msg.from_id
|
|
|
|
var date = moment.unix(msg.date).fromNow()
|
2015-08-31 14:04:32 +02:00
|
|
|
name = data.getName(from,'user')
|
2015-08-31 03:03:28 +02:00
|
|
|
var txt
|
|
|
|
if(msg.media){
|
|
|
|
if(msg.media.photo)
|
|
|
|
txt = ' <*> (Photo)'
|
|
|
|
else if(msg.media.audio)
|
|
|
|
txt = " <*> (Audio Message) "+msg.media.audio.duration+" seconds"
|
|
|
|
else if(msg.message)
|
|
|
|
txt = ' > '+msg.message
|
|
|
|
else txt = " <*> (Unsupported Message)"
|
|
|
|
}
|
|
|
|
box.add(date+' | '+(name || from)+txt)
|
2015-08-30 12:16:41 +02:00
|
|
|
}
|
2015-08-30 01:49:03 +02:00
|
|
|
}
|
|
|
|
|
2015-08-30 12:16:41 +02:00
|
|
|
// - Entry Point -
|
|
|
|
// Load authKey and userdata from disk, then act depending on outcome
|
2015-08-31 14:04:32 +02:00
|
|
|
data.screen.render()
|
|
|
|
var keyPath = data.cfgDir+'key'
|
|
|
|
data.log('Loading files...')
|
2015-08-29 02:38:59 +02:00
|
|
|
fs.exists(keyPath,function(exists){
|
|
|
|
if(exists){
|
2015-08-31 00:47:36 +02:00
|
|
|
//log('Authorization Key found')
|
2015-08-29 02:38:59 +02:00
|
|
|
fs.readFile(keyPath,function(err,content){
|
|
|
|
if(err)
|
2015-08-31 14:04:32 +02:00
|
|
|
data.log('Error while reading key:',err)
|
2015-08-29 02:38:59 +02:00
|
|
|
else {
|
2015-08-31 14:04:32 +02:00
|
|
|
data.app.authKey = data.telegramLink.retrieveAuthKey(content,'password') // yeah sorry just testing
|
|
|
|
data.log('Authorization Key found')
|
|
|
|
fs.readFile(data.cfgDir+'user_data.json',function(err,res){
|
2015-08-30 12:16:41 +02:00
|
|
|
if(err)
|
2015-08-31 14:04:32 +02:00
|
|
|
data.log("FATAL: couldn't read user_data.json")
|
2015-08-30 12:16:41 +02:00
|
|
|
else {
|
|
|
|
try {
|
2015-08-31 14:04:32 +02:00
|
|
|
data.user = JSON.parse(res)
|
|
|
|
data.log('Welcome',data.getName(data.user.id,'user'))
|
2015-08-30 12:16:41 +02:00
|
|
|
} catch (e) {
|
2015-08-31 14:04:32 +02:00
|
|
|
data.log("FATAL: user data corrupted:",e)
|
2015-08-30 12:16:41 +02:00
|
|
|
}
|
2015-08-31 14:04:32 +02:00
|
|
|
data.connect()
|
2015-08-30 12:16:41 +02:00
|
|
|
}
|
|
|
|
})
|
2015-08-29 02:38:59 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
} else {
|
2015-08-31 14:04:32 +02:00
|
|
|
data.connect()
|
2015-08-29 02:38:59 +02:00
|
|
|
}
|
|
|
|
})
|