@ -599,6 +599,24 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -599,6 +599,24 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} ) ;
}
function getChatInviteLink ( id , force ) {
return getChatFull ( id ) . then ( function ( chatFull ) {
if ( ! force &&
chatFull . exported _invite &&
chatFull . exported _invite . _ == 'chatInviteExported' ) {
return chatFull . exported _invite . link ;
}
return MtpApiManager . invokeApi ( 'messages.exportChatInvite' , {
chat _id : id
} ) . then ( function ( exportedInvite ) {
if ( chatsFull [ id ] !== undefined ) {
chatsFull [ id ] . exported _invite = exportedInvite ;
}
return exportedInvite . link ;
} ) ;
} ) ;
}
function hasChat ( id ) {
return angular . isObject ( chats [ id ] ) ;
}
@ -628,10 +646,11 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -628,10 +646,11 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if ( chatFull . participants && chatFull . participants . _ == 'chatParticipants' ) {
MtpApiManager . getUserID ( ) . then ( function ( myID ) {
chatFull . isAdmin = ( myID == chatFull . participants . admin _id ) ;
angular . forEach ( chatFull . participants . participants , function ( participant ) {
participant . user = AppUsersManager . getUser ( participant . user _id ) ;
participant . canLeave = myID == participant . user _id ;
participant . canKick = ! participant . canLeave && ( myID == chatFull . participants . admin _id || myID == participant . inviter _id ) ;
participant . canKick = ! participant . canLeave && ( chatFull . isAdmin || myID == participant . inviter _id ) ;
} ) ;
} ) ;
}
@ -717,6 +736,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -717,6 +736,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
getChatFull : getChatFull ,
getChatPhoto : getChatPhoto ,
getChatString : getChatString ,
getChatInviteLink : getChatInviteLink ,
hasChat : hasChat ,
wrapForFull : wrapForFull ,
openChat : openChat
@ -792,7 +812,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -792,7 +812,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
} )
. service ( 'AppMessagesManager' , function ( $q , $rootScope , $location , $filter , $timeout , ApiUpdatesManager , AppUsersManager , AppChatsManager , AppPeersManager , AppPhotosManager , AppVideoManager , AppDocsManager , AppAudioManager , AppWebPagesManager , MtpApiManager , MtpApiFileManager , RichTextProcessor , NotificationsManager , PeersSelectService , Storage , FileManager , TelegramMeWebService , StatusManager , _ ) {
. service ( 'AppMessagesManager' , function ( $q , $rootScope , $location , $filter , $timeout , $sce , ApiUpdatesManager , AppUsersManager , AppChatsManager , AppPeersManager , AppPhotosManager , AppVideoManager , AppDocsManager , AppAudioManager , AppWebPagesManager , MtpApiManager , MtpApiFileManager , RichTextProcessor , NotificationsManager , PeersSelectService , Storage , FileManager , TelegramMeWebService , Error Service , StatusManager , _ ) {
var messagesStorage = { } ;
var messagesForHistory = { } ;
@ -1358,6 +1378,22 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -1358,6 +1378,22 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return historyStorage . readPromise ;
}
function readMessages ( messageIDs ) {
MtpApiManager . invokeApi ( 'messages.readMessageContents' , {
id : messageIDs
} ) . then ( function ( affectedMessages ) {
ApiUpdatesManager . processUpdateMessage ( {
_ : 'updateShort' ,
update : {
_ : 'updateReadMessagesContents' ,
messages : messageIDs ,
pts : affectedMessages . pts ,
pts _count : affectedMessages . pts _count
}
} ) ;
} ) ;
}
function flushHistory ( inputPeer ) {
// console.log('start flush');
var peerID = AppPeersManager . getPeerID ( inputPeer ) ,
@ -1382,6 +1418,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -1382,6 +1418,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
angular . forEach ( apiMessages , function ( apiMessage ) {
apiMessage . unread = apiMessage . flags & 1 ? true : false ;
apiMessage . out = apiMessage . flags & 2 ? true : false ;
apiMessage . media _unread = apiMessage . flags & 32 ? true : false ;
messagesStorage [ apiMessage . id ] = apiMessage ;
apiMessage . date -= serverTimeOffset ;
@ -1885,6 +1922,46 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -1885,6 +1922,46 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return false ;
}
function openChatInviteLink ( hash ) {
return MtpApiManager . invokeApi ( 'messages.checkChatInvite' , {
hash : hash
} ) . then ( function ( chatInvite ) {
var chatTitle ;
if ( chatInvite . _ == 'chatInviteAlready' ) {
AppChatsManager . saveApiChat ( chatInvite . chat ) ;
if ( ! chatInvite . chat . left ) {
return $rootScope . $broadcast ( 'history_focus' , {
peerString : AppChatsManager . getChatString ( chatInvite . chat . id )
} ) ;
}
chatTitle = chatInvite . chat . title ;
} else {
chatTitle = chatInvite . title ;
}
ErrorService . confirm ( {
type : 'JOIN_GROUP_BY_LINK' ,
title : chatTitle
} ) . then ( function ( ) {
return MtpApiManager . invokeApi ( 'messages.importChatInvite' , {
hash : hash
} ) . then ( function ( updates ) {
ApiUpdatesManager . processUpdateMessage ( updates ) ;
if ( updates . updates && updates . updates . length ) {
for ( var i = 0 , len = updates . updates . length , update ; i < len ; i ++ ) {
update = updates . updates [ i ] ;
if ( update . _ == 'updateNewMessage' ) {
$rootScope . $broadcast ( 'history_focus' , { peerString : AppChatsManager . getChatString ( update . message . to _id . chat _id )
} ) ;
break ;
}
}
}
} ) ;
} ) ;
} ) ;
}
function getMessagePeer ( message ) {
var toID = message . to _id && AppPeersManager . getPeerID ( message . to _id ) || 0 ;
@ -1949,9 +2026,14 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -1949,9 +2026,14 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
if ( message . media ) {
if ( message . media . caption &&
message . media . caption . length ) {
message . media . rCaption = RichTextProcessor . wrapRichText ( message . media . caption ) ;
}
switch ( message . media . _ ) {
case 'messageMediaPhoto' :
message . media . photo = AppPhotosManager . wrapForHistory ( message . media . photo . id )
message . media . photo = AppPhotosManager . wrapForHistory ( message . media . photo . id ) ;
break ;
case 'messageMediaVideo' :
@ -1966,6 +2048,22 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -1966,6 +2048,22 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
message . media . audio = AppAudioManager . wrapForHistory ( message . media . audio . id ) ;
break ;
case 'messageMediaGeo' :
var mapUrl = 'https://maps.google.com/?q=' + message . media . geo [ 'lat' ] + ',' + message . media . geo [ 'long' ] ;
message . media . mapUrl = $sce . trustAsResourceUrl ( mapUrl ) ;
break ;
case 'messageMediaVenue' :
var mapUrl ;
if ( message . media . provider == 'foursquare' &&
message . media . venue _id ) {
mapUrl = 'https://foursquare.com/v/' + encodeURIComponent ( message . media . venue _id ) ;
} else {
mapUrl = 'https://maps.google.com/?q=' + message . media . geo [ 'lat' ] + ',' + message . media . geo [ 'long' ] ;
}
message . media . mapUrl = $sce . trustAsResourceUrl ( mapUrl ) ;
break ;
case 'messageMediaContact' :
message . media . rFullName = RichTextProcessor . wrapRichText (
message . media . first _name + ' ' + ( message . media . last _name || '' ) ,
@ -1975,7 +2073,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -1975,7 +2073,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
case 'messageMediaWebPage' :
if ( ! message . media . webpage ||
message . media . webpage . _ == 'webPageEmpty' ) {
message . media . webpage . _ == 'webPageEmpty' ||
Config . Mobile ) {
delete message . media ;
break ;
}
@ -2187,7 +2286,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -2187,7 +2286,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
break ;
case 'messageMediaAudio' : notificationMessage = _ ( 'conversation_media_audio_raw' ) ; break ;
case 'messageMediaGeo' : notificationMessage = _ ( 'conversation_media_location_raw' ) ; break ;
case 'messageMediaGeo' :
case 'messageMediaVenue' : notificationMessage = _ ( 'conversation_media_location_raw' ) ; break ;
case 'messageMediaContact' : notificationMessage = _ ( 'conversation_media_contact_raw' ) ; break ;
default : notificationMessage = _ ( 'conversation_media_attachment_raw' ) ; break ;
}
@ -2464,6 +2564,21 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -2464,6 +2564,21 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
break ;
case 'updateReadMessagesContents' :
var messages = update . messages ;
var len = messages . length ;
var i , messageID , message , historyMessage ;
for ( i = 0 ; i < len ; i ++ ) {
messageID = messages [ i ] ;
if ( message = messagesStorage [ messageID ] ) {
delete message . media _unread ;
}
if ( historyMessage = messagesForHistory [ messageID ] ) {
delete historyMessage . media _unread ;
}
}
break ;
case 'updateDeleteMessages' :
var dialogsUpdated = { } ,
historiesUpdated = { } ,
@ -2558,6 +2673,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -2558,6 +2673,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
getSearch : getSearch ,
getMessage : getMessage ,
readHistory : readHistory ,
readMessages : readMessages ,
flushHistory : flushHistory ,
deleteMessages : deleteMessages ,
saveMessages : saveMessages ,
@ -2565,6 +2681,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -2565,6 +2681,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
sendFile : sendFile ,
sendOther : sendOther ,
forwardMessages : forwardMessages ,
openChatInviteLink : openChatInviteLink ,
getMessagePeer : getMessagePeer ,
wrapForDialog : wrapForDialog ,
wrapForHistory : wrapForHistory ,
@ -3978,7 +4095,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -3978,7 +4095,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
// resource path
"(?:/(?:\\S{0,255}[^\\s.;,(\\[\\]{}<>\"'])?)?" ;
var regExp = new RegExp ( '(^|\\s)((?:https?://)?telegram\\.me/| @)([a-zA-Z\\d_]{5,32})|(' + urlRegex + ')|(\\n)|(' + emojiRegex + ')|(^|\\s)(#[' + regexAlphaNumericChars + ']{2,64})' , 'i' ) ;
var regExp = new RegExp ( '(^|\\s)(@)([a-zA-Z\\d_]{5,32})|(' + urlRegex + ')|(\\n)|(' + emojiRegex + ')|(^|\\s)(#[' + regexAlphaNumericChars + ']{2,64})' , 'i' ) ;
var emailRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ ;
var youtubeRegex = /^(?:https?:\/\/)?(?:www\.)?youtu(?:|\.be|be\.com|\.b)(?:\/v\/|\/watch\\?v=|e\/|(?:\/\??#)?\/watch(?:.+)v=)(.{11})(?:\&[^\s]*)?/ ;
@ -4049,14 +4166,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -4049,14 +4166,10 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
if ( match [ 3 ] ) { // telegram.me links
var contextUrl = ! options . noLinks && siteMentions [ contextSite ] ;
if ( match [ 2 ] != '@' && contextExternal ) {
contextUrl = false ;
}
if ( contextUrl ) {
var attr = '' ;
if ( options . highlightUsername &&
options . highlightUsername . toLowerCase ( ) == match [ 3 ] . toLowerCase ( ) &&
match [ 2 ] == '@' ) {
options . highlightUsername . toLowerCase ( ) == match [ 3 ] . toLowerCase ( ) ) {
attr = 'class="im_message_mymention"' ;
}
html . push (
@ -4108,6 +4221,19 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -4108,6 +4221,19 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
url = ( match [ 5 ] ? '' : protocol ) + match [ 4 ] ;
}
var tgMeMatch ;
if ( tld == 'me' &&
( tgMeMatch = url . match ( /^https?:\/\/telegram\.me\/(.+)/ ) ) ) {
var path = tgMeMatch [ 1 ] . split ( '/' ) ;
switch ( path [ 0 ] ) {
case 'joinchat' :
url = 'tg://join?invite=' + path [ 1 ] ;
break ;
default :
url = 'tg://resolve?domain=' + path [ 0 ] ;
}
}
} else { // IP address
url = ( match [ 5 ] ? '' : 'http://' ) + match [ 4 ] ;
}
@ -5152,20 +5278,37 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -5152,20 +5278,37 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} )
. service ( 'LocationParamsService' , function ( $rootScope , $routeParams , AppUsersManager ) {
. service ( 'LocationParamsService' , function ( $rootScope , $routeParams , AppUsersManager , AppMessagesManager ) {
function checkTgAddr ( ) {
if ( ! $routeParams . tgaddr ) {
return ;
var tgAddrRegEx = /^(web\+)?tg:(\/\/)?(.+)/ ;
function checkLocationTgAddr ( ) {
if ( $routeParams . tgaddr ) {
var matches = $routeParams . tgaddr . match ( tgAddrRegEx ) ;
if ( matches ) {
handleTgProtoAddr ( matches [ 3 ] ) ;
}
}
}
var matches = $routeParams . tgaddr . match ( /^(web\+)?tg:(\/\/)?resolve\?domain=(.+)$/ ) ;
if ( matches && matches [ 3 ] ) {
AppUsersManager . resolveUsername ( matches [ 3 ] ) . then ( function ( userID ) {
function handleTgProtoAddr ( url ) {
var matches ;
if ( matches = url . match ( /^resolve\?domain=(.+)$/ ) ) {
AppUsersManager . resolveUsername ( matches [ 1 ] ) . then ( function ( userID ) {
$rootScope . $broadcast ( 'history_focus' , {
peerString : AppUsersManager . getUserString ( userID )
} ) ;
} ) ;
return true ;
}
if ( matches = url . match ( /^join\?invite=(.+)$/ ) ) {
AppMessagesManager . openChatInviteLink ( matches [ 1 ] ) ;
return true ;
}
return false ;
}
var started = ! ( 'registerProtocolHandler' in navigator ) ;
@ -5181,8 +5324,25 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
@@ -5181,8 +5324,25 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
navigator . registerProtocolHandler ( 'web+tg' , '#im?tgaddr=%s' , 'Telegram Web' ) ;
} catch ( e ) { }
$rootScope . $on ( '$routeUpdate' , checkTgAddr ) ;
checkTgAddr ( ) ;
$ ( document ) . on ( 'click' , function ( event ) {
var target = event . target ;
if ( target &&
target . tagName == 'A' &&
! target . onclick &&
! target . onmousedown ) {
var href = $ ( target ) . attr ( 'href' ) || target . href || '' ;
var match = href . match ( tgAddrRegEx ) ;
if ( match ) {
if ( handleTgProtoAddr ( match [ 3 ] ) ) {
return cancelEvent ( event ) ;
}
}
}
} ) ;
$rootScope . $on ( '$routeUpdate' , checkLocationTgAddr ) ;
checkLocationTgAddr ( ) ;
} ;
return {