Add comments shortcode.

This commit is contained in:
tastytea 2019-10-31 08:37:37 +01:00
parent 811fa02a41
commit 049822a72a
Signed by: tastytea
GPG Key ID: CFC39497F1B26E07
8 changed files with 317 additions and 0 deletions

2
content/scripts/jquery-3.4.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,71 @@
/* globals MastodonAPI */
function fetch_mastodon_api_comments(instance, status_id)
{
const root = document.getElementById("mastodon-api-comments_" + status_id);
let api = new MastodonAPI(
{
instance: "https://" + instance,
api_user_token: ""
});
// Get the URL of the status and write the intro.
api.get("statuses/" + status_id, function(data)
{
root.appendChild(comments_intro(data.url));
});
// Get all the replies to the status and write them to the page.
api.get("statuses/" + status_id + "/context", function(data)
{
write_comments(root, data);
});
}
function comments_intro(url)
{
const p = document.createElement("p");
const a = document.createElement("a");
p.appendChild(document.createTextNode("You can "));
p.setAttribute("class", "mastodon-api-comment-intro");
a.setAttribute("href", url);
a.appendChild(
document.createTextNode("comment on this post in the Fediverse"));
p.appendChild(a);
p.appendChild(document.createTextNode("."));
return p;
}
function write_comments(root, data)
{
for (const status of data.descendants)
{
let content = status.content;
for (const emoji of status.emojis)
{
content = content.replace(
':' + emoji.shortcode + ':',
'<img style="height: 1em;" src="' + emoji.url + '">');
}
const p = document.createElement("p");
p.setAttribute("class", "mastodon-api-comment");
p.appendChild(author_html(status.account));
p.innerHTML += content;
root.appendChild(p);
}
}
function author_html(account)
{
const p = document.createElement("p");
p.setAttribute("class", "mastodon-api-comment-author");
const strong = document.createElement("strong");
strong.appendChild(document.createTextNode(account.display_name));
p.appendChild(strong);
p.appendChild(document.createTextNode(" (" + account.acct + ") wrote:"));
return p;
}

223
content/scripts/mastodon.js Normal file
View File

@ -0,0 +1,223 @@
// mastodon javascript lib
// by @kirschn@pleasehug.me 2017
// no fucking copyright
// do whatever you want with it
// but please don't hurt it (and keep this header)
var MastodonAPI = function (config) {
var apiBase = config.instance + "/api/v1/";
function checkArgs(args) {
var checkedArgs;
if (typeof args[1] === "function") {
checkedArgs = { data: {}, callback: args[1] };
} else {
checkedArgs = { data: args[1], callback: args[2] };
}
return checkedArgs;
}
function addAuthorizationHeader(headers, token) {
if (token) {
headers.Authorization = "Bearer " + token;
}
return headers;
}
function onAjaxSuccess(url, op, callback, logData) {
return function (data, textStatus, xhr) {
console.log("Successful " + op + " API request to " + url,
", status: " + textStatus,
", HTTP status: " + xhr.status,
", data: " + (logData ? JSON.stringify(data) : "<skipped>"));
if (typeof callback !== "undefined") {
callback(data, textStatus);
}
};
}
function onAjaxError(url, op) {
return function (xhr, textStatus, errorThrown) {
console.error("Failed " + op + " API request to " + url,
", status: " + textStatus,
", error: " + errorThrown,
", HTTP status: " + xhr.status,
", response JSON: " + JSON.stringify(xhr.responseJSON));
};
}
return {
setConfig: function (key, value) {
// modify initial config afterwards
config[key] = value;
},
getConfig: function (key) {
// get config key
return config[key];
},
get: function (endpoint) {
// for GET API calls
// can be called with two or three parameters
// endpoint, callback
// or
// endpoint, queryData, callback
// where queryData is an object { paramname1: "paramvalue1", paramname2: paramvalue2 }
var args = checkArgs(arguments);
var queryData = args.data;
var callback = args.callback;
var url = apiBase + endpoint;
// ajax function
return $.ajax({
url: url,
type: "GET",
data: queryData,
headers: addAuthorizationHeader({}, config.api_user_token),
success: onAjaxSuccess(url, "GET", callback, false),
error: onAjaxError(url, "GET")
});
},
patch: function (endpoint) {
// for PATCH API calls
var args = checkArgs(arguments);
var postData = args.data;
var callback = args.callback;
var url = apiBase + endpoint;
return $.ajax({
url: url,
type: "PATCH",
data: postData,
headers: addAuthorizationHeader({}, config.api_user_token),
success: onAjaxSuccess(url, "POST", callback, false),
error: onAjaxError(url, "POST")
});
},
post: function (endpoint) {
// for POST API calls
var args = checkArgs(arguments);
var postData = args.data;
var callback = args.callback;
var url = apiBase + endpoint;
return $.ajax({
url: url,
type: "POST",
data: postData,
headers: addAuthorizationHeader({}, config.api_user_token),
success: onAjaxSuccess(url, "POST", callback, false),
error: onAjaxError(url, "POST")
});
},
postMedia: function (endpoint) {
// for POST API calls
var args = checkArgs(arguments);
var postData = args.data;
var callback = args.callback;
var url = apiBase + endpoint;
return $.ajax({
url: url,
type: "POST",
data: postData,
contentType: false,
processData: false,
headers: addAuthorizationHeader({}, config.api_user_token),
success: onAjaxSuccess(url, "POST MEDIA", callback, false),
error: onAjaxError(url, "POST MEDIA")
});
},
delete: function (endpoint, callback) {
// for DELETE API calls.
var url = apiBase + endpoint;
return $.ajax({
url: url,
type: "DELETE",
headers: addAuthorizationHeader({}, config.api_user_token),
success: onAjaxSuccess(url, "DELETE", callback, false),
error: onAjaxError(url, "DELETE")
});
},
stream: function (streamType, onData) {
// Event Stream Support
// websocket streaming is undocumented. i had to reverse engineer the fucking web client.
// streamType is either
// user for your local home TL and notifications
// public for your federated TL
// public:local for your home TL
// hashtag&tag=fuckdonaldtrump for the stream of #fuckdonaldtrump
// callback gets called whenever new data ist recieved
// callback { event: (eventtype), payload: {mastodon object as described in the api docs} }
// eventtype could be notification (=notification) or update (= new toot in TL)
var es = new WebSocket("wss://" + apiBase.substr(8)
+ "streaming?access_token=" + config.api_user_token + "&stream=" + streamType);
var listener = function (event) {
console.log("Got Data from Stream " + streamType);
event = JSON.parse(event.data);
event.payload = JSON.parse(event.payload);
onData(event);
};
es.onmessage = listener;
},
registerApplication: function (client_name, redirect_uri, scopes, website, callback) {
// register a new application
// OAuth Auth flow:
// First register the application
// 2) get a access code from a user (using the link, generation function below!)
// 3) insert the data you got from the application and the code from the user into
// getAccessTokenFromAuthCode. Note: scopes has to be an array, every time!
// For example ["read", "write"]
// determine which parameters we got
if (website === null) {
website = "";
}
// build scope array to string for the api request
if (typeof scopes !== "string") {
scopes = scopes.join(" ");
}
var url = apiBase + "apps";
return $.ajax({
url: url,
type: "POST",
data: {
client_name: client_name,
redirect_uris: redirect_uri,
scopes: scopes,
website: website
},
success: onAjaxSuccess(url, "REGISTER", callback, true),
error: onAjaxError(url, "REGISTER")
});
},
generateAuthLink: function (client_id, redirect_uri, responseType, scopes) {
return config.instance + "/oauth/authorize?client_id=" + client_id + "&redirect_uri=" + redirect_uri +
"&response_type=" + responseType + "&scope=" + scopes.join("+");
},
getAccessTokenFromAuthCode: function (client_id, client_secret, redirect_uri, code, callback) {
var url = config.instance + "/oauth/token";
return $.ajax({
url: url,
type: "POST",
data: {
client_id: client_id,
client_secret: client_secret,
redirect_uri: redirect_uri,
grant_type: "authorization_code",
code: code
},
success: onAjaxSuccess(url, "TOKEN", callback, true),
error: onAjaxError(url, "TOKEN")
});
}
};
};
// node.js
if (typeof module !== "undefined") { module.exports = MastodonAPI; }

