1
0
mirror of https://github.com/fazo96/telecommander.git synced 2025-01-10 11:34:20 +01:00
telecommander/telecommander.js

382 lines
10 KiB
JavaScript
Raw Normal View History

2015-08-29 02:38:59 +02:00
#!/usr/bin/env node
2015-08-29 13:51:14 +02:00
// Prepare deps and fs
2015-08-29 02:38:59 +02:00
var cfgDir = (process.env.HOME || process.env.USERPROFILE) + '/.config/telecommander/'
process.env.LOGGER_FILE = cfgDir+'log'
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')
try { fs.makeDirSync(cfgDir,'0770') } catch (e) { }
var getLogger = require('get-log')
getLogger.PROJECT_NAME = 'telecommander'
var logger = getLogger('main')
var telegramLink = require('telegram.link')()
2015-08-29 13:51:14 +02:00
// Prepare blessed UI
2015-08-29 02:38:59 +02:00
var screen = blessed.screen({
smartCSR: true,
dockBorders: true
})
screen.title = "Telecommander"
var defaultStyle = {
fg: 'white',
border: { fg: 'gray' },
scrollbar: {
bg: 'blue',
fg: 'red'
}
}
2015-08-29 13:51:14 +02:00
// Function to create a log box
function mkBox(){
return blessed.log({
right: 0,
width: '80%',
height: screen.height-3,
border: { type: 'line' },
scrollable: true,
style: defaultStyle
})
2015-08-29 02:38:59 +02:00
}
2015-08-29 13:51:14 +02:00
// Contact list window
2015-08-29 02:38:59 +02:00
var chats = blessed.list({
left: 0,
top:0,
height: screen.height-3,
width: '20%',
border: { type: 'line' },
mouse: true,
style: defaultStyle,
})
chats.style.selected = { bg: 'blue' }
2015-08-29 02:38:59 +02:00
2015-08-29 13:51:14 +02:00
// Command line prompt
2015-08-29 02:38:59 +02:00
var cmdline = blessed.textbox({
inputOnFocus: true,
bottom: 0,
left: 'center',
width: '100%',
height: 3,
border: { type: 'line' },
style: defaultStyle
})
2015-08-29 13:51:14 +02:00
var statusWindow = "Status"
// mgsBox holds the chat boxes for every list entry
var msgBox = { }
msgBox[statusWindow] = mkBox()
2015-08-29 13:51:14 +02:00
// Add stuff to the screen
2015-08-29 02:38:59 +02:00
screen.append(chats);
screen.append(cmdline);
2015-08-29 13:51:14 +02:00
screen.append(msgBox[statusWindow]);
2015-08-29 02:38:59 +02:00
2015-08-30 01:49:03 +02:00
// Contacts holds all the contacts data
2015-08-29 02:38:59 +02:00
var contacts = { }
2015-08-30 01:49:03 +02:00
// Groups hold all the data about groups
var groups = { }
2015-08-29 13:51:14 +02:00
// nameToUid is used to match a name to its user id (for the contact list)
var nameToUid = { }
2015-08-29 02:38:59 +02:00
2015-08-30 01:49:03 +02:00
var state // keeps track of the last time the client was updated
2015-08-29 13:51:14 +02:00
var client // used to talk with telegram
var phone // our phone number
var code // our phone code
var phoneCodeHash // our phone code thingy that telegram wants
var fullName
var username
var loginResult // Store here the server answer to the login
var uid // our user id
var authKey // our authorization key to access telegram
var registered = false // keep track of wether the phone number is registered
var connected = false // keep track of wether we are good to go and logged in
var selectedWindow = statusWindow // the currently selected window
2015-08-29 02:38:59 +02:00
function command(cmd){
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-29 02:38:59 +02:00
phone = cmd.split(' ')[1]
client.auth.sendCode(phone,5,'en',function(result){
log('Errors:',result.error_code,result.error_message)
if(result.error_code) return
log('Res:',JSON.stringify(result))
registered = result.phone_registered
phoneCodeHash = result.phone_code_hash
if(!registered){
log("Your number is not registered. The client will register your account with the Telegram service")
log('Ready for phone code, use command: "code <code> <name> <lastname>" to register')
} else {
log("Your number is already registered with telegram. The client will log in.")
log('Ready for phone code, use command: "code <code>" to login')
}
})
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]
if(((!name || !lastname) && !registered) || !code)
return log('insufficient arguments:',cmd)
cb = function(result){
loginResult = result
log('Result:',JSON.stringify(result))
whenReady()
}
// Log in finally
if(registered) client.auth.signIn(phone,phoneCodeHash,code,cb)
else client.auth.signUp(phone,phoneCodeHash,code,name,lastname,cb)
2015-08-29 13:51:14 +02:00
} else if(cmdname === 'msg'){ // Send a message
msg(cmdl[1],cmdl[2])
2015-08-29 02:38:59 +02:00
}
}
2015-08-29 13:51:14 +02:00
chats.addItem(msgBox[statusWindow])
screen.render();
// What happens when a different window is selected
chats.on('select',function(selected){
log('SELECT:',selected.content)
2015-08-29 13:51:14 +02:00
msgBox[selectedWindow].hide()
selectedWindow = selected.content;
2015-08-30 01:49:03 +02:00
var newb = getMsgBox(selectedWindow)
newb.show()
})
2015-08-29 02:38:59 +02:00
2015-08-30 01:49:03 +02:00
// Get msgBox for given chat, create if not exists
function getMsgBox(chat){
// Automatically convert ids to names
if(contacts[chat]) chat = contacts[chat].user.id
if(groups[chat]); // To be implemented
if(!msgBox[chat]){
log('Generating window: "'+chat+'"')
msgBox[chat] = mkBox()
screen.append(msgBox[chat])
var uid = nameToUid[chat]
if(uid != undefined){
// Is a real user: download messages and stuff
getMessages(uid,msgBox[chat])
}
}
return msgBox[chat]
}
2015-08-29 13:51:14 +02:00
// What happens when the user submits a command in the prompt
2015-08-29 02:38:59 +02:00
cmdline.on('submit',function(value){
2015-08-30 01:49:03 +02:00
msgBox[statusWindow].add('< '+value)
2015-08-29 13:51:14 +02:00
if(nameToUid[selectedWindow] == undefined){
command(value)
} else {
// Send Message
2015-08-29 13:51:14 +02:00
msg(nameToUid[selectedWindow],value)
}
2015-08-29 02:38:59 +02:00
cmdline.clearValue()
cmdline.focus()
})
2015-08-29 13:51:14 +02:00
cmdline.focus() // make sure prompt is focused
// Catch ctrl-c or escape event and close program
2015-08-29 02:38:59 +02:00
cmdline.key(['escape','C-c'], function(ch,key){
2015-08-29 13:51:14 +02:00
if(connected || client != undefined){
2015-08-29 02:38:59 +02:00
log('Closing communications and shutting down...')
client.end(function(){
process.exit(0)
})
} else process.exit(0);
});
2015-08-29 13:51:14 +02:00
// Send a message
function msg(uid,str){
if(!connected){
return log('Error: not ready to send messages')
}
var peer = new telegramLink.type.InputPeerContact({ props: { user_id: ''+uid } })
var randid = parseInt(Math.random() * 1000000000)
client.messages.sendMessage(peer,str,randid,function(sent){
log('Send message:','"'+str+'"','to:',selectedWindow+':',sent.toPrintable())
})
}
// Write something in the Status box
2015-08-29 02:38:59 +02:00
function log(){
args = Array.prototype.slice.call(arguments)
2015-08-29 13:51:14 +02:00
var msg = args.join(' ')
msgBox[statusWindow].add(msg)
2015-08-29 02:38:59 +02:00
logger.info(msg)
}
2015-08-29 13:51:14 +02:00
// Prepare data to feed to telegramLink
2015-08-29 02:38:59 +02:00
var app = {
id: '42419',
hash: '90a3c2cdbf9b391d9ed72c0639dc0786',
version: require('./package.json').version,
lang: 'en',
deviceModel: os.type(),
systemVersion: os.platform()+'/'+os.release()
}
// Connects to telegram
function connect(){
client = telegramLink.createClient(app, telegramLink.PROD_PRIMARY_DC, function(){
if(!app.authKey){
log('Creating authkey...')
client.createAuthKey(function(auth){
authKey = auth.key.encrypt('password') // I know sorry, but I'm testing. Will add security later, I promise
// Writes the new encrypted key to disk
fs.writeFile(keyPath,authKey,function(err){
if(err)
log('Could not write key to disk:',err)
else
log('Done writing key to disk')
})
log('Created key, writing it to disk')
log('ready for phone number, use command: phone <number>')
})
} else {
log('Authkey loaded from disk. Should be ready to go.')
whenReady()
}
})
client.once('dataCenter',function(dcs){
log('Datacenters:',dcs.toPrintable())
})
}
2015-08-29 13:51:14 +02:00
// Executed when connected and logged in
2015-08-29 02:38:59 +02:00
function whenReady(){
log('READY!')
2015-08-29 13:51:14 +02:00
connected = true
2015-08-29 02:38:59 +02:00
downloadData()
}
2015-08-29 13:51:14 +02:00
// Downloads stuff
2015-08-29 02:38:59 +02:00
function downloadData(){
log('Downloading data...')
2015-08-30 01:49:03 +02:00
2015-08-29 02:38:59 +02:00
client.contacts.getContacts('',function(cont){
chats.clearItems()
2015-08-29 13:51:14 +02:00
chats.add(statusWindow)
cont.users.list.forEach(function(user,index){
2015-08-30 01:49:03 +02:00
if(!contacts[user.id]) contacts[user.id] = {}
contacts[user.id].user = user
var name = getName(user.id)
2015-08-29 13:51:14 +02:00
nameToUid[name] = user.id
2015-08-30 01:49:03 +02:00
chats.addItem(name)
log('Added user:',user.id,'-',name)
})
2015-08-29 02:38:59 +02:00
})
2015-08-30 01:49:03 +02:00
2015-08-29 13:51:14 +02:00
client.messages.getDialogs(0,0,10,function(dialogs){
2015-08-30 01:49:03 +02:00
dialogs.dialogs.list.forEach(function(item){
if(item.peer.chat_id){ // is a group
groups[item.peer.chat_id] = item
log('Added group:',item.peer.chat_id)
}
})
})
client.updates.getState(function(astate){
log('ADDING LISTENER FOR UPDATES')
client.registerOnUpdates(onUpdate)
log('Started receiving updates\nGot State:',astate.toPrintable())
2015-08-29 13:51:14 +02:00
})
}
2015-08-30 01:49:03 +02:00
// Called when the server sends an update
function onUpdate(upd){
return
log('Got Update:',upd.toPrintable())
// Process update
if(update.message){
// It's a chat message
log('Writing chat message to ',update.from_id)
//appendMsg(update,getName(update.from_id))
}
}
function getName(uid){
var user = contacts[uid]
if(!contacts[uid])
return
else
user = contacts[uid].user
return user.first_name + ' ' + user.last_name + (user.username?' ('+user.username+')':'')
}
// Get message history with given id in the given box
function getMessages(uid,box){
2015-08-29 13:51:14 +02:00
if(!connected){
return log('Uh cant get messages cuz not connected.....')
}
2015-08-30 01:49:03 +02:00
box.add('Downloading message history for '+getName(uid))
2015-08-29 13:51:14 +02:00
var peer = new telegramLink.type.InputPeerContact({ props: { user_id: uid } })
client.messages.getHistory(peer,0,-1,20,function(res){
2015-08-30 01:49:03 +02:00
//log(res.toPrintable())
var rbox = getMsgBox(getName(peer.user_id))
log('Got history for: '+getName(uid))
res.messages.list.sort(function(msg1,msg2){
return msg1.date - msg2.date
})
if(res.messages.list.length === 0)
return rbox.add('No messages.')
rbox.add('Printing...')
for(i in res.messages.list){
appendMsg(res.messages.list[i],rbox)
}
/*
2015-08-29 13:51:14 +02:00
res.messages.list.forEach(function(msg){
if(!msg.message) return;
2015-08-30 01:49:03 +02:00
appendMsg(msg,rbox)
2015-08-29 13:51:14 +02:00
})
2015-08-30 01:49:03 +02:00
*/
2015-08-29 02:38:59 +02:00
})
}
2015-08-30 01:49:03 +02:00
// Writes given telegram.link "message" object to given boxId
function appendMsg(msg,toBoxId){
var from = msg.from_id
var date = moment.unix(msg.date).fromNow()
name = getName(from)
toBoxId.add(date+' | '+(name || from)+' > '+msg.message)
}
2015-08-29 13:51:14 +02:00
// Try to load key from disk
2015-08-29 02:38:59 +02:00
var keyPath = cfgDir+'key'
log('Checking disk for key...')
fs.exists(keyPath,function(exists){
if(exists){
log('Key found')
fs.readFile(keyPath,function(err,content){
if(err)
log('Error while reading key:',err)
else {
authKey = telegramLink.retrieveAuthKey(content,'password') // yeah sorry just testing
app.authKey = authKey
log('Key loaded')
}
connect()
})
} else {
log('Key not found')
connect()
}
})