2017-05-01 09:40:19 +02:00
|
|
|
/**
|
|
|
|
|
* Mastodon User Timeline Widget
|
2017-05-08 09:07:03 +02:00
|
|
|
* Copyright (c) 2017 有限会社アゼット
|
|
|
|
|
* ライセンスに関して、LICENSEファイルを参照下さい。
|
|
|
|
|
* see license file for details.
|
2017-05-01 09:40:19 +02:00
|
|
|
*
|
2017-05-16 12:20:57 +02:00
|
|
|
* @author Azet <http://www.azet.jp>
|
2017-05-19 04:58:08 +02:00
|
|
|
* @version 1.04 (also update MastodonAPI.version below)
|
2017-05-01 09:40:19 +02:00
|
|
|
* @param object params_
|
|
|
|
|
* instance_uri : the instance to fetch messages from
|
2017-05-16 12:20:57 +02:00
|
|
|
* access_token : widget's application access token (can be generated from http://www.azet.jp/mastodon.wizard/wizard_en.html)
|
2017-05-01 09:40:19 +02:00
|
|
|
* account_id : user account id to fetch messages of
|
|
|
|
|
* target_selector : HTML node selector (jquery/css style)
|
2017-05-16 12:20:57 +02:00
|
|
|
* toots_limit : max toots display count (default 20 like API)
|
2017-05-01 09:40:19 +02:00
|
|
|
*/
|
2017-05-18 09:01:01 +02:00
|
|
|
|
2017-05-19 04:58:08 +02:00
|
|
|
/* constructor >>> */
|
2017-05-01 09:40:19 +02:00
|
|
|
var MastodonApi = function(params_) {
|
|
|
|
|
|
|
|
|
|
// endpoint access settings
|
2017-05-19 04:58:08 +02:00
|
|
|
this.INSTANCE_URI = params_.instance_uri;
|
|
|
|
|
this.ACCESS_TOKEN = params_.access_token;
|
|
|
|
|
this.ACCOUNT_ID = params_.account_id;
|
2017-05-01 09:40:19 +02:00
|
|
|
// optional parameters
|
2017-05-19 04:58:08 +02:00
|
|
|
this.toots_limit = params_.toots_limit || 20;
|
|
|
|
|
this.picIcon = params_.pic_icon || '[PICTURE]';
|
|
|
|
|
this.boostsCountIcon = params_.boosts_count_icon || '[Boosts]';
|
|
|
|
|
this.favouritesCountIcon = params_.favourites_count_icon || '[Favourites]';
|
2017-05-01 09:40:19 +02:00
|
|
|
|
|
|
|
|
// display target element
|
|
|
|
|
this.widget = $(params_.target_selector);
|
|
|
|
|
|
|
|
|
|
// build the basic widget
|
|
|
|
|
this.makeWidget();
|
|
|
|
|
this.listStatuses();
|
2017-05-10 11:06:36 +02:00
|
|
|
|
|
|
|
|
// spoiler toggle
|
|
|
|
|
// jQuery event handler
|
|
|
|
|
var toggleSpoiler = function(e_) {
|
|
|
|
|
e_.preventDefault();
|
|
|
|
|
|
|
|
|
|
// btn text
|
|
|
|
|
if( $(this).hasClass('spoiler-opened') ) {
|
2017-05-18 09:01:01 +02:00
|
|
|
$(this).text(MastodonApi.text.spoilerBtnClosed);
|
2017-05-10 11:06:36 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2017-05-18 09:01:01 +02:00
|
|
|
$(this).text(MastodonApi.text.spoilerBtnOpened);
|
2017-05-10 11:06:36 +02:00
|
|
|
}
|
|
|
|
|
$(this).toggleClass('spoiler-opened');
|
|
|
|
|
|
|
|
|
|
// open body
|
|
|
|
|
$(this).parent().next('.spoiler-body').toggle();
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2017-05-18 09:01:01 +02:00
|
|
|
|
|
|
|
|
// nsfw toggle
|
|
|
|
|
// jQuery event handler
|
|
|
|
|
var toggleNsfwMedia = function(e_) {
|
|
|
|
|
e_.preventDefault();
|
|
|
|
|
|
|
|
|
|
if($(this).hasClass('nsfw-opened')) {
|
|
|
|
|
// hide image ===
|
|
|
|
|
$(this).css({
|
|
|
|
|
'background' : 'black'
|
|
|
|
|
})
|
|
|
|
|
.text(MastodonApi.text.nsfwViewMsg)
|
|
|
|
|
.removeClass('nsfw-opened');
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// display image ===
|
|
|
|
|
var img = $(this).attr('data-picpreview-url');
|
|
|
|
|
$(this).css({
|
|
|
|
|
'background' : 'url('+img+') center center no-repeat'
|
|
|
|
|
,'background-size' : 'cover'
|
|
|
|
|
})
|
|
|
|
|
.text('')
|
|
|
|
|
.addClass('nsfw-opened');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-05-10 11:06:36 +02:00
|
|
|
// spoiler buttons events
|
|
|
|
|
this.widget.on('click', '.btn-spoiler', toggleSpoiler);
|
|
|
|
|
|
2017-05-18 09:01:01 +02:00
|
|
|
// hidden media display toggle
|
|
|
|
|
this.widget.on('click', '.toot-media-nsfw', toggleNsfwMedia);
|
2017-05-10 11:06:36 +02:00
|
|
|
}
|
2017-05-19 04:58:08 +02:00
|
|
|
/* <<< end constructor */
|
|
|
|
|
|
2017-05-10 11:06:36 +02:00
|
|
|
|
2017-05-19 04:58:08 +02:00
|
|
|
/* widget Attributes >>> */
|
|
|
|
|
MastodonApi.build = 4; // later for version comparisons if needed
|
|
|
|
|
MastodonApi.version = "1.04"; // display
|
|
|
|
|
/* <<< */
|
2017-05-16 12:20:57 +02:00
|
|
|
|
2017-05-01 09:40:19 +02:00
|
|
|
|
2017-05-19 04:58:08 +02:00
|
|
|
/* texts >>> */
|
2017-05-18 09:01:01 +02:00
|
|
|
MastodonApi.text = {
|
|
|
|
|
spoilerBtnClosed : "Show more"
|
|
|
|
|
,spoilerBtnOpened : "Show less"
|
|
|
|
|
,nsfwLabel : "NSFW"
|
|
|
|
|
,nsfwViewMsg : "Click to view"
|
|
|
|
|
};
|
2017-05-19 04:58:08 +02:00
|
|
|
/* <<< */
|
2017-05-18 09:01:01 +02:00
|
|
|
|
2017-05-01 09:40:19 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* build timeline widget
|
|
|
|
|
*/
|
|
|
|
|
MastodonApi.prototype.makeWidget = function() {
|
|
|
|
|
this.widget.addClass('mastodon-timeline');
|
|
|
|
|
this.widget.append($('<div class="mt-header"><h4>Toots</h4> by <span class="user-link"></span></div>'));
|
|
|
|
|
this.widget.append($('<div class="mt-body"><div class="mt-loading">loading...</div></div>'));
|
|
|
|
|
this.widget.append($('<div class="mt-footer"></div>'));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* listing function
|
|
|
|
|
*/
|
|
|
|
|
MastodonApi.prototype.listStatuses = function() {
|
|
|
|
|
var mapi = this;
|
|
|
|
|
|
|
|
|
|
// get request
|
|
|
|
|
$.ajax({
|
|
|
|
|
url: this.INSTANCE_URI+'/api/v1/accounts/'+this.ACCOUNT_ID+'/statuses'
|
|
|
|
|
,headers: {
|
|
|
|
|
Authorization : 'Bearer '+this.ACCESS_TOKEN
|
|
|
|
|
}
|
|
|
|
|
,method : 'GET'
|
|
|
|
|
,dataType: 'json'
|
|
|
|
|
,data : {
|
|
|
|
|
limit : this.toots_limit
|
|
|
|
|
}
|
|
|
|
|
,success: function(data_) {
|
|
|
|
|
// clear the loading message
|
|
|
|
|
$('.mt-body', mapi.widget).html("");
|
|
|
|
|
//console.log( data_ );
|
|
|
|
|
|
|
|
|
|
// add posts
|
|
|
|
|
for(var i in data_) {
|
|
|
|
|
if(i==0) {
|
|
|
|
|
// update user link only at first post
|
|
|
|
|
var account = data_[i].account;
|
|
|
|
|
setHeaderUserLink.call(mapi, account);
|
|
|
|
|
setFooterLink.call(mapi, account);
|
|
|
|
|
}
|
2017-05-19 08:51:22 +02:00
|
|
|
if(data_[i].visibility=='public') {
|
2017-05-10 09:46:33 +02:00
|
|
|
// list only public toots
|
|
|
|
|
appendStatus.call(mapi, data_[i]);
|
|
|
|
|
}
|
2017-05-01 09:40:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fix content link target
|
|
|
|
|
$('a', this.widget).attr('target', '_blank');
|
|
|
|
|
}
|
2017-05-02 11:18:02 +02:00
|
|
|
,error: function(d_) {
|
|
|
|
|
//console.log( d_ );
|
|
|
|
|
if(d_.responseJSON) {
|
|
|
|
|
$('.mt-header', mapi.widget).html('ERROR');
|
|
|
|
|
$('.mt-body', mapi.widget).html( '<div class="mt-error">' + d_.responseJSON.error + '</div>');
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-05-01 09:40:19 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* add user link
|
|
|
|
|
* @param object account_
|
|
|
|
|
*/
|
|
|
|
|
var setHeaderUserLink = function(account_) {
|
|
|
|
|
// set user name and link
|
|
|
|
|
$('.user-link', this.widget).append("<a href='"+account_.url+"'>@"+account_.username+"</a>");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* add user link
|
|
|
|
|
* @param object account_
|
|
|
|
|
*/
|
|
|
|
|
var setFooterLink = function(account_) {
|
|
|
|
|
var domain = this.INSTANCE_URI.replace(/https?:\/\//, '');
|
|
|
|
|
$('.mt-footer', this.widget).append("View on <a href='"+account_.url+"'>"+domain+"</a>");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* inner function to add each message in container
|
|
|
|
|
* @param object status_
|
|
|
|
|
*/
|
|
|
|
|
var appendStatus = function(status_) {
|
|
|
|
|
//console.log( status_ );
|
2017-05-18 11:09:24 +02:00
|
|
|
var content;
|
2017-05-01 09:40:19 +02:00
|
|
|
|
2017-05-18 07:21:00 +02:00
|
|
|
// dealing with spoiler content
|
2017-05-10 11:06:36 +02:00
|
|
|
if(status_.spoiler_text != "") {
|
|
|
|
|
// handle spoilers
|
|
|
|
|
//content.wrap('<div class="spoiler"></div>');
|
2017-05-18 11:09:24 +02:00
|
|
|
content = $(
|
|
|
|
|
'<div class="spoiler-header">'+status_.spoiler_text+'<a class="btn-spoiler" href="#open-spoiler">'+MastodonApi.text.spoilerBtnClosed+'</a></div>'+
|
|
|
|
|
'<div class="spoiler-body">'+status_.content+'</div>' +
|
|
|
|
|
'<div class="toot-medias"></div>'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
content = $(status_.content +
|
|
|
|
|
'<div class="toot-medias"></div>'
|
|
|
|
|
);
|
2017-05-10 11:06:36 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-01 09:40:19 +02:00
|
|
|
var date = prepareDateDisplay(status_.created_at);
|
|
|
|
|
var timestamp = $("<div class='mt-date'><a href='"+status_.url+"'>" + date + "</a></div>");
|
|
|
|
|
|
2017-05-18 07:21:00 +02:00
|
|
|
// sensitive content
|
2017-05-16 12:49:44 +02:00
|
|
|
if(status_.sensitive) {
|
2017-05-18 09:01:01 +02:00
|
|
|
timestamp.prepend('<span class="nsfw">' + MastodonApi.text.nsfwLabel + '</span>');
|
2017-05-16 12:49:44 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-18 07:21:00 +02:00
|
|
|
|
2017-05-01 09:40:19 +02:00
|
|
|
// status container
|
2017-05-18 07:21:00 +02:00
|
|
|
var toot = $("<div class='mt-toot'></div>");
|
2017-05-01 09:40:19 +02:00
|
|
|
// avatar
|
|
|
|
|
var avatar = $("<div class='mt-avatar'></div>");
|
|
|
|
|
avatar.css({
|
|
|
|
|
'background' : "white url('"+status_.account.avatar+"') 50% 50% no-repeat"
|
|
|
|
|
,'background-size' : 'contain'
|
|
|
|
|
});
|
|
|
|
|
// user name and url
|
|
|
|
|
var user = $("<div class='mt-user'><a href='"+status_.account.url+"'>"+status_.account.username+"</a></div>");
|
|
|
|
|
|
|
|
|
|
// add to HTML
|
|
|
|
|
toot.append( avatar );
|
|
|
|
|
toot.append( user );
|
|
|
|
|
toot.append( timestamp );
|
|
|
|
|
toot.append( content );
|
|
|
|
|
$('.mt-body', this.widget).append(toot);
|
2017-05-18 11:09:24 +02:00
|
|
|
|
|
|
|
|
// media attachmets? >>>
|
|
|
|
|
if(status_.media_attachments.length>0) {
|
|
|
|
|
var pic;
|
|
|
|
|
for(var picid in status_.media_attachments) {
|
|
|
|
|
pic = this.replaceMedias(content, status_.media_attachments[picid], status_.sensitive);
|
|
|
|
|
toot.append( pic );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// <<<
|
2017-05-19 04:58:08 +02:00
|
|
|
|
|
|
|
|
// stats (boosts + favourites counts) >>>
|
|
|
|
|
// data
|
|
|
|
|
var boostsCountIcon = '<span class="toot-status-boosts">' + this.boostsCountIcon +":"+ status_.reblogs_count + '</span>';
|
|
|
|
|
var favouritesCountIcon = '<span class="toot-status-favourites">' + this.favouritesCountIcon +":"+ status_.favourites_count + '</span>';
|
|
|
|
|
|
|
|
|
|
// html nodes
|
|
|
|
|
var statusBar = $('<div class="toot-status">' +
|
|
|
|
|
boostsCountIcon +
|
|
|
|
|
favouritesCountIcon +
|
|
|
|
|
'</div>');
|
|
|
|
|
|
|
|
|
|
toot.append( statusBar );
|
|
|
|
|
// <<<
|
2017-05-01 09:40:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* display toot time
|
|
|
|
|
*
|
|
|
|
|
* @author Azet
|
|
|
|
|
* @param StringDate date_ (standard time format)
|
|
|
|
|
* @return String
|
|
|
|
|
*/
|
|
|
|
|
var prepareDateDisplay = function(date_) {
|
|
|
|
|
var displayTime = "";
|
|
|
|
|
|
|
|
|
|
//var now = new Date();
|
|
|
|
|
var date = new Date( date_ );
|
|
|
|
|
|
|
|
|
|
displayTime = date.getFullYear()
|
|
|
|
|
+"/"+(date.getMonth()+1)
|
|
|
|
|
+"/"+date.getDate()
|
|
|
|
|
+" "+date.getHours()
|
|
|
|
|
+":"+("0"+date.getMinutes()).replace(/0(\d{2})/, "$1")
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
return displayTime;
|
2017-05-18 07:21:00 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* replace media (pictures) in text with an icon and appends a preview
|
|
|
|
|
*
|
|
|
|
|
* @author Azet
|
|
|
|
|
* @param jquery_object content
|
|
|
|
|
* @param object media_ (received with toot's JSON data)
|
|
|
|
|
* @param bool nsfw_ indicates the media is not to be displayed
|
|
|
|
|
* @return object modifier content object
|
|
|
|
|
*/
|
|
|
|
|
MastodonApi.prototype.replaceMedias = function(content, media_, nsfw_) {
|
|
|
|
|
var nsfw = nsfw_ || false;
|
|
|
|
|
|
2017-05-18 11:09:24 +02:00
|
|
|
// icon in place of link in content
|
|
|
|
|
var icon = '<a href="'+media_.url+'" target="_blank">'+this.picIcon+'</a>';
|
|
|
|
|
$('a[href="'+media_.text_url+'"]', content).replaceWith(icon);
|
|
|
|
|
|
2017-05-18 07:21:00 +02:00
|
|
|
if(nsfw) {
|
|
|
|
|
// pics hidden
|
2017-05-18 09:01:01 +02:00
|
|
|
var pic = '<div class="toot-media-preview toot-media-nsfw" style="background:black;" data-picpreview-url="'+media_.preview_url+'">' +
|
|
|
|
|
MastodonApi.text.nsfwViewMsg +
|
|
|
|
|
'</div>';
|
2017-05-18 07:21:00 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// pics visible
|
|
|
|
|
var pic = '<div class="toot-media-preview" style="background-image:url('+media_.preview_url+');"></div>';
|
2017-05-01 09:40:19 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-18 11:09:24 +02:00
|
|
|
return pic;
|
2017-05-01 09:40:19 +02:00
|
|
|
};
|
|
|
|
|
|