2013-08-19 22:30:57 +09:00
|
|
|
|
|
|
|
|
|
/* · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
|
|
|
|
· ·
|
|
|
|
|
· ·
|
|
|
|
|
· Q V I T T E R ·
|
|
|
|
|
· ·
|
|
|
|
|
· http://github.com/hannesmannerheim/qvitter ·
|
|
|
|
|
· ·
|
|
|
|
|
· ·
|
|
|
|
|
· <o) ·
|
|
|
|
|
· /_//// ·
|
|
|
|
|
· (____/ ·
|
|
|
|
|
· (o< ·
|
|
|
|
|
· o> \\\\_\ ·
|
|
|
|
|
· \\) \____) ·
|
|
|
|
|
· ·
|
|
|
|
|
· ·
|
|
|
|
|
· ·
|
|
|
|
|
· Qvitter is free software: you can redistribute it and / or modify it ·
|
|
|
|
|
· under the terms of the GNU Affero General Public License as published by ·
|
|
|
|
|
· the Free Software Foundation, either version three of the License or (at ·
|
|
|
|
|
· your option) any later version. ·
|
|
|
|
|
· ·
|
|
|
|
|
· Qvitter is distributed in hope that it will be useful but WITHOUT ANY ·
|
|
|
|
|
· WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS ·
|
|
|
|
|
· FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for ·
|
|
|
|
|
· more details. ·
|
|
|
|
|
· ·
|
|
|
|
|
· You should have received a copy of the GNU Affero General Public License ·
|
|
|
|
|
· along with Qvitter. If not, see <http://www.gnu.org/licenses/>. ·
|
|
|
|
|
· ·
|
|
|
|
|
· Contact h@nnesmannerhe.im if you have any questions. ·
|
|
|
|
|
· ·
|
|
|
|
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · */
|
|
|
|
|
|
2014-05-16 11:07:30 +09:00
|
|
|
|
/* ·
|
|
|
|
|
·
|
|
|
|
|
· Current time in milliseconds, to send with each request to make sure
|
|
|
|
|
· we're not getting 304 responses.
|
|
|
|
|
·
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · · · · · */
|
|
|
|
|
|
|
|
|
|
function timeNow() {
|
|
|
|
|
return new Date().getTime();
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-19 22:30:57 +09:00
|
|
|
|
|
2015-01-26 03:05:09 +09:00
|
|
|
|
|
|
|
|
|
/* ·
|
|
|
|
|
·
|
|
|
|
|
· Get a document and replace strings
|
|
|
|
|
·
|
|
|
|
|
· @param doc: the name of the document
|
|
|
|
|
· @param actionOnSuccess: callback function to run on success
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · · · · · */
|
|
|
|
|
|
|
|
|
|
function getDoc(doc, actionOnSuccess) {
|
|
|
|
|
var timeNow = new Date().getTime();
|
|
|
|
|
$.get(window.fullUrlToThisQvitterApp + 'doc/' + window.selectedLanguage + '/' + doc + '.html?t=' + timeNow, function(data){
|
|
|
|
|
if(data) {
|
|
|
|
|
actionOnSuccess(renderDoc(data));
|
|
|
|
|
}
|
|
|
|
|
}).fail(function() { // default to english if we can't find the doc in selected language
|
|
|
|
|
$.get(window.fullUrlToThisQvitterApp + 'doc/en/' + doc + '.html?t=' + timeNow, function(data){
|
|
|
|
|
if(data) {
|
|
|
|
|
actionOnSuccess(renderDoc(data));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
function renderDoc(docHtml) {
|
|
|
|
|
docHtml = docHtml.replace(/{instance-name}/g,window.siteTitle);
|
|
|
|
|
docHtml = docHtml.replace(/{instance-url}/g,window.siteRootDomain);
|
|
|
|
|
docHtml = docHtml.replace(/{instance-url-with-protocol}/g,window.siteInstanceURL);
|
|
|
|
|
docHtml = docHtml.replace(/{nickname}/g,window.loggedIn.screen_name);
|
|
|
|
|
docHtml = docHtml.replace(/{instance-email}/g,window.siteEmail);
|
|
|
|
|
docHtml = docHtml.replace(/{instance-license-title}/g,window.siteLicenseTitle);
|
|
|
|
|
docHtml = docHtml.replace(/{instance-license-url}/g,window.siteLicenseURL);
|
|
|
|
|
return docHtml;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-19 22:30:57 +09:00
|
|
|
|
/* ·
|
|
|
|
|
·
|
|
|
|
|
· Check login credentials with http basic auth
|
|
|
|
|
·
|
|
|
|
|
· @param username: users screen name
|
|
|
|
|
· @param password: users password
|
|
|
|
|
· @param actionOnSuccess: callback function on log in success
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · */
|
|
|
|
|
|
|
|
|
|
function checkLogin(username,password,actionOnSuccess) {
|
2014-05-17 05:30:10 +09:00
|
|
|
|
$.ajax({ url: window.apiRoot + 'qvitter/checklogin.json',
|
2014-05-16 19:36:30 +09:00
|
|
|
|
type: 'POST',
|
|
|
|
|
data: {
|
|
|
|
|
username: username,
|
|
|
|
|
password: password
|
|
|
|
|
},
|
2013-08-19 22:30:57 +09:00
|
|
|
|
dataType: 'json',
|
2013-08-26 03:11:53 +09:00
|
|
|
|
error: function() {
|
|
|
|
|
logoutWithoutReload(true);
|
|
|
|
|
},
|
2014-05-16 11:07:30 +09:00
|
|
|
|
success: function(data) {
|
2014-05-16 19:36:30 +09:00
|
|
|
|
if(typeof data.error == 'undefined' && data !== false) {
|
2013-08-19 22:30:57 +09:00
|
|
|
|
actionOnSuccess(data);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
logoutWithoutReload(true);
|
2013-08-19 22:30:57 +09:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ·
|
|
|
|
|
·
|
|
|
|
|
· Generic API GET request
|
|
|
|
|
·
|
|
|
|
|
· @param stream: any api get-request e.g. 'statuses/favs/111111.json'
|
|
|
|
|
· @param actionOnSuccess: callback function
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · · · · · */
|
|
|
|
|
|
|
|
|
|
function getFromAPI(stream, actionOnSuccess) {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
$.ajax({ url: window.apiRoot + stream + qOrAmp(stream) + 't=' + timeNow(),
|
|
|
|
|
type: "GET",
|
|
|
|
|
dataType: 'json',
|
2014-10-18 02:06:29 +09:00
|
|
|
|
statusCode: {
|
2014-11-27 21:20:00 +09:00
|
|
|
|
401:function() {
|
2014-10-18 02:06:29 +09:00
|
|
|
|
location.reload(); // we may have been logged out in another tab, reload page
|
|
|
|
|
},
|
|
|
|
|
404:function() {
|
2014-11-27 21:20:00 +09:00
|
|
|
|
// redirect to frontpage when trying to access non-existing users
|
|
|
|
|
if(stream.indexOf('statuses/user_timeline.json?screen_name=') > -1) {
|
|
|
|
|
window.location.replace(window.siteInstanceURL);
|
|
|
|
|
}
|
2014-10-18 02:06:29 +09:00
|
|
|
|
}
|
|
|
|
|
},
|
2015-01-27 01:13:34 +09:00
|
|
|
|
success: function(data, textStatus, request) {
|
2014-05-23 21:13:38 +09:00
|
|
|
|
|
2015-01-27 01:13:34 +09:00
|
|
|
|
displayOrHideUnreadNotifications(request.getResponseHeader('Qvitter-Notifications'));
|
|
|
|
|
|
2014-10-03 02:24:54 +09:00
|
|
|
|
data = convertEmptyObjectToEmptyArray(data);
|
2014-05-23 21:13:38 +09:00
|
|
|
|
|
2015-01-19 04:36:08 +09:00
|
|
|
|
data = iterateRecursiveReplaceHtmlSpecialChars(data);
|
|
|
|
|
|
2014-05-16 11:07:30 +09:00
|
|
|
|
actionOnSuccess(data);
|
|
|
|
|
},
|
|
|
|
|
error: function(data) {
|
|
|
|
|
actionOnSuccess(false);
|
|
|
|
|
console.log(data);
|
|
|
|
|
remove_spinner();
|
|
|
|
|
}
|
|
|
|
|
});
|
2013-08-19 22:30:57 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-01-19 04:36:08 +09:00
|
|
|
|
|
2013-08-26 03:11:53 +09:00
|
|
|
|
/* ·
|
|
|
|
|
·
|
|
|
|
|
· Post new link color
|
|
|
|
|
·
|
|
|
|
|
· @param newLinkColor: the new link color in hex without #
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · · · · · */
|
|
|
|
|
|
|
|
|
|
function postNewLinkColor(newLinkColor) {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
$.ajax({ url: window.apiRoot + 'qvitter/update_link_color.json?t=' + timeNow(),
|
2013-08-26 03:11:53 +09:00
|
|
|
|
type: "POST",
|
|
|
|
|
data: {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
linkcolor: newLinkColor
|
2013-08-26 03:11:53 +09:00
|
|
|
|
},
|
|
|
|
|
dataType:"json",
|
|
|
|
|
error: function(data){ console.log(data); },
|
2013-08-26 05:34:09 +09:00
|
|
|
|
success: function(data) {
|
|
|
|
|
window.userLinkColor = newLinkColor;
|
|
|
|
|
}
|
2013-08-26 03:11:53 +09:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-08-26 05:34:09 +09:00
|
|
|
|
|
|
|
|
|
/* ·
|
|
|
|
|
·
|
|
|
|
|
· Post new background color
|
|
|
|
|
·
|
|
|
|
|
· @param newBackgroundColor: the new background color in hex without #
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · · · · · */
|
|
|
|
|
|
|
|
|
|
function postNewBackgroundColor(newBackgroundColor) {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
$.ajax({ url: window.apiRoot + 'qvitter/update_background_color.json?t=' + timeNow(),
|
2013-08-26 05:34:09 +09:00
|
|
|
|
type: "POST",
|
|
|
|
|
data: {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
backgroundcolor: newBackgroundColor
|
2013-08-26 05:34:09 +09:00
|
|
|
|
},
|
|
|
|
|
dataType:"json",
|
|
|
|
|
error: function(data){ console.log(data); },
|
|
|
|
|
success: function(data) {
|
2014-11-24 21:47:45 +09:00
|
|
|
|
window.userBackgroundColor = newBackgroundColor;
|
|
|
|
|
$('body').css('background-image','url(""'); // unset background image
|
|
|
|
|
window.userBackgroundImage = '';
|
2013-08-26 05:34:09 +09:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-08-26 03:11:53 +09:00
|
|
|
|
|
2013-08-19 22:30:57 +09:00
|
|
|
|
/* ·
|
|
|
|
|
·
|
|
|
|
|
· Post follow or unfollow user request
|
|
|
|
|
·
|
|
|
|
|
· @param followOrUnfollow: either 'follow' or 'unfollow'
|
|
|
|
|
· @param user_id: the user id of the user we want to follow
|
|
|
|
|
· @param actionOnSuccess: callback function, false on error, data on success
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · · · · · */
|
|
|
|
|
|
|
|
|
|
function APIFollowOrUnfollowUser(followOrUnfollow,user_id,this_element,actionOnSuccess) {
|
|
|
|
|
|
|
|
|
|
if(followOrUnfollow == 'follow') {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
var postRequest = 'friendships/create.json?t=' + timeNow();
|
2013-08-19 22:30:57 +09:00
|
|
|
|
}
|
|
|
|
|
else if (followOrUnfollow == 'unfollow') {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
var postRequest = 'friendships/destroy.json?t=' + timeNow();
|
2013-08-19 22:30:57 +09:00
|
|
|
|
}
|
|
|
|
|
|
2014-05-16 11:07:30 +09:00
|
|
|
|
$.ajax({ url: window.apiRoot + postRequest,
|
2013-08-19 22:30:57 +09:00
|
|
|
|
type: "POST",
|
|
|
|
|
data: {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
user_id: user_id
|
2013-08-19 22:30:57 +09:00
|
|
|
|
},
|
|
|
|
|
dataType:"json",
|
|
|
|
|
error: function(data){ actionOnSuccess(false,this_element); console.log(data); },
|
|
|
|
|
success: function(data) { actionOnSuccess(data,this_element);}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ·
|
|
|
|
|
·
|
|
|
|
|
· Post join or leave group request
|
|
|
|
|
·
|
|
|
|
|
· @param joinOrLeave: either 'join' or 'leave'
|
|
|
|
|
· @param group_id: group's id
|
|
|
|
|
· @param actionOnSuccess: callback function, false on error, data on success
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · · · · · */
|
|
|
|
|
|
|
|
|
|
function APIJoinOrLeaveGroup(joinOrLeave,group_id,this_element,actionOnSuccess) {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
$.ajax({ url: window.apiRoot + 'statusnet/groups/' + joinOrLeave + '.json?t=' + timeNow(),
|
2013-08-19 22:30:57 +09:00
|
|
|
|
type: "POST",
|
|
|
|
|
data: {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
id: group_id
|
2013-08-19 22:30:57 +09:00
|
|
|
|
},
|
|
|
|
|
dataType:"json",
|
|
|
|
|
error: function(data){ actionOnSuccess(false,this_element); console.log(data); },
|
|
|
|
|
success: function(data) { actionOnSuccess(data,this_element);}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ·
|
|
|
|
|
·
|
2014-05-28 03:40:51 +09:00
|
|
|
|
· Post queet
|
2013-08-19 22:30:57 +09:00
|
|
|
|
·
|
|
|
|
|
· @param queetText_txt: the text to post
|
|
|
|
|
· @param in_reply_to_status_id: the local id for the queet to reply to
|
|
|
|
|
· @param actionOnSuccess: callback function, false on error, data on success
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · · · · · */
|
|
|
|
|
|
2014-05-28 03:40:51 +09:00
|
|
|
|
function postQueetToAPI(queetText_txt, in_reply_to_status_id, actionOnSuccess) {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
$.ajax({ url: window.apiRoot + 'statuses/update.json?t=' + timeNow(),
|
2013-08-19 22:30:57 +09:00
|
|
|
|
type: "POST",
|
|
|
|
|
data: {
|
|
|
|
|
status: queetText_txt,
|
|
|
|
|
source: 'Qvitter',
|
|
|
|
|
in_reply_to_status_id: in_reply_to_status_id
|
|
|
|
|
},
|
|
|
|
|
dataType:"json",
|
|
|
|
|
error: function(data){ actionOnSuccess(false); console.log(data); },
|
|
|
|
|
success: function(data) { actionOnSuccess(data);}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ·
|
|
|
|
|
·
|
|
|
|
|
· Generic POST-action
|
|
|
|
|
·
|
|
|
|
|
· @param action: the api action, e.q. 'statuses/retweet/1.json'
|
|
|
|
|
· @param actionOnSuccess: callback function, false on error, data on success
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · · · · · */
|
|
|
|
|
|
|
|
|
|
function postActionToAPI(action, actionOnSuccess) {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
$.ajax({ url: window.apiRoot + action + qOrAmp(action) + 't=' + timeNow(),
|
2013-08-19 22:30:57 +09:00
|
|
|
|
type: "POST",
|
|
|
|
|
data: {
|
2014-05-16 11:07:30 +09:00
|
|
|
|
source: 'Qvitter'
|
2013-08-19 22:30:57 +09:00
|
|
|
|
},
|
|
|
|
|
dataType:"json",
|
|
|
|
|
error: function(data){ actionOnSuccess(false); console.log(data); },
|
2014-05-23 21:13:38 +09:00
|
|
|
|
success: function(data) {
|
|
|
|
|
|
2014-10-03 02:24:54 +09:00
|
|
|
|
data = convertEmptyObjectToEmptyArray(data);
|
2014-05-23 21:13:38 +09:00
|
|
|
|
|
|
|
|
|
actionOnSuccess(data);
|
|
|
|
|
}
|
2013-08-19 22:30:57 +09:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ·
|
|
|
|
|
·
|
|
|
|
|
· Delete requeet
|
|
|
|
|
·
|
|
|
|
|
· @param this_stream_item: jQuery object for stream-item
|
|
|
|
|
· @param this_action: JQuery object for the requeet-button
|
|
|
|
|
· @param my_rq_id: the id for the requeet
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · */
|
|
|
|
|
|
|
|
|
|
function unRequeet(this_stream_item, this_action, my_rq_id) {
|
|
|
|
|
this_action.children('.with-icn').removeClass('done');
|
|
|
|
|
this_action.find('.with-icn b').html(window.sL.requeetVerb);
|
|
|
|
|
this_stream_item.removeClass('requeeted');
|
|
|
|
|
|
|
|
|
|
// post unrequeet
|
|
|
|
|
postActionToAPI('statuses/destroy/' + my_rq_id + '.json', function(data) {
|
|
|
|
|
if(data) {
|
|
|
|
|
remove_spinner();
|
|
|
|
|
this_stream_item.removeAttr('data-requeeted-by-me-id');
|
2014-11-24 21:47:45 +09:00
|
|
|
|
this_stream_item.children('.queet').children('.context').find('.requeet-text').children('a[data-user-id="' + window.myUserID + '"]').remove();
|
|
|
|
|
if(this_stream_item.children('.queet').children('.context').find('.requeet-text').children('a').length<1) {
|
|
|
|
|
this_stream_item.children('.queet').children('.context').remove();
|
|
|
|
|
}
|
2015-02-26 05:16:24 +09:00
|
|
|
|
getFavsAndRequeetsForQueet(this_stream_item, this_stream_item.attr('data-quitter-id'));
|
2013-08-19 22:30:57 +09:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
remove_spinner();
|
|
|
|
|
this_action.children('.with-icn').addClass('done');
|
|
|
|
|
this_action.find('.with-icn b').html(window.sL.requeetedVerb);
|
|
|
|
|
this_stream_item.addClass('requeeted');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ·
|
|
|
|
|
·
|
|
|
|
|
· Gets favs or requeets for a queet from api
|
|
|
|
|
·
|
2015-02-26 05:16:24 +09:00
|
|
|
|
· @param q: stream item object
|
2013-08-19 22:30:57 +09:00
|
|
|
|
· @param qid: the queet id
|
|
|
|
|
·
|
|
|
|
|
· · · · · · · · · */
|
|
|
|
|
|
2015-02-26 05:16:24 +09:00
|
|
|
|
function getFavsAndRequeetsForQueet(q,qid) {
|
|
|
|
|
|
|
|
|
|
// get immediately from localstorage cache
|
2015-03-06 06:22:48 +09:00
|
|
|
|
localStorageObjectCache_GET('favsAndRequeets',qid,function(data){
|
|
|
|
|
if(data) {
|
|
|
|
|
showFavsAndRequeetsInQueet(q, data);
|
|
|
|
|
}
|
|
|
|
|
});
|
2015-02-26 05:16:24 +09:00
|
|
|
|
|
|
|
|
|
$.ajax({ url: window.apiRoot + "qvitter/favs_and_repeats/" + qid + ".json?t=" + timeNow(),
|
2014-05-16 11:07:30 +09:00
|
|
|
|
type: "GET",
|
2013-08-19 22:30:57 +09:00
|
|
|
|
dataType: 'json',
|
2015-02-26 05:16:24 +09:00
|
|
|
|
success: function(data) {
|
|
|
|
|
if(data.favs.length > 0 || data.repeats.length > 0) {
|
2015-03-06 06:22:48 +09:00
|
|
|
|
|
|
|
|
|
localStorageObjectCache_STORE('favsAndRequeets',qid, data); // cache response
|
2015-02-26 05:16:24 +09:00
|
|
|
|
|
|
|
|
|
if(q.hasClass('expanded') && !q.hasClass('collapsing')) {
|
|
|
|
|
showFavsAndRequeetsInQueet(q,data);
|
|
|
|
|
}
|
2013-08-19 22:30:57 +09:00
|
|
|
|
}
|
|
|
|
|
else {
|
2015-02-26 05:16:24 +09:00
|
|
|
|
// remove from cache and DOM if all favs and repeats are deleted
|
2015-03-06 06:22:48 +09:00
|
|
|
|
localStorageObjectCache_STORE('favsAndRequeets',qid, false);
|
2015-02-26 05:16:24 +09:00
|
|
|
|
q.children('.queet').find('.stats').remove();
|
2013-08-19 22:30:57 +09:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
error: function(data) {
|
|
|
|
|
remove_spinner();
|
|
|
|
|
console.log(data);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2015-03-06 06:22:48 +09:00
|
|
|
|
showFavsAndRequeetsInQueet
|