mirror of
https://github.com/fazo96/telecommander.git
synced 2025-01-09 11:29:51 +01:00
improved interface, implemented marking messages as read
This commit is contained in:
parent
d6ff917688
commit
66d9667c88
@ -14,14 +14,13 @@ As of __now__, __Telecommander lets you__:
|
||||
- Chat in groups and in private (it also marks messages as read when you read them)
|
||||
- Know when you have unread messages
|
||||
- Do everything __completely in the terminal, even via ssh__ using only the keyboard
|
||||
- Do everything (except writing, duh) using only the mouse!
|
||||
- Do everything (except writing messages, duh) using only the mouse, in the terminal!
|
||||
- Navigate your contact and chat list
|
||||
- Scroll back to view old messages
|
||||
|
||||
Waht's missing for version _0.1.0_ (__Almost done!__):
|
||||
|
||||
- View who's online and when was the last time they logged in
|
||||
- Testing and tying up loose ends in user interface and code quality
|
||||
|
||||
What's missing (for future versions up to 1.0)
|
||||
|
||||
@ -35,7 +34,6 @@ What's missing (for future versions up to 1.0)
|
||||
- Sign out (without having to manually delete files)
|
||||
- Delete account
|
||||
- Reply to and Forward message support
|
||||
- Cool interface (it's already ok, just not as cool as I want it to be)
|
||||
- Search, Tab completion, chatbox history
|
||||
- Send multiline messages
|
||||
- Themes and configurability! Basic scripting!
|
||||
@ -86,7 +84,7 @@ $ telecommander
|
||||
# either swap it with python 2 or if you're on arch linux
|
||||
# and/or your python 2 executable is "python2" just run this:
|
||||
|
||||
$ PYTHON=python2 npm install [-g .]
|
||||
$ PYTHON=python2 npm install [-g .]
|
||||
```
|
||||
|
||||
__PLEASE READ:__ if you fork the project and want to create a custom version of
|
||||
|
161
lib/ui.js
161
lib/ui.js
@ -8,31 +8,37 @@ module.exports = function(data){
|
||||
// Get msgBox for given group/user NAME, create if not exists
|
||||
data.getMsgBox = function(chat){
|
||||
if(chat === undefined){
|
||||
log('ERROR: asked for box for "undefined"!!')
|
||||
data.log('ERROR: asked for box for "undefined"!!')
|
||||
return data.msgBox[statusWindow]
|
||||
}
|
||||
if(!data.msgBox[chat]){
|
||||
//log('Generating window: "'+chat+'"')
|
||||
data.msgBox[chat] = data.mkBox(chat)
|
||||
data.screen.append(data.msgBox[chat])
|
||||
data.screen.insertBefore(data.msgBox[chat],data.loader)
|
||||
//data.getMessages(chat,data.msgBox[chat])
|
||||
} // else log('Getting window','"'+chat+'"')
|
||||
return data.msgBox[chat]
|
||||
}
|
||||
|
||||
data.switchToBox = function(boxname){
|
||||
// Hide current window
|
||||
if(data.selectedWindow && data.msgBox[data.selectedWindow])
|
||||
data.msgBox[data.selectedWindow].hide()
|
||||
data.selectedWindow = boxname;
|
||||
if(data.selectedWindow != data.statusWindow){
|
||||
data.cmdline.setLabel('to '+data.selectedWindow)
|
||||
data.markAsRead(data.selectedWindow)
|
||||
if(boxname === undefined){
|
||||
// Leave the clear
|
||||
} else {
|
||||
data.cmdline.setLabel('Command for Telecommander')
|
||||
// Switch window
|
||||
data.selectedWindow = boxname;
|
||||
if(data.selectedWindow != data.statusWindow){
|
||||
data.cmdline.setLabel('to '+data.selectedWindow)
|
||||
data.markAsRead(data.selectedWindow)
|
||||
} else {
|
||||
data.cmdline.setLabel('Command for Telecommander')
|
||||
}
|
||||
var newb = data.getMsgBox(data.selectedWindow)
|
||||
newb.show()
|
||||
newb.emit('scroll')
|
||||
}
|
||||
var newb = data.getMsgBox(data.selectedWindow)
|
||||
newb.show()
|
||||
newb.emit('scroll')
|
||||
data.screen.render()
|
||||
}
|
||||
|
||||
@ -88,6 +94,20 @@ module.exports = function(data){
|
||||
})
|
||||
data.screen.append(data.chats)
|
||||
|
||||
// Command line prompt
|
||||
data.cmdline = blessed.textbox({
|
||||
keys: false,
|
||||
mouse: true,
|
||||
label: 'Command for Telecommander',
|
||||
bottom: 0,
|
||||
left: 'center',
|
||||
width: '100%',
|
||||
height: 3,
|
||||
border: { type: 'line' },
|
||||
style: data.getDefaultStyle()
|
||||
})
|
||||
data.screen.append(data.cmdline);
|
||||
|
||||
// Function to create a log box
|
||||
data.mkBox = function(txt){
|
||||
var b = ChatBox({
|
||||
@ -125,40 +145,44 @@ module.exports = function(data){
|
||||
return b
|
||||
}
|
||||
|
||||
// Command line prompt
|
||||
data.cmdline = blessed.textbox({
|
||||
keys: false,
|
||||
mouse: true,
|
||||
label: 'Command for Telecommander',
|
||||
bottom: 0,
|
||||
left: 'center',
|
||||
width: '100%',
|
||||
height: 3,
|
||||
border: { type: 'line' },
|
||||
style: data.getDefaultStyle()
|
||||
})
|
||||
data.screen.append(data.cmdline);
|
||||
data.getDefaultPopupStyle = function(){
|
||||
return {
|
||||
width: '30%',
|
||||
key: true,
|
||||
height: 'shrink',
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
align: 'center',
|
||||
valign: 'center',
|
||||
border: { type: 'line' },
|
||||
style: data.getDefaultStyle()
|
||||
}
|
||||
}
|
||||
|
||||
// Widget used to show loading windows
|
||||
data.loader = blessed.loading({
|
||||
width: '30%',
|
||||
height: 5,
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
align: 'center',
|
||||
valign: 'center',
|
||||
border: { type: 'line' },
|
||||
style: data.getDefaultStyle()
|
||||
})
|
||||
data.loader = blessed.Loading(data.getDefaultPopupStyle())
|
||||
data.screen.append(data.loader)
|
||||
data.load = function(msg){
|
||||
data.loader.stop()
|
||||
data.loader.load(msg)
|
||||
}
|
||||
|
||||
// Widget used to ask for phone number and code
|
||||
data.promptBox = blessed.Prompt(data.getDefaultPopupStyle())
|
||||
data.screen.append(data.promptBox)
|
||||
|
||||
// Widget used to show pop up read only messages
|
||||
data.popup = blessed.Message(data.getDefaultPopupStyle())
|
||||
data.screen.append(data.popup)
|
||||
data.popup.hide()
|
||||
|
||||
// mgsBox holds the chat window instance for every chat
|
||||
data.msgBox = { }
|
||||
|
||||
// Add the status window and switch to it
|
||||
// Add the status window but don't show it
|
||||
data.msgBox[data.statusWindow] = data.mkBox(data.statusWindow)
|
||||
data.screen.append(data.msgBox[data.statusWindow])
|
||||
data.switchToBox(data.statusWindow)
|
||||
data.switchToBox()
|
||||
|
||||
data.screen.on('resize',function(){
|
||||
for(i in data.msgBox){
|
||||
@ -175,72 +199,7 @@ module.exports = function(data){
|
||||
data.switchToBox(data.statusWindow)
|
||||
})
|
||||
data.command = function(cmd){
|
||||
cmdl = cmd.split(' ')
|
||||
cmdname = cmdl[0]
|
||||
|
||||
if(cmdname === 'phone'){ // So the user can provide his phone numbah
|
||||
if(data.connected){
|
||||
return log("Silly user, you're already connected! We don't need that phone number")
|
||||
}
|
||||
data.user.phone = cmd.split(' ')[1]
|
||||
var mindate = moment()
|
||||
log('Checking your phone number with Telegram...')
|
||||
data.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))
|
||||
data.user.registered = result.phone_registered
|
||||
data.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(!data.user.registered){
|
||||
data.log("Your number is not registered. Telecommander will register your account with the Telegram service")
|
||||
data.log(gmd())
|
||||
data.log('Ready for phone code, use command: "code <code> <name> <lastname>" to register')
|
||||
data.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")
|
||||
} else {
|
||||
data.log("Your number is already assigned to a Telegram account. Telecommander will log you in.")
|
||||
data.log(gmd())
|
||||
data.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")
|
||||
}
|
||||
})
|
||||
|
||||
} else if(cmdname === 'code'){ // So the user can provide his phone code
|
||||
if(data.connected){
|
||||
return log("Silly user, you're already connected! We don't need that phone code")
|
||||
}
|
||||
code = cmdl[1]
|
||||
name = cmdl[2]
|
||||
lastname = cmdl[3]
|
||||
if(((!name || !lastname) && !data.user.registered) || !code)
|
||||
return log('insufficient arguments:',cmd)
|
||||
cb = function(result){
|
||||
data.user.id = ''+result.user.id
|
||||
data.user.phone = result.user.phone
|
||||
data.user.phoneCodeHash = result.phone_code_hash
|
||||
data.user.username = result.user.username
|
||||
data.user.first_name = result.user.first_name
|
||||
data.user.last_name = result.user.last_name
|
||||
// Done, write user data and key to disk
|
||||
log('Writing Log In token and user data to',cfgDir)
|
||||
fs.writeFile(cfgDir+'key',authKey,function(err){
|
||||
if(err) log('FATAL: Could not write key to disk:',err)
|
||||
})
|
||||
fs.writeFile(cfgDir+'user_data.json',JSON.stringify(user),function(err){
|
||||
if(err) log("FATAL: couldn't write user_data.json:",err)
|
||||
})
|
||||
whenReady()
|
||||
}
|
||||
// Log in finally
|
||||
if(user.registered) client.auth.signIn(user.phone,user.phoneCodeHash,code,cb)
|
||||
else client.auth.signUp(user.phone,user.phoneCodeHash,code,name,lastname,cb)
|
||||
} else {
|
||||
data.log('Command not found.')
|
||||
}
|
||||
data.log('Commands are not implemented... sorry!')
|
||||
}
|
||||
|
||||
// What happens when a different window is selected
|
||||
|
@ -127,18 +127,15 @@ module.exports = function(data){
|
||||
toread = data.contacts[id].toread
|
||||
} else data.log('Failed to find name for',type,id)
|
||||
if(obj === undefined){
|
||||
throw new Error("Can't find name for",type,id)
|
||||
return
|
||||
}
|
||||
if(type === 'user'){
|
||||
name = 'Unknown '+type+' '+id
|
||||
} else if(type === 'user'){
|
||||
// User
|
||||
if(obj.first_name === undefined && obj.last_name === undefined && obj.username === undefined){
|
||||
data.log('Zombie User: '+obj)
|
||||
return 'undefined'
|
||||
}
|
||||
name = obj.first_name + (obj.last_name?' '+obj.last_name:'') + (obj.username?' (@'+obj.username+')':'')
|
||||
} else {
|
||||
// Group
|
||||
} else { // Group
|
||||
name = obj.title
|
||||
}
|
||||
if(forChatList && toread > 0) return '* '+name
|
||||
|
175
telecommander.js
175
telecommander.js
@ -57,70 +57,13 @@ data.command = function(cmd){
|
||||
if(data.connected){
|
||||
return log("Silly user, you're already connected! We don't need that phone number")
|
||||
}
|
||||
data.user.phone = cmd.split(' ')[1]
|
||||
var mindate = moment()
|
||||
data.log('Checking your phone number with Telegram...')
|
||||
data.client.auth.sendCode(data.user.phone,5,'en',function(result){
|
||||
if(result.err_code){
|
||||
return data.log('Errors:',result.error_code,result.error_message)
|
||||
}
|
||||
//data.log('Res:',JSON.stringify(result))
|
||||
data.user.registered = result.phone_registered
|
||||
data.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(!data.user.registered){
|
||||
data.log("Your number is not registered. Telecommander will register your account with the Telegram service")
|
||||
data.log(gmd())
|
||||
data.log('Ready for phone code, use command: "code <code> <name> <lastname>" to register')
|
||||
data.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")
|
||||
} else {
|
||||
data.log("Your number is already assigned to a Telegram account. Telecommander will log you in.")
|
||||
data.log(gmd())
|
||||
data.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")
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
} else if(cmdname === 'code'){ // So the user can provide his phone code
|
||||
if(data.connected){
|
||||
return data.log("Silly user, you're already connected! We don't need that phone code")
|
||||
}
|
||||
code = cmdl[1]
|
||||
name = cmdl[2]
|
||||
lastname = cmdl[3]
|
||||
if(((!name || !lastname) && !data.user.registered) || !code)
|
||||
return log('insufficient arguments:',cmd)
|
||||
var cb = function(result){
|
||||
data.user.id = ''+result.user.id
|
||||
data.user.phone = result.user.phone
|
||||
data.user.phoneCodeHash = result.phone_code_hash
|
||||
data.user.username = result.user.username
|
||||
data.user.first_name = result.user.first_name
|
||||
data.user.last_name = result.user.last_name
|
||||
// Done, write user data and key to disk
|
||||
try {
|
||||
fs.mkdirSync(data.cfgDir,'0770')
|
||||
} catch (e) {
|
||||
if(e.code != 'EEXIST'){
|
||||
console.error("FATAL: couldn't create configuration directory",data.cfgDir,e)
|
||||
process.exit(-1)
|
||||
}
|
||||
}
|
||||
data.log('Writing Log In token and user data to',data.cfgDir)
|
||||
fs.writeFile(data.cfgDir+'key',data.app.authKey,function(err){
|
||||
if(err) data.log('FATAL: Could not write key to disk:',err)
|
||||
})
|
||||
fs.writeFile(data.cfgDir+'user_data.json',JSON.stringify(data.user),function(err){
|
||||
if(err) data.log("FATAL: couldn't write user_data.json:",err)
|
||||
})
|
||||
data.whenReady()
|
||||
}
|
||||
// Log in finally
|
||||
if(data.user.registered) data.client.auth.signIn(data.user.phone,data.user.phoneCodeHash,code,cb)
|
||||
else data.client.auth.signUp(data.user.phone,data.user.phoneCodeHash,code,name,lastname,cb)
|
||||
|
||||
} else {
|
||||
data.log('Command not found.')
|
||||
}
|
||||
@ -142,15 +85,86 @@ data.sendMsg = function(name,str){
|
||||
})
|
||||
}
|
||||
|
||||
data.onPhoneCode = function(something,s){
|
||||
if(s === null){ // User cancelled
|
||||
process.exit(0)
|
||||
}
|
||||
var cmdl = s.split(' ')
|
||||
code = cmdl[0]
|
||||
name = cmdl[1]
|
||||
lastname = cmdl[2]
|
||||
if(((!name || !lastname) && !data.user.registered) || !code)
|
||||
return log('insufficient arguments:',cmd) // TODO: handle this better!
|
||||
var cb = function(result){
|
||||
data.user.id = ''+result.user.id
|
||||
data.user.phone = result.user.phone
|
||||
data.user.phoneCodeHash = result.phone_code_hash
|
||||
data.user.username = result.user.username
|
||||
data.user.first_name = result.user.first_name
|
||||
data.user.last_name = result.user.last_name
|
||||
// Done, write user data and key to disk
|
||||
try {
|
||||
fs.mkdirSync(data.cfgDir,'0770')
|
||||
} catch (e) {
|
||||
if(e.code != 'EEXIST'){
|
||||
console.error("FATAL: couldn't create configuration directory",data.cfgDir,e)
|
||||
process.exit(-1)
|
||||
}
|
||||
}
|
||||
data.log('Writing Log In token and user data to',data.cfgDir)
|
||||
fs.writeFile(data.cfgDir+'key',data.app.authKey,function(err){
|
||||
if(err) data.log('FATAL: Could not write key to disk:',err)
|
||||
})
|
||||
fs.writeFile(data.cfgDir+'user_data.json',JSON.stringify(data.user),function(err){
|
||||
if(err) data.log("FATAL: couldn't write user_data.json:",err)
|
||||
})
|
||||
data.whenReady()
|
||||
}
|
||||
// Log in finally
|
||||
if(data.user.registered) data.client.auth.signIn(data.user.phone,data.user.phoneCodeHash,code,cb)
|
||||
else data.client.auth.signUp(data.user.phone,data.user.phoneCodeHash,code,name,lastname,cb)
|
||||
}
|
||||
|
||||
data.onPhoneNumber = function(something,s){
|
||||
if(s === null){ // User cancelled
|
||||
process.exit(0)
|
||||
}
|
||||
data.user.phone = s.trim()
|
||||
var mindate = moment()
|
||||
data.log('Checking your phone number with Telegram...')
|
||||
data.client.auth.sendCode(data.user.phone,5,'en',function(result){
|
||||
if(result.err_code){
|
||||
return data.log('Errors:',result.error_code,result.error_message)
|
||||
}
|
||||
//data.log('Res:',JSON.stringify(result))
|
||||
data.user.registered = result.phone_registered
|
||||
data.user.phoneCodeHash = result.phone_code_hash
|
||||
var msg
|
||||
if(!data.user.registered){
|
||||
msg = "Your number ("+data.user.phone+") is not registered.\nTelecommander will register your account with the Telegram service."
|
||||
} else {
|
||||
msg = "Your number ("+data.user.phone+") is already assigned to a Telegram account.\nTelecommander will log you in."
|
||||
}
|
||||
msg += "\nPress ESC to exit now, or enter to continue"
|
||||
data.popup.display(msg,0,function(){
|
||||
data.popup.hide()
|
||||
data.promptBox.input('Your telegram code:','',data.onPhoneCode)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Connects to telegram
|
||||
data.connect = function(){
|
||||
data.load('Connecting...')
|
||||
data.client = data.telegramLink.createClient(data.app, data.dataCenter, function(){
|
||||
if(!data.app.authKey){
|
||||
data.log('Downloading Authorization Key...')
|
||||
data.client.createAuthKey(function(auth){
|
||||
data.app.authKey = auth.key.encrypt('password') // Will add security later, I promise
|
||||
// Writes the new encrypted key to disk
|
||||
data.log('Ready for phone number, use command: phone <number>')
|
||||
data.loader.stop()
|
||||
//data.log('Ready for phone number, use command: phone <number>')
|
||||
data.promptBox.input('Phone number (international format):','+',data.onPhoneNumber)
|
||||
})
|
||||
} else {
|
||||
data.whenReady()
|
||||
@ -164,7 +178,7 @@ data.connect = function(){
|
||||
|
||||
// Executed when connected and logged in
|
||||
data.whenReady = function(){
|
||||
data.log('Connected')
|
||||
data.load('Connected')
|
||||
data.connected = true
|
||||
data.downloadData()
|
||||
data.chats.focus()
|
||||
@ -172,8 +186,7 @@ data.whenReady = function(){
|
||||
|
||||
// Downloads stuff
|
||||
data.downloadData = function(){
|
||||
data.loader.load('Downloading data')
|
||||
data.screen.render()
|
||||
data.load('Downloading data')
|
||||
data.client.contacts.getContacts('',function(cont){
|
||||
//data.chats.clearItems()
|
||||
//data.chats.add(data.statusWindow)
|
||||
@ -184,6 +197,7 @@ data.downloadData = function(){
|
||||
data.client.messages.getDialogs(0,0,10,function(dialogs){
|
||||
if(dialogs && dialogs.chats && dialogs.chats.list)
|
||||
dialogs.chats.list.forEach(data.addGroup)
|
||||
data.loader.stop()
|
||||
})
|
||||
|
||||
data.client.updates.getState(function(astate){
|
||||
@ -236,6 +250,7 @@ data.getMessages = function(name,box){
|
||||
if(!peer) return log('Could not find peer:',name)
|
||||
data.downloadingMessages = true
|
||||
var oldnlines = box.getLines().length
|
||||
if(data.selectedWindow === name) data.load('Downloading history...')
|
||||
data.client.messages.getHistory(peer,0,obj.oldest_message||0,10,function(res){
|
||||
//log(res.toPrintable())
|
||||
//log('Got history for: '+getName(peer.user_id||peer.chat_id,peer.chat_id?'group':'user'))
|
||||
@ -251,6 +266,7 @@ data.getMessages = function(name,box){
|
||||
})
|
||||
if(oldnlines == 0) box.setScrollPerc(100)
|
||||
//box.add(obj.oldest_message)
|
||||
data.loader.stop()
|
||||
data.downloadingMessages = false
|
||||
})
|
||||
}
|
||||
@ -308,20 +324,25 @@ data.appendMsg = function(msg,toBoxId,bare,prepend){
|
||||
box.add(msg)
|
||||
else {
|
||||
var id = msg.from_id
|
||||
var date = moment.unix(msg.date).format('DD-MM-YYYY H:mm')
|
||||
name = data.getName(id,'user')
|
||||
var txt = (name || id)+' {|} {grey-fg}'+date+'{/grey-fg}\n'
|
||||
if(msg.media){
|
||||
if(msg.media.photo)
|
||||
txt += '{grey-fg}>>>{/grey-fg} (Photo)'
|
||||
else if(msg.media.audio)
|
||||
txt += "{grey-fg}>>>{/grey-fg} (Audio Message) "+msg.media.audio.duration+" seconds"
|
||||
else if(!msg.message)
|
||||
txt += "{grey-fg}>>>{/grey-fg} (Unsupported Message)"
|
||||
if(!id){ // Weird zombie message!
|
||||
data.log('Zombie Message:',msg.toPrintable())
|
||||
return box
|
||||
} else { // Regular message
|
||||
var date = moment.unix(msg.date).format('DD-MM-YYYY H:mm')
|
||||
name = data.getName(id,'user')
|
||||
var txt = (name || id)+' {|} {grey-fg}'+date+'{/grey-fg}\n'
|
||||
if(msg.media){
|
||||
if(msg.media.photo)
|
||||
txt += '{grey-fg}>>>{/grey-fg} (Photo)'
|
||||
else if(msg.media.audio)
|
||||
txt += "{grey-fg}>>>{/grey-fg} (Audio Message) "+msg.media.audio.duration+" seconds"
|
||||
else if(!msg.message)
|
||||
txt += "{grey-fg}>>>{/grey-fg} (Unsupported Message)"
|
||||
}
|
||||
if(msg.message) txt += '{grey-fg}>{/grey-fg} '+msg.message
|
||||
if(prepend) box.prepend(txt)
|
||||
else box.add(txt)
|
||||
}
|
||||
if(msg.message) txt += '{grey-fg}>{/grey-fg} '+msg.message
|
||||
if(prepend) box.prepend(txt)
|
||||
else box.add(txt)
|
||||
}
|
||||
// Mark messages as read if needed
|
||||
if(param === data.selectedWindow) data.markAsRead(param)
|
||||
@ -330,8 +351,8 @@ data.appendMsg = function(msg,toBoxId,bare,prepend){
|
||||
|
||||
// - Entry Point -
|
||||
// Load authKey and userdata from disk, then act depending on outcome
|
||||
data.load('Starting up...')
|
||||
data.screen.render()
|
||||
data.log('Loading files...')
|
||||
fs.exists(data.keyFile,function(exists){
|
||||
if(exists){
|
||||
//log('Authorization Key found')
|
||||
|
Loading…
Reference in New Issue
Block a user