View File

@ -0,0 +1,3 @@
<script type="application/javascript" src="/scripts/jquery-3.4.1.min.js"></script>
<script type="application/javascript" src="/scripts/mastodon.js"></script>
<script type="application/javascript" src="/scripts/mastodon-api-comments.js"></script>

View File

@ -0,0 +1,8 @@
{{ $instance := .Get "instance" | default "false" }}
{{ $status_id := .Get "status_id" | default "false" }}
{{ partial "mastodon-api-comments-scripts.html" . }}
<p id="mastodon-api-comments_{{ $status_id }}" class="mastodon-api-comments"></p>
<script type="application/javascript">
fetch_mastodon_api_comments("{{ $instance }}", "{{ $status_id }}");
</script>

View File

@ -73,6 +73,10 @@ for file in style.css style-compat.css; do
sed -i 's/$/.right{float:right}/' tastytea/static/assets/${file}
sed -i 's/$/.left{float:left}/' tastytea/static/assets/${file}
sed -i 's/$/.mastodon-api-comment{margin-left: 1em;border:0.1em solid black;padding:0.1em 1em;}/' tastytea/static/assets/${file}
sed -i 's/$/.mastodon-api-comment:nth-child(even){background-color:#0402}/' tastytea/static/assets/${file}
sed -i 's/$/.mastodon-api-comment:nth-child(odd){background-color:#2402}/' tastytea/static/assets/${file}
# Make CSS more readable
sed -i 's/}/}\n/g' tastytea/static/assets/${file}
sed -i 's/{/ {/g' tastytea/static/assets/${file}

View File

@ -301,3 +301,6 @@ div.tip td.icon {color:var(--blue)}
div.important td.icon {color:var(--yellow)}
.right {float:right}
.left {float:left}
.mastodon-api-comment {margin-left: 1em; border:0.1em solid black; padding:0.1em 1em; }
.mastodon-api-comment:nth-child(even) {background-color:#0402}
.mastodon-api-comment:nth-child(odd) {background-color:#2402}

View File

@ -334,3 +334,6 @@ div.tip td.icon {color:var(--blue)}
div.important td.icon {color:var(--yellow)}
.right {float:right}
.left {float:left}
.mastodon-api-comment {margin-left: 1em; border:0.1em solid black; padding:0.1em 1em; }
.mastodon-api-comment:nth-child(even) {background-color:#0402}
.mastodon-api-comment:nth-child(odd) {background-color:#2402}