1 parent
7ad089ec54
commit
e678442198
56 files changed
+1452
-43
No files matched your search
@@ -1,6 +0,0 @@
|
||||
---
|
||||
title: "{{ replace .Name "-" " " | title }}"
|
||||
date: {{ .Date }}
|
||||
draft: true
|
||||
---
|
||||
|
||||
+7
-4
@@ -1,14 +1,14 @@
|
||||
baseurl = "https://mehl.mx/"
|
||||
languageCode = "en-GB"
|
||||
title = "Max Mehl"
|
||||
theme = [ "hugo-sustain", "hugo-cloak-email" ]
|
||||
theme = [ "hugo-sustain", "hugo-cloak-email", "hugo-mastodon-comments" ]
|
||||
|
||||
[blackfriday]
|
||||
# preserves linebreaks, and transforms to <br />
|
||||
extensions = [ "hardLineBreak" ]
|
||||
|
||||
[permalinks]
|
||||
post = "/:year/:month/:day/:slug"
|
||||
blog = "/blog/:year/:slug"
|
||||
|
||||
[params]
|
||||
avatar = "profile.jpg"
|
||||
@@ -17,8 +17,11 @@ extensions = [ "hardLineBreak" ]
|
||||
keywords = "manager, free software, open source, project, campaign, konstanz, berlin, munster, communication, IT service, computer, politics, administration, FSFE, scouts, founder"
|
||||
|
||||
# Custom assets can be linked with their paths relative to static/
|
||||
custom_css = ['css/custom.css']
|
||||
custom_js = []
|
||||
custom_css = ['css/custom.css', 'comments/mastodon-comments.css']
|
||||
custom_js = ['comments/getcomments.js']
|
||||
|
||||
[params.blog]
|
||||
headline = "Thoughts about tech, politics, and more"
|
||||
|
||||
[params.social]
|
||||
Github = "mxmehl"
|
||||
|
||||
@@ -4,7 +4,7 @@ date: 2014-09-28
|
||||
linktitle: Creating a New Theme
|
||||
title: Creating a New Theme
|
||||
highlight: true
|
||||
draft: true
|
||||
draft: false
|
||||
---
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ categories = [
|
||||
"golang",
|
||||
]
|
||||
highlight = "true"
|
||||
draft = true
|
||||
draft = false
|
||||
headerimage = "placeholder.jpg"
|
||||
headercredits = "Unsplash, [Dlanor S](https://unsplash.com/photos/2xEQDxB0ss4)"
|
||||
+++
|
||||
|
||||
Hugo uses the excellent [go][] [html/template][gohtmltemplate] library for
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title = "Getting Started with Hugo"
|
||||
description = ""
|
||||
tags = [
|
||||
"radio lockdown",
|
||||
"RadioLockdown",
|
||||
"golang",
|
||||
"hugo",
|
||||
"development",
|
||||
@@ -13,7 +13,7 @@ categories = [
|
||||
"golang",
|
||||
]
|
||||
highlight = "true"
|
||||
draft = true
|
||||
draft = false
|
||||
+++
|
||||
|
||||
## Step 1. Install Hugo
|
||||
|
||||
@@ -3,7 +3,7 @@ date: 2014-03-10
|
||||
linktitle: Migrating from Jekyll
|
||||
title: Migrate to Hugo from Jekyll
|
||||
highlight: "true"
|
||||
draft: true
|
||||
draft: false
|
||||
---
|
||||
|
||||
## Move static content to `static`
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
+++
|
||||
title = "TEST ARTICLE"
|
||||
description = ""
|
||||
tags = [
|
||||
"test"
|
||||
]
|
||||
date = "2018-04-02"
|
||||
categories = [
|
||||
"Development",
|
||||
]
|
||||
highlight = "true"
|
||||
draft = false
|
||||
headerimage = "placeholder.jpg"
|
||||
headercredits = "Unsplash, [Dlanor S](https://unsplash.com/photos/2xEQDxB0ss4)"
|
||||
+++
|
||||
|
||||
LOREM IPSUM Hugo uses the excellent [go][] [html/template][gohtmltemplate] library for
|
||||
its template engine. It is an extremely lightweight engine that provides a very
|
||||
small amount of logic. In our experience that it is just the right amount of
|
||||
logic to be able to create a good static website. If you have used other
|
||||
template systems from different languages or frameworks you will find a lot of
|
||||
similarities in go templates.
|
||||
|
||||
This document is a brief primer on using go templates. The [go docs][gohtmltemplate]
|
||||
provide more details.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 979 KiB |
@@ -0,0 +1 @@
|
||||
static/comments/config.php
|
||||
@@ -0,0 +1,14 @@
|
||||
<div class="comments-container">
|
||||
<h5>Comments</h5>
|
||||
<div id="statistics">
|
||||
<div id="like-count-container"></div><div id="reblog-count-container"></div><div id="reply-count-container"></div>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
<div id="comments"></div>
|
||||
<div class="clear"></div>
|
||||
<div id="reference"></div>
|
||||
<!--<p class="reference"><a href="https://mastodon.social/users/bjoern/statuses/{{ .Params.toot }}">Join the discussion on Mastodon!</a></p>-->
|
||||
</div>
|
||||
|
||||
<script>var MastodonTootId="{{ .Params.toot }}"</script>
|
||||
<script>var RelPermalink="{{ .RelPermalink }}"</script>
|
||||
@@ -0,0 +1,975 @@
|
||||
<?php
|
||||
// defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Class Mastodon_api
|
||||
*
|
||||
* PHP version 7.1
|
||||
*
|
||||
* Mastodon https://mastodon.social/
|
||||
* API LIST https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md
|
||||
*
|
||||
* @author KwangSeon Yun <middleyks@hanmail.net>
|
||||
* @copyright KwangSeon Yun
|
||||
* @license https://raw.githubusercontent.com/yks118/Mastodon-api-php/master/LICENSE MIT License
|
||||
* @link https://github.com/yks118/Mastodon-api-php
|
||||
*/
|
||||
class Mastodon_api {
|
||||
private $mastodon_url = '';
|
||||
private $client_id = '';
|
||||
private $client_secret = '';
|
||||
|
||||
private $token = array();
|
||||
private $scopes = array();
|
||||
|
||||
public function __construct () {}
|
||||
|
||||
public function __destruct () {}
|
||||
|
||||
/**
|
||||
* _post
|
||||
*
|
||||
* curl post
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $data
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
private function _post ($url,$data = array()) {
|
||||
$parameters = array();
|
||||
$parameters[CURLOPT_POST] = 1;
|
||||
|
||||
// set access_token
|
||||
if (isset($this->token['access_token'])) {
|
||||
$data['access_token'] = $this->token['access_token'];
|
||||
}
|
||||
|
||||
if (count($data)) {
|
||||
$parameters[CURLOPT_POSTFIELDS] = preg_replace('/([(%5B)]{1})[0-9]+([(%5D)]{1})/','$1$2',http_build_query($data));
|
||||
}
|
||||
|
||||
$url = $this->mastodon_url.$url;
|
||||
$response = $this->get_content_curl($url,$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* _get
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $data
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
private function _get ($url,$data = array()) {
|
||||
$parameters = array();
|
||||
|
||||
// set authorization bearer
|
||||
if (isset($this->token['access_token'])) {
|
||||
$authorization = 'Authorization: '.$this->token['token_type'].' '.$this->token['access_token'];
|
||||
$parameters[CURLOPT_HTTPHEADER] = array('Content-Type: application/json',$authorization);
|
||||
}
|
||||
|
||||
$url = $this->mastodon_url.$url;
|
||||
if (count($data)) {
|
||||
$url .= '?' . http_build_query($data);
|
||||
}
|
||||
|
||||
$response = $this->get_content_curl($url,$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* _patch
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $data
|
||||
*
|
||||
* @return array $parameters
|
||||
*/
|
||||
private function _patch ($url,$data = array()) {
|
||||
$parameters = array();
|
||||
$parameters[CURLOPT_CUSTOMREQUEST] = 'PATCH';
|
||||
|
||||
// set authorization bearer
|
||||
if (isset($this->token['access_token'])) {
|
||||
$authorization = 'Authorization: '.$this->token['token_type'].' '.$this->token['access_token'];
|
||||
$parameters[CURLOPT_HTTPHEADER] = array('Content-Type: application/json',$authorization);
|
||||
}
|
||||
|
||||
if (count($data)) {
|
||||
$parameters[CURLOPT_POSTFIELDS] = json_encode($data);
|
||||
}
|
||||
|
||||
$url = $this->mastodon_url.$url;
|
||||
$response = $this->get_content_curl($url,$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* _delete
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
private function _delete ($url) {
|
||||
$parameters = array();
|
||||
$parameters[CURLOPT_CUSTOMREQUEST] = 'DELETE';
|
||||
|
||||
// set authorization bearer
|
||||
if (isset($this->token['access_token'])) {
|
||||
$authorization = 'Authorization: '.$this->token['token_type'].' '.$this->token['access_token'];
|
||||
$parameters[CURLOPT_HTTPHEADER] = array('Content-Type: application/json',$authorization);
|
||||
}
|
||||
|
||||
$url = $this->mastodon_url.$url;
|
||||
$response = $this->get_content_curl($url,$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_content_curl
|
||||
*
|
||||
* @param string $url
|
||||
* @param array $parameters
|
||||
*
|
||||
* @return array $data
|
||||
*/
|
||||
protected function get_content_curl ($url,$parameters = array()) {
|
||||
$data = array();
|
||||
|
||||
// set CURLOPT_USERAGENT
|
||||
if (!isset($parameters[CURLOPT_USERAGENT])) {
|
||||
if (isset($_SERVER['HTTP_USER_AGENT'])) {
|
||||
$parameters[CURLOPT_USERAGENT] = $_SERVER['HTTP_USER_AGENT'];
|
||||
} else {
|
||||
// default IE11
|
||||
$parameters[CURLOPT_USERAGENT] = 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko';
|
||||
}
|
||||
}
|
||||
|
||||
// check curl_init
|
||||
if (function_exists('curl_init')) {
|
||||
$ch = curl_init();
|
||||
|
||||
// url 설정
|
||||
curl_setopt($ch,CURLOPT_URL,$url);
|
||||
|
||||
foreach ($parameters as $key => $value) {
|
||||
curl_setopt($ch,$key,$value);
|
||||
}
|
||||
|
||||
// https
|
||||
if (!isset($parameters[CURLOPT_SSL_VERIFYPEER])) {
|
||||
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
|
||||
}
|
||||
if (!isset($parameters[CURLOPT_SSLVERSION])) {
|
||||
curl_setopt($ch,CURLOPT_SSLVERSION,6);
|
||||
}
|
||||
|
||||
// no header
|
||||
if (!isset($parameters[CURLOPT_HEADER])) {
|
||||
curl_setopt($ch,CURLOPT_HEADER,0);
|
||||
}
|
||||
|
||||
// POST / GET (default : GET)
|
||||
if (!isset($parameters[CURLOPT_POST]) && !isset($parameters[CURLOPT_CUSTOMREQUEST])) {
|
||||
curl_setopt($ch,CURLOPT_POST,0);
|
||||
}
|
||||
|
||||
// response get php value
|
||||
if (!isset($parameters[CURLOPT_RETURNTRANSFER])) {
|
||||
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
|
||||
}
|
||||
|
||||
// HTTP2
|
||||
if (!isset($parameters[CURLOPT_HTTP_VERSION])) {
|
||||
curl_setopt($ch,CURLOPT_HTTP_VERSION,3);
|
||||
}
|
||||
if (!isset($parameters[CURLINFO_HEADER_OUT])) {
|
||||
curl_setopt($ch,CURLINFO_HEADER_OUT,TRUE);
|
||||
}
|
||||
|
||||
$data['html'] = json_decode(curl_exec($ch),true);
|
||||
$data['response'] = curl_getinfo($ch);
|
||||
|
||||
curl_close($ch);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_url
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public function set_url ($path) {
|
||||
$this->mastodon_url = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_client
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $secret
|
||||
*/
|
||||
public function set_client ($id,$secret) {
|
||||
$this->client_id = $id;
|
||||
$this->client_secret = $secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_token
|
||||
*
|
||||
* @param string $token
|
||||
* @param string $type
|
||||
*/
|
||||
public function set_token ($token,$type) {
|
||||
$this->token['access_token'] = $token;
|
||||
$this->token['token_type'] = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_scopes
|
||||
*
|
||||
* @param array $scopes read / write / follow
|
||||
*/
|
||||
public function set_scopes ($scopes) {
|
||||
$this->scopes = $scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* create_app
|
||||
*
|
||||
* @param string $client_name
|
||||
* @param array $scopes read / write / follow
|
||||
* @param string $redirect_uris
|
||||
* @param string $website
|
||||
*
|
||||
* @return array $response
|
||||
* int $response['id']
|
||||
* string $response['redirect_uri']
|
||||
* string $response['client_id']
|
||||
* string $response['client_secret']
|
||||
*/
|
||||
public function create_app ($client_name,$scopes = array(),$redirect_uris = '',$website = '') {
|
||||
$parameters = array();
|
||||
|
||||
if (count($scopes) == 0) {
|
||||
if (count($this->scopes) == 0) {
|
||||
$scopes = array('read','write','follow');
|
||||
} else {
|
||||
$scopes = $this->scopes;
|
||||
}
|
||||
}
|
||||
|
||||
$parameters['client_name'] = $client_name;
|
||||
$parameters['scopes'] = implode(' ',$scopes);
|
||||
|
||||
if (empty($redirect_uris)) {
|
||||
$parameters['redirect_uris'] = 'urn:ietf:wg:oauth:2.0:oob';
|
||||
} else {
|
||||
$parameters['redirect_uris'] = $redirect_uris;
|
||||
}
|
||||
|
||||
if ($website) {
|
||||
$parameters['website'] = $website;
|
||||
}
|
||||
|
||||
$response = $this->_post('/api/v2/apps',$parameters);
|
||||
|
||||
if (isset($response['html']['client_id'])) {
|
||||
$this->client_id = $response['html']['client_id'];
|
||||
$this->client_secret = $response['html']['client_secret'];
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* login
|
||||
*
|
||||
* @param string $id E-mail Address
|
||||
* @param string $password Password
|
||||
*
|
||||
* @return array $response
|
||||
* string $response['access_token']
|
||||
* string $response['token_type'] bearer
|
||||
* string $response['scope'] read
|
||||
* int $response['created_at'] time
|
||||
*/
|
||||
public function login ($id,$password) {
|
||||
$parameters = array();
|
||||
$parameters['client_id'] = $this->client_id;
|
||||
$parameters['client_secret'] = $this->client_secret;
|
||||
$parameters['grant_type'] = 'password';
|
||||
$parameters['username'] = $id;
|
||||
$parameters['password'] = $password;
|
||||
|
||||
if (count($this->scopes) == 0) {
|
||||
$parameters['scope'] = implode(' ',array('read','write','follow'));
|
||||
} else {
|
||||
$parameters['scope'] = implode(' ',$this->scopes);
|
||||
}
|
||||
|
||||
$response = $this->_post('/oauth/token',$parameters);
|
||||
|
||||
if (isset($response['html']['access_token'])) {
|
||||
$this->token['access_token'] = $response['html']['access_token'];
|
||||
$this->token['token_type'] = $response['html']['token_type'];
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
* int $response['id']
|
||||
* string $response['username']
|
||||
* string $response['acct']
|
||||
* string $response['display_name'] The name to display in the user's profile
|
||||
* bool $response['locked']
|
||||
* string $response['created_at']
|
||||
* int $response['followers_count']
|
||||
* int $response['following_count']
|
||||
* int $response['statuses_count']
|
||||
* string $response['note'] A new biography for the user
|
||||
* string $response['url']
|
||||
* string $response['avatar'] A base64 encoded image to display as the user's avatar
|
||||
* string $response['avatar_static']
|
||||
* string $response['header'] A base64 encoded image to display as the user's header image
|
||||
* string $response['header_static']
|
||||
*/
|
||||
public function accounts ($id) {
|
||||
$response = $this->_get('/api/v2/accounts/'.$id);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_verify_credentials
|
||||
*
|
||||
* Getting the current user
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_verify_credentials () {
|
||||
$response = $this->_get('/api/v2/accounts/verify_credentials');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_update_credentials
|
||||
*
|
||||
* Updating the current user
|
||||
*
|
||||
* @param array $parameters
|
||||
* string $parameters['display_name'] The name to display in the user's profile
|
||||
* string $parameters['note'] A new biography for the user
|
||||
* string $parameters['avatar'] A base64 encoded image to display as the user's avatar
|
||||
* string $parameters['header'] A base64 encoded image to display as the user's header image
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_update_credentials ($parameters) {
|
||||
$response = $this->_patch('/api/v2/accounts/update_credentials',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_followers
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_followers ($id) {
|
||||
$response = $this->_get('/api/v2/accounts/'.$id.'/followers');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_following
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_following ($id) {
|
||||
$response = $this->_get('/api/v2/accounts/'.$id.'/following');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_statuses
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_statuses ($id) {
|
||||
$response = $this->_get('/api/v2/accounts/'.$id.'/statuses');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_own_statuses, only own statuses
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_own_statuses ($id) {
|
||||
$response = $this->_get('/api/v2/accounts/'.$id.'/statuses?exclude_replies=1');
|
||||
$result = [];
|
||||
foreach ($response['html'] as $r) {
|
||||
if(is_null($r['reblog'])) {
|
||||
$result[] = $r;
|
||||
}
|
||||
}
|
||||
|
||||
$response['html'] = $result;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_follow
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_follow ($id) {
|
||||
$response = $this->_post('/api/v2/accounts/'.$id.'/follow');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_unfollow
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_unfollow ($id) {
|
||||
$response = $this->_post('/api/v2/accounts/'.$id.'/unfollow');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_block
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_block ($id) {
|
||||
$response = $this->_post('/api/v2/accounts/'.$id.'/block');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_unblock
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_unblock ($id) {
|
||||
$response = $this->_post('/api/v2/accounts/'.$id.'/unblock');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_mute
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_mute ($id) {
|
||||
$response = $this->_post('/api/v2/accounts/'.$id.'/mute');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_unmute
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_unmute ($id) {
|
||||
$response = $this->_post('/api/v2/accounts/'.$id.'/unmute');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_relationships
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param array $parameters
|
||||
* int $parameters['id']
|
||||
*
|
||||
* @return array $response
|
||||
* int $response['id']
|
||||
* bool $response['following']
|
||||
* bool $response['followed_by']
|
||||
* bool $response['blocking']
|
||||
* bool $response['muting']
|
||||
* bool $response['requested']
|
||||
*/
|
||||
public function accounts_relationships ($parameters) {
|
||||
$response = $this->_get('/api/v2/accounts/relationships',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* accounts_search
|
||||
*
|
||||
* @param array $parameters
|
||||
* string $parameters['q']
|
||||
* int $parameters['limit'] default : 40
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function accounts_search ($parameters) {
|
||||
$response = $this->_get('/api/v2/accounts/search',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* blocks
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function blocks () {
|
||||
$response = $this->_get('/api/v2/blocks');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* favourites
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function favourites () {
|
||||
$response = $this->_get('/api/v2/favourites');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* follow_requests
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function follow_requests () {
|
||||
$response = $this->_get('/api/v2/follow_requests');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* follow_requests_authorize
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function follow_requests_authorize ($id) {
|
||||
$response = $this->_post('/api/v2/follow_requests/authorize',array('id'=>$id));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* follow_requests_reject
|
||||
*
|
||||
* @see https://your-domain/web/accounts/:id
|
||||
*
|
||||
* @param int $id
|
||||
* @return array $response
|
||||
*/
|
||||
public function follow_requests_reject ($id) {
|
||||
$response = $this->_post('/api/v2/follow_requests/reject',array('id'=>$id));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* follows
|
||||
*
|
||||
* Following a remote user
|
||||
*
|
||||
* @param string $uri username@domain of the person you want to follow
|
||||
* @return array $response
|
||||
*/
|
||||
public function follows ($uri) {
|
||||
$response = $this->_post('/api/v2/follows',array('uri'=>$uri));
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* instance
|
||||
*
|
||||
* Getting instance information
|
||||
*
|
||||
* @return array $response
|
||||
* string $response['uri']
|
||||
* string $response['title']
|
||||
* string $response['description']
|
||||
* string $response['email']
|
||||
*/
|
||||
public function instance () {
|
||||
$response = $this->_get('/api/v2/instance');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* media
|
||||
*
|
||||
* Uploading a media attachment
|
||||
*
|
||||
* @param string $file_path local path / http path
|
||||
*
|
||||
* @return array $response
|
||||
* int $response['id'] ID of the attachment
|
||||
* string $response['type'] One of: "image", "video", "gifv"
|
||||
* string $response['url'] URL of the locally hosted version of the image
|
||||
* string $response['remote_url'] For remote images, the remote URL of the original image
|
||||
* string $response['preview_url'] URL of the preview image
|
||||
* string $response['text_url'] Shorter URL for the image, for insertion into text (only present on local images)
|
||||
*/
|
||||
public function media ($file_path) {
|
||||
$url = $this->mastodon_url.'/api/v2/media';
|
||||
$parameters = $data = array();
|
||||
$parameters[CURLOPT_HTTPHEADER] = array('Content-Type'=>'multipart/form-data');
|
||||
$parameters[CURLOPT_POST] = true;
|
||||
|
||||
// set access_token
|
||||
if (isset($this->token['access_token'])) {
|
||||
$parameters[CURLOPT_POSTFIELDS]['access_token'] = $this->token['access_token'];
|
||||
}
|
||||
|
||||
if (is_file($file_path)) {
|
||||
$mime_type = mime_content_type($file_path);
|
||||
|
||||
$cf = curl_file_create($file_path,$mime_type,'file');
|
||||
$parameters[CURLOPT_POSTFIELDS]['file'] = $cf;
|
||||
}
|
||||
|
||||
$response = $this->get_content_curl($url,$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* mutes
|
||||
*
|
||||
* Fetching a user's mutes
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function mutes () {
|
||||
$response = $this->_get('/api/v2/mutes');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* notifications
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function notifications ($id = 0) {
|
||||
$url = '/api/v2/notifications';
|
||||
|
||||
if ($id > 0) {
|
||||
$url .= '/'.$id;
|
||||
}
|
||||
|
||||
$response = $this->_get($url);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* notifications_clear
|
||||
*
|
||||
* Clearing notifications
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function notifications_clear () {
|
||||
$response = $this->_post('/api/v2/notifications/clear');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_reports
|
||||
*
|
||||
* Fetching a user's reports
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function get_reports () {
|
||||
$response = $this->_get('/api/v2/reports');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* post_reports
|
||||
*
|
||||
* Reporting a user
|
||||
*
|
||||
* @param array $parameters
|
||||
* int $parameters['account_id'] The ID of the account to report
|
||||
* int $parameters['status_ids'] The IDs of statuses to report (can be an array)
|
||||
* string $parameters['comment'] A comment to associate with the report.
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function post_reports ($parameters) {
|
||||
$response = $this->_post('/api/v2/reports',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* search
|
||||
*
|
||||
* Searching for content
|
||||
*
|
||||
* @param array $parameters
|
||||
* string $parameters['q'] The search query
|
||||
* string $parameters['resolve'] Whether to resolve non-local accounts
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function search ($parameters) {
|
||||
$response = $this->_get('/api/v2/search',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses
|
||||
*
|
||||
* Fetching a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses ($id) {
|
||||
$response = $this->_get('/api/v2/statuses/'.$id);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_context
|
||||
*
|
||||
* Getting status context
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_context ($id) {
|
||||
$response = $this->_get('/api/v2/statuses/'.$id.'/context');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_card
|
||||
*
|
||||
* Getting a card associated with a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_card ($id) {
|
||||
$response = $this->_get('/api/v2/statuses/'.$id.'/card');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_reblogged_by
|
||||
*
|
||||
* Getting who reblogged a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_reblogged_by ($id) {
|
||||
$response = $this->_get('/api/v2/statuses/'.$id.'/reblogged_by');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_favourited_by
|
||||
*
|
||||
* Getting who favourited a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_favourited_by ($id) {
|
||||
$response = $this->_get('/api/v2/statuses/'.$id.'/favourited_by');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* post_statuses
|
||||
*
|
||||
* @param array $parameters
|
||||
* string $parameters['status'] The text of the status
|
||||
* int $parameters['in_reply_to_id'] (optional): local ID of the status you want to reply to
|
||||
* int $parameters['media_ids'] (optional): array of media IDs to attach to the status (maximum 4)
|
||||
* string $parameters['sensitive'] (optional): set this to mark the media of the status as NSFW
|
||||
* string $parameters['spoiler_text'] (optional): text to be shown as a warning before the actual content
|
||||
* string $parameters['visibility'] (optional): either "direct", "private", "unlisted" or "public"
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function post_statuses ($parameters) {
|
||||
$response = $this->_post('/api/v2/statuses',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* delete_statuses
|
||||
*
|
||||
* Deleting a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response empty
|
||||
*/
|
||||
public function delete_statuses ($id) {
|
||||
$response = $this->_delete('/api/v2/statuses/'.$id);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_reblog
|
||||
*
|
||||
* Reblogging a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_reblog ($id) {
|
||||
$response = $this->_post('/api/v2/statuses/'.$id.'/reblog');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_unreblog
|
||||
*
|
||||
* Unreblogging a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_unreblog ($id) {
|
||||
$response = $this->_post('/api/v2/statuses/'.$id.'/unreblog');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_favourite
|
||||
*
|
||||
* Favouriting a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_favourite ($id) {
|
||||
$response = $this->_post('/api/v2/statuses/'.$id.'/favourite');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* statuses_unfavourite
|
||||
*
|
||||
* Unfavouriting a status
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function statuses_unfavourite ($id) {
|
||||
$response = $this->_post('/api/v2/statuses/'.$id.'/unfavourite');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* timelines_home
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function timelines_home () {
|
||||
$response = $this->_get('/api/v2/timelines/home');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* timelines_public
|
||||
*
|
||||
* @param array $parameters
|
||||
* bool $parameters['local'] Only return statuses originating from this instance
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function timelines_public ($parameters = array()) {
|
||||
$response = $this->_get('/api/v2/timelines/public',$parameters);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* timelines_tag
|
||||
*
|
||||
* @param string $hashtag
|
||||
* @param array $parameters
|
||||
* bool $parameters['local'] Only return statuses originating from this instance
|
||||
*
|
||||
* @return array $response
|
||||
*/
|
||||
public function timelines_tag ($hashtag,$parameters = array()) {
|
||||
$response = $this->_get('/api/v2/timelines/tag/'.$hashtag,$parameters);
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
$config = [
|
||||
'mastodon-instance' => 'https://mastodon.social',
|
||||
'user-id' => 549759,
|
||||
'threshold' => 300,
|
||||
'token' => '47598kdjhfgkdg894kejg834joejg43'
|
||||
];
|
||||
@@ -0,0 +1,50 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
// check if we show a blog post or not. You might have to adapt this
|
||||
var isArticle = /\/?blog\/\d\d\d\d\/.+$/.test(RelPermalink);
|
||||
if (isArticle === false) {
|
||||
console.log("Not a blog post, no need to search for comments");
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: "/comments/getcomments.php",
|
||||
type: "get",
|
||||
data: {
|
||||
search : RelPermalink
|
||||
},
|
||||
success: function(data) {
|
||||
var stats = data.stats;
|
||||
var root = data.stats.root;
|
||||
$("#like-count-container").append('<div id="mastodon-like-count"><a href="' + stats.url + '"><span title="Likes"><i class="fa fa-star"></i>' + stats.favs + '</span></a></div></div>');
|
||||
$("#reblog-count-container").append('<div id="mastodon-reblog-count"><a href="' + stats.url + '"><span title="Reblogs"><i class="fa fa-retweet"></i>' + stats.reblogs + '</span></a></div></div>');
|
||||
$("#reply-count-container").append('<div id="mastodon-reply-count"><a href="' + stats.url + '"><span title="Comments"><i class="fa fa-comments"></i>' + stats.replies + '</span></a></div></div>');
|
||||
var comments = data.comments;
|
||||
$.each(comments, function(key, value) {
|
||||
var timestamp = Date.parse(value.date);
|
||||
var date = new Date(timestamp);
|
||||
var comment = "<div class='comment' id='" + key + "'>";
|
||||
comment += "<img class='avatar' src='" + value.author.avatar + "' />";
|
||||
comment += "<div class='author'><a class='displayName' href='" + value.author.url + "'>" + value.author.display_name + "</a> wrote at ";
|
||||
comment += "<a class='date' href='" + value.url + "'>" + date.toDateString() + ', ' + date.toLocaleTimeString() + "</a></div>";
|
||||
comment += "<div class='toot'>" + value.toot + "</div>";
|
||||
comment += "</div>";
|
||||
var parentComment = document.getElementById(value.reply_to);
|
||||
if (value.reply_to === root || parentComment === null) {
|
||||
$("#comments").append(comment);
|
||||
} else {
|
||||
var selector = '#'+value.reply_to;
|
||||
$(selector).append(comment);
|
||||
}
|
||||
});
|
||||
if (parseInt(root) > 0) {
|
||||
$("#reference").append("<a href='https://mastodon.social/users/bjoern/statuses/" + root + "'>Join the discussion on Mastodon!</a>");
|
||||
} else {
|
||||
$("#comments").empty();
|
||||
$("#statistics").empty();
|
||||
$("#reference").append("Comments are handled by my <a href='https://mastodon.social/@bjoern'>Mastodon account</a>. Sadly this article wasn't published at Mastodon. Feel free to <a href='https://www.schiessle.org/contact/'>send me a mail</a> if you want to share your thoughts regarding this topic.");
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Bjoern Schiessle <bjoern@schiessle.org>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program 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 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
require_once 'Mastodon_api.php';
|
||||
require_once '../../mastodon.feed/config.php';
|
||||
|
||||
class CollectMastodonData {
|
||||
|
||||
/** @var \Mastodon_api */
|
||||
private $api;
|
||||
|
||||
/** @var string url of the mastodon instance */
|
||||
private $mastodonUrl = 'https://mastodon.social';
|
||||
|
||||
/** @var string token to authenticate at the mastodon instance */
|
||||
private $bearerToken;
|
||||
|
||||
/** @var int keep cache at least 600 seconds = 10 minutes */
|
||||
private $threshold = 600;
|
||||
|
||||
/** @var string uid on the mastodon instance */
|
||||
private $uid;
|
||||
|
||||
/** @var array cached comments from previous searches */
|
||||
private $commentCache = [];
|
||||
|
||||
private $cacheFile = 'myCommentsCache.json';
|
||||
|
||||
public function __construct($config) {
|
||||
$this->mastodonUrl = $config['mastodon-instance'];
|
||||
$this->bearerToken = $config['token'];
|
||||
$this->uid = $config['user-id'];
|
||||
|
||||
$this->api = new Mastodon_api();
|
||||
|
||||
$this->api->set_url($this->mastodonUrl);
|
||||
$this->api->set_token($this->bearerToken, 'bearer');
|
||||
}
|
||||
|
||||
private function filterComments($descendants, $root, &$result) {
|
||||
foreach ($descendants as $d) {
|
||||
$result['comments'][$d['id']] = [
|
||||
'author' => [
|
||||
'display_name' => $d['account']['display_name'] ? $d['account']['display_name'] : $d['account']['username'],
|
||||
'avatar' => $d['account']['avatar_static'],
|
||||
'url' => $d['account']['url']
|
||||
],
|
||||
'toot' => $d['content'],
|
||||
'date' => $d['created_at'],
|
||||
'url' => $d['uri'],
|
||||
'reply_to' => $d['in_reply_to_id'],
|
||||
'root' => $root,
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function filterStats($stats) {
|
||||
$result = [
|
||||
'reblogs' => (int)$stats['reblogs_count'],
|
||||
'favs' => (int)$stats['favourites_count'],
|
||||
'replies' => (int)$stats['replies_count'],
|
||||
'url' => $stats['url']
|
||||
];
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function filterSearchResults($searchResult) {
|
||||
$result = [];
|
||||
if (isset($searchResult['html']['statuses'])) {
|
||||
foreach ($searchResult['html']['statuses'] as $status) {
|
||||
if ($status['in_reply_to_id'] === null) {
|
||||
$result[] = $status['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* find all toots for a given blog post and return the corresponding IDs
|
||||
*
|
||||
* @param string $search
|
||||
* @return array
|
||||
*/
|
||||
public function findToots($search) {
|
||||
$result = $this->api->search(['q' => $search]);
|
||||
return $this->filterSearchResults($result);
|
||||
}
|
||||
|
||||
public function getComments($id, &$result) {
|
||||
$raw = file_get_contents("https://mastodon.social/api/v1/statuses/$id/context");
|
||||
$json = json_decode($raw, true);
|
||||
$this->filterComments($json['descendants'], $id, $result);
|
||||
}
|
||||
|
||||
public function getStatistics($id, &$result) {
|
||||
$raw = file_get_contents("https://mastodon.social/api/v1/statuses/$id");
|
||||
$json = json_decode($raw, true);
|
||||
$newStats = $this->filterStats($json);
|
||||
$result['stats']['reblogs'] += $newStats['reblogs'];
|
||||
$result['stats']['favs'] += $newStats['favs'];
|
||||
$result['stats']['replies'] += $newStats['replies'];
|
||||
if (empty($result['stats']['url'])) {
|
||||
$result['stats']['url'] = $newStats['url'];
|
||||
}
|
||||
}
|
||||
|
||||
public function storeCollection($id, $comments) {
|
||||
$timestamp = time();
|
||||
$comments['timestamp'] = $timestamp;
|
||||
$this->commentCache[$id] = $comments;
|
||||
file_put_contents($this->cacheFile, json_encode($this->commentCache));
|
||||
}
|
||||
|
||||
public function getCachedCollection($search) {
|
||||
if (file_exists($this->cacheFile)) {
|
||||
$cachedComments = file_get_contents($this->cacheFile);
|
||||
$cachedCommentsArray = json_decode($cachedComments, true);
|
||||
if (is_array($cachedCommentsArray)) {
|
||||
$this->commentCache = $cachedCommentsArray;
|
||||
$currentTimestamp = time();
|
||||
if (isset($cachedCommentsArray[$search])) {
|
||||
if ((int)$cachedCommentsArray[$search]['timestamp'] + $this->threshold > $currentTimestamp) {
|
||||
unset($cachedCommentsArray[$search]['timestamp']);
|
||||
return $cachedCommentsArray[$search];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
$result = ['comments' => [], 'stats' => ['reblogs' => 0, 'favs' => 0, 'replies' => 0, 'url' => '', 'root' => 0]];
|
||||
|
||||
$search = isset($_GET['search']) ? $_GET['search'] : '';
|
||||
$collector = new CollectMastodonData($config);
|
||||
$ids = [];
|
||||
if (!empty($search)) {
|
||||
$oldCollection = $collector->getCachedCollection($search);
|
||||
if (empty($oldCollection)) {
|
||||
$ids = $collector->findToots($search);
|
||||
$result['stats']['root'] = isset($ids[0]) ? $ids[0] : 0;
|
||||
foreach ($ids as $id) {
|
||||
// get comments
|
||||
$newComments = $collector->getComments($id, $result);
|
||||
// get statistics (likes, replies, boosts,...)
|
||||
$collector->getStatistics($id, $result);
|
||||
// FIXME: At the moment the API doesn't return the correct replies count so I count it manually
|
||||
$result['stats']['replies'] = count($result['comments']);
|
||||
}
|
||||
$collector->storeCollection($search, $result);
|
||||
} else {
|
||||
$result = $oldCollection;
|
||||
}
|
||||
}
|
||||
|
||||
// headers for not caching the results
|
||||
header('Cache-Control: no-cache, must-revalidate');
|
||||
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||
|
||||
// headers to tell that result is JSON
|
||||
header('Content-type: application/json');
|
||||
|
||||
// send the result now
|
||||
echo json_encode($result);
|
||||
@@ -0,0 +1,60 @@
|
||||
.comments-container .comment .avatar {
|
||||
float: left;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-left: 16px;
|
||||
margin-right: 16px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.comments-container #reference {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.comments-container .comment {
|
||||
margin-top: 50px;
|
||||
margin-bottom: 50px;
|
||||
font-size: 16px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.comments-container .toot {
|
||||
padding-left: 82px;
|
||||
}
|
||||
|
||||
.comments-container .author {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.comments-container #mastodon-like-count,
|
||||
.comments-container #mastodon-reblog-count,
|
||||
.comments-container #mastodon-reply-count
|
||||
{
|
||||
float: right;
|
||||
font-size: 16px;
|
||||
background: #eee;
|
||||
padding: 3px 10px;
|
||||
margin: 30px 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.comments-container #mastodon-like-count a,
|
||||
.comments-container #mastodon-reblog-count a,
|
||||
.comments-container #mastodon-reply-count a
|
||||
{
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.comments-container #mastodon-like-count a:hover,
|
||||
.comments-container #mastodon-reblog-count a:hover,
|
||||
.comments-container #mastodon-reply-count a:hover
|
||||
{
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.comments-container .fa {
|
||||
padding-right: 10px;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# theme.yaml configuration file
|
||||
|
||||
name: Mastodon Comments
|
||||
license: AGPL-3.0-or-later
|
||||
licenselink:
|
||||
description: Hugo theme component for scraping comments on a Mastodon post containing a site's address
|
||||
homepage:
|
||||
tags:
|
||||
- component
|
||||
features:
|
||||
- comments
|
||||
min_version: 0.40.0
|
||||
|
||||
author:
|
||||
name: Björn Schießle, Max Mehl
|
||||
homepage:
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 241 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 117 KiB |
@@ -1,24 +1,36 @@
|
||||
{{ partial "head" . }}
|
||||
<body>
|
||||
<body>
|
||||
<div id="wrap">
|
||||
<!-- Header -->
|
||||
{{ partial "header" . }}
|
||||
<div class="container">
|
||||
<h1>Archive</h1>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="container archive">
|
||||
<h1>{{ .Site.Params.Blog.Headline }}
|
||||
{{ if (isset .Data "Singular") }}
|
||||
<br />({{ .Data.Singular | humanize }}: {{lower .Title}})
|
||||
<span class="article-rss"><a href="/{{ .Data.Plural }}/{{lower .Title}}/index.xml" title="RSS Feed"><i class="fa fa-rss" aria-hidden="true"></i></a></span>
|
||||
{{ else }}
|
||||
<span class="article-rss"><a href="/index.xml" title="RSS Feed"><i class="fa fa-rss" aria-hidden="true"></i></a></span>
|
||||
{{ end }}
|
||||
</h1>
|
||||
{{ if .Site.Params.Social.CommentsProvider }}
|
||||
<p><a href="{{ .Site.Params.Social.CommentsProvider }}">Subscribe</a> to my Blog via Diaspora, Mastodon, Friendica or GNU Social. Never miss a article! Reshare, like and discuss it!</p>
|
||||
{{ end }}
|
||||
<p class="categories">
|
||||
<a class="label label-success" href="/blog">All</a>
|
||||
{{ range $name, $taxonomy := .Site.Taxonomies.categories }}
|
||||
<a class="label label-success" href="{{ "/categories/" | relLangURL }}{{ $name | urlize }}">
|
||||
{{ humanize $name }}
|
||||
</a>
|
||||
{{ end }}
|
||||
</p>
|
||||
|
||||
<div class="panel panel-default panel-overview">
|
||||
<div class="blogpost">
|
||||
{{ range .Data.Pages.ByPublishDate.Reverse }}
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-4 col-lg-4">
|
||||
<h5 style="text-align: right">
|
||||
{{ .Date.Format "January 2, 2006" }}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="col-sm-8 col-md-8 col-lg-8">
|
||||
<h5 style="text-align: left">
|
||||
<strong><a href="{{ .RelPermalink }}">{{ .Title | markdownify }}</a></strong>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="blog-summary">
|
||||
<h4><strong><a href="{{ .RelPermalink }}">{{ .Title | markdownify }}</a></strong></h4>
|
||||
<div class="metadata">Posted on {{ .Date.Format "2 January 2006" }} - Tagged with {{ range $i, $tag := .Params.tags }}{{ if $i }}, {{ end }}<a href="/tags/{{ lower $tag }}">{{ $tag }}</a>{{ end }}</div>
|
||||
<p>{{ .Summary }} <a class="learn-more" href="{{ .RelPermalink }}"></a></p>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
@@ -27,5 +39,5 @@
|
||||
</div>
|
||||
<!-- Footer -->
|
||||
{{ partial "footer" . }}
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -6,24 +6,27 @@
|
||||
{{ partial "header" . }}
|
||||
|
||||
<div class="container {{ replace (.LinkTitle | lower) " " "_" }}"> <!-- add link title add class -->
|
||||
<div class="blog-post">
|
||||
<h1>{{ .Title }}</h1>
|
||||
</div>
|
||||
{{ if ne .Params.page true }}
|
||||
<div class="blog-title">
|
||||
<h4>
|
||||
{{ .Date.Format "January 2, 2006" }}
|
||||
<div>
|
||||
<p class="categories">
|
||||
{{ .Date.Format "2 January 2006" }}
|
||||
|
||||
{{ range .Params.tags }}
|
||||
<span class="label label-success">{{ . }}</span>
|
||||
|
||||
<a class="label label-success" href="/tags/{{ lower . }}">{{ . }}</a>
|
||||
{{ end }}
|
||||
</h4>
|
||||
</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="blogpost">
|
||||
{{ if isset .Params "headerimage" }}
|
||||
<div class="header-image">
|
||||
<img src="/img/{{ .Params.headerImage }}" />
|
||||
<p>{{ with .Params.headercredits }}{{ . | markdownify }}{{ end }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ .Content }}
|
||||
<!-- only show related posts if param is true, or if it's not a page -->
|
||||
{{ if or (eq .Params.related true) (ne .Params.page true) }}
|
||||
@@ -34,7 +37,7 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-4 col-lg-4">
|
||||
<h6 style="text-align: right">
|
||||
{{ .Date.Format "January 2, 2006" }}
|
||||
{{ .Date.Format "2 January 2006" }}
|
||||
</h6>
|
||||
</div>
|
||||
<div class="col-sm-8 col-md-8 col-lg-8">
|
||||
@@ -49,6 +52,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
{{ partial "comments.html" . }}
|
||||
{{ partial "social" . }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
Vendored
File renamed without changes.
@@ -11,13 +11,24 @@ div.footer {
|
||||
.container a:hover {
|
||||
color: #12437A;
|
||||
}
|
||||
div.container.links .label-success {
|
||||
.container .label-success {
|
||||
background-color: rgba(92, 139, 184, 0.6);
|
||||
color: #FFF;
|
||||
}
|
||||
div.container h1 {
|
||||
.container a.label-success:hover {
|
||||
background-color: rgba(92, 139, 184, 0.9);
|
||||
color: #FFF;
|
||||
}
|
||||
.container h1 {
|
||||
font-weight: bold;
|
||||
color: #0D76EC;
|
||||
}
|
||||
.container h4 a {
|
||||
color: #0D76EC;
|
||||
}
|
||||
.container h4 a:hover {
|
||||
color: #0060CC;
|
||||
}
|
||||
|
||||
/* Avoid scrollbar jumps in centering
|
||||
* see https://css-tricks.com/eliminate-jumps-in-horizontal-centering-by-forcing-a-scroll-bar/
|
||||
@@ -63,3 +74,49 @@ div.contact p {
|
||||
.social-links li a:hover i {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
/* BLOG */
|
||||
.categories {
|
||||
font-size: 18px;
|
||||
margin: 1em 0 3em 0;
|
||||
}
|
||||
.blog-summary {
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
.metadata {
|
||||
font-size: 0.8em;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.blogpost .header-image img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
.blogpost .header-image p {
|
||||
opacity: 0.7;
|
||||
font-size: 0.8em;
|
||||
text-align: center;
|
||||
line-height: 1em;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
a.learn-more {
|
||||
font-size: 1.8em;
|
||||
line-height: 0.8em;
|
||||
font-weight: 700;
|
||||
font-variant: small-caps;
|
||||
text-transform: lowercase;
|
||||
padding: 0 1em 0 .3em;
|
||||
position: absolute;
|
||||
}
|
||||
a.learn-more::after {
|
||||
position: absolute;
|
||||
right: 0.3em;
|
||||
content: " » ";
|
||||
opacity: .8;
|
||||
transition: all 150ms linear;
|
||||
}
|
||||
a.learn-more:hover::after {
|
||||
right: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
Vendored
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user