Skip to content

Commit 05a2008

Browse files
committed
Add hashtag follow support.
1 parent fafa413 commit 05a2008

File tree

1 file changed

+213
-10
lines changed

1 file changed

+213
-10
lines changed

includes/class-mastodon-api.php

Lines changed: 213 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ public function rewrite_rules() {
161161
'api/v1/timelines/(home|public)' => 'api/v1/timelines/$matches[1]',
162162
'api/v1/timelines/tag/([^/|$]+)' => 'api/v1/timelines/tag/$matches[1]',
163163
'api/v2/search' => 'api/v1/search',
164+
'api/v1/tags/(.+)' => 'api/v1/tags/$matches[1]',
165+
'api/v1/tags/([^/]+)/follow' => 'api/v1/tags/$matches[1]/follow',
166+
'api/v1/tags/([^/]+)/unfollow' => 'api/v1/tags/$matches[1]/unfollow',
164167
);
165168

166169
foreach ( $generic as $rule ) {
@@ -254,7 +257,7 @@ public function add_rest_routes() {
254257
'api/v1/followed_tags',
255258
array(
256259
'methods' => 'GET',
257-
'callback' => '__return_empty_array',
260+
'callback' => array( $this, 'api_followed_tags' ),
258261
'permission_callback' => array( $this, 'logged_in_permission' ),
259262
)
260263
);
@@ -660,6 +663,36 @@ public function add_rest_routes() {
660663
'permission_callback' => array( $this, 'logged_in_permission' ),
661664
)
662665
);
666+
667+
register_rest_route(
668+
self::PREFIX,
669+
'api/v1/tags/(?P<id>[^/]+)',
670+
array(
671+
'methods' => array( 'GET', 'OPTIONS' ),
672+
'callback' => array( $this, 'api_tags' ),
673+
'permission_callback' => array( $this, 'logged_in_permission' ),
674+
)
675+
);
676+
677+
register_rest_route(
678+
self::PREFIX,
679+
'api/v1/tags/(?P<id>[^/]+)/follow',
680+
array(
681+
'methods' => array( 'POST', 'OPTIONS' ),
682+
'callback' => array( $this, 'api_tags_follow' ),
683+
'permission_callback' => array( $this, 'logged_in_permission' ),
684+
)
685+
);
686+
687+
register_rest_route(
688+
self::PREFIX,
689+
'api/v1/tags/(?P<id>[^/]+)/unfollow',
690+
array(
691+
'methods' => array( 'POST', 'OPTIONS' ),
692+
'callback' => array( $this, 'api_tags_unfollow' ),
693+
'permission_callback' => array( $this, 'logged_in_permission' ),
694+
)
695+
);
663696
}
664697

665698
public function query_vars( $query_vars ) {
@@ -1520,6 +1553,10 @@ public function api_timelines( $request ) {
15201553
public function api_tag_timelines( $request ) {
15211554
$args = $this->get_posts_query_args( $request );
15221555
$args['tag'] = $request->get_param( 'hashtag' );
1556+
1557+
$ppp_param = $request->get_param( 'limit' );
1558+
if( $ppp_param != null ) { $args['posts_per_page'] = $ppp_param; }
1559+
15231560
$args = apply_filters( 'mastodon_api_timelines_args', $args, $request );
15241561

15251562
return $this->get_posts( $args, $request->get_param( 'min_id' ), $request->get_param( 'max_id' ) );
@@ -1536,14 +1573,20 @@ public function api_search( $request ) {
15361573
$ret = array(
15371574
'accounts' => array(),
15381575
'statuses' => array(),
1576+
'hashtags' => array(),
15391577
);
1578+
$search_query = trim( $request->get_param( 'q' ) );
1579+
// Don't allow empty search queries.
1580+
if ( $search_query == '' ) {
1581+
return $ret;
1582+
}
15401583
if ( ! $type || 'accounts' === $type ) {
1541-
if ( preg_match( '/^@?' . self::ACTIVITYPUB_USERNAME_REGEXP . '$/i', $request->get_param( 'q' ) ) && ! $request->get_param( 'offset' ) ) {
1542-
$ret['accounts'][] = $this->get_friend_account_data( $request->get_param( 'q' ), array(), true );
1584+
if ( preg_match( '/^@?' . self::ACTIVITYPUB_USERNAME_REGEXP . '$/i', $search_query ) && ! $request->get_param( 'offset' ) ) {
1585+
$ret['accounts'][] = $this->get_friend_account_data( $search_query, array(), true );
15431586
}
15441587
$query = new \WP_User_Query(
15451588
array(
1546-
'search' => '*' . $request->get_param( 'q' ) . '*',
1589+
'search' => '*' . $search_query . '*',
15471590
'search_columns' => array(
15481591
'user_login',
15491592
'user_nicename',
@@ -1566,10 +1609,10 @@ public function api_search( $request ) {
15661609
return array();
15671610
}
15681611
$args = apply_filters( 'mastodon_api_timelines_args', $args, $request );
1569-
$valid_url = wp_parse_url( $request->get_param( 'q' ) );
1612+
$valid_url = wp_parse_url( $search_query );
15701613
if ( $valid_url && isset( $valid_url['host'] ) ) {
15711614
if ( ! $request->get_param( 'offset' ) ) {
1572-
$url = $request->get_param( 'q' );
1615+
$url = $search_query;
15731616
$json = $this->get_json( $url, crc32( $url ) );
15741617
if ( ! is_wp_error( $json ) && isset( $json['id'], $json['attributedTo'] ) ) {
15751618
$user_id = $this->get_acct( $json['attributedTo'] );
@@ -1583,13 +1626,39 @@ public function api_search( $request ) {
15831626
);
15841627
}
15851628
}
1586-
} elseif ( is_user_logged_in() ) {
1587-
$args['s'] = $request->get_param( 'q' );
1588-
$args['offset'] = $request->get_param( 'offset' );
1589-
$args['posts_per_page'] = $request->get_param( 'limit' );
1629+
} elseif ( is_user_logged_in() || $this->oauth->get_token() ) {
1630+
$args['s'] = $search_query;
1631+
1632+
$offset_param = $request->get_param( 'offset' );
1633+
if( $offset_param != null ) { $args['offset'] = $offset_param; }
1634+
1635+
$ppp_param = $request->get_param( 'limit' );
1636+
if( $ppp_param != null ) { $args['posts_per_page'] = $ppp_param; }
1637+
15901638
$ret['statuses'] = array_merge( $ret['statuses'], $this->get_posts( $args ) );
15911639
}
15921640
}
1641+
if ( ! $type || 'hashtags' === $type ) {
1642+
$token = $this->oauth->get_token();
1643+
$user_id = $token['user_id'];
1644+
1645+
$categories = $this->get_categories();
1646+
$post_data['post_category'] = array();
1647+
foreach( $categories as $category ) {
1648+
if( strcasecmp( $search_query, $category->name ) == 0 ) {
1649+
$ret['hashtags'][] = $this->generate_hashtag_array( $category, array(), $this->check_if_hashtag_followed( $user_id, $category->name ) );
1650+
}
1651+
}
1652+
$tags = $this->get_tags();
1653+
$post_data['tags_input'] = array();
1654+
foreach( $tags as $tag ) {
1655+
if( strcasecmp( $search_query, $tag->name ) == 0 ) {
1656+
$ret['hashtags'][] = $this->generate_hashtag_array( $tag, array(), $this->check_if_hashtag_followed( $user_id, $tag->name ) );
1657+
}
1658+
}
1659+
1660+
}
1661+
15931662
return $ret;
15941663
}
15951664

@@ -2867,4 +2936,138 @@ public function api_instance_v2() {
28672936

28682937
return apply_filters( 'mastodon_api_instance_v2', $ret );
28692938
}
2939+
2940+
public function api_tags( $request ) {
2941+
$token = $this->oauth->get_token();
2942+
$user_id = $token['user_id'];
2943+
$hashtag = $request->get_param( 'id' );
2944+
$followed = $this->check_if_hashtag_followed( $user_id, $hashtag );
2945+
2946+
$term = $this->find_hashtag_term( $hashtag );
2947+
return $this->generate_hashtag_array( $term, array(), $followed );
2948+
}
2949+
2950+
public function api_tags_follow( $request ) {
2951+
$token = $this->oauth->get_token();
2952+
$user_id = $token['user_id'];
2953+
2954+
$tags_followed = get_user_meta( $user_id, 'enable-mastodon-apps-tags-followed', true );
2955+
2956+
if ( $tags_followed === false ) {
2957+
$tags_followed = array();
2958+
} else {
2959+
$tags_followed = unserialize( $tags_followed );
2960+
}
2961+
2962+
$hashtag = $request->get_param( 'id' );
2963+
$term = $this->find_hashtag_term( $hashtag );
2964+
2965+
$tags_followed[$hashtag] = true;
2966+
2967+
update_user_meta( $user_id, 'enable-mastodon-apps-tags-followed', serialize( $tags_followed ) );
2968+
2969+
if ( $term === null ) {
2970+
return $this->generate_hashtag_array( '' );
2971+
}
2972+
2973+
return $this->generate_hashtag_array( $term, array(), true );
2974+
}
2975+
2976+
public function api_tags_unfollow( $request ) {
2977+
$token = $this->oauth->get_token();
2978+
$user_id = $token['user_id'];
2979+
2980+
$tags_followed = get_user_meta( $user_id, 'enable-mastodon-apps-tags-followed', true );
2981+
2982+
if ( $tags_followed === false ) {
2983+
$tags_followed = array();
2984+
} else {
2985+
$tags_followed = unserialize( $tags_followed );
2986+
}
2987+
2988+
$hashtag = $request->get_param( 'id' );
2989+
$term = $this->find_hashtag_term( $hashtag );
2990+
2991+
unset( $tags_followed[$hashtag] );
2992+
2993+
update_user_meta( $user_id, 'enable-mastodon-apps-tags-followed', serialize( $tags_followed ) );
2994+
2995+
if ( $term === null ) {
2996+
return $this->generate_hashtag_array( '' );
2997+
}
2998+
2999+
return $this->generate_hashtag_array( $term, array() );
3000+
}
3001+
3002+
public function api_followed_tags( $request ) {
3003+
$token = $this->oauth->get_token();
3004+
$user_id = $token['user_id'];
3005+
3006+
$tags_followed = get_user_meta( $user_id, 'enable-mastodon-apps-tags-followed', true );
3007+
3008+
if ( $tags_followed === false ) {
3009+
$tags_followed = array();
3010+
} else {
3011+
$tags_followed = unserialize( $tags_followed );
3012+
}
3013+
3014+
$ret = array();
3015+
foreach( $tags_followed as $key => $value ) {
3016+
$term = $this->find_hashtag_term( $key );
3017+
$ret[] = $this->generate_hashtag_array( $term, array(), true );
3018+
}
3019+
3020+
return $ret;
3021+
}
3022+
3023+
private function generate_hashtag_array( $term, $history = array(), $following = false ) {
3024+
$ret = array( 'name' => $term->name, 'url' => get_term_link( $term ), 'history' => $history );
3025+
if( $following ) {
3026+
$ret['following'] = true;
3027+
}
3028+
return $ret;
3029+
}
3030+
3031+
private function get_categories() {
3032+
return get_categories( array( 'orderby' => 'name', 'hide_empty' => false ) );
3033+
}
3034+
3035+
private function get_tags() {
3036+
return get_tags( array( 'orderby' => 'name', 'hide_empty' => false ) );
3037+
}
3038+
3039+
private function find_hashtag_term( $hashtag ) {
3040+
$tags = $this->get_tags();
3041+
$post_data['tags_input'] = array();
3042+
foreach( $tags as $tag ) {
3043+
if( strcmp( $hashtag, $tag->name ) == 0 ) {
3044+
return $tag;
3045+
}
3046+
}
3047+
$categories = $this->get_categories();
3048+
$post_data['post_category'] = array();
3049+
foreach( $categories as $category ) {
3050+
if( strcmp( $hashtag, $category->name ) == 0 ) {
3051+
return $category;
3052+
}
3053+
}
3054+
return null;
3055+
}
3056+
3057+
private function check_if_hashtag_followed( $user_id, $hashtag ) {
3058+
$tags_followed = get_user_meta( $user_id, 'enable-mastodon-apps-tags-followed', true );
3059+
3060+
if ( $tags_followed === false ) {
3061+
$tags_followed = array();
3062+
} else {
3063+
$tags_followed = unserialize( $tags_followed );
3064+
}
3065+
3066+
if( array_key_exists( $hashtag, $tags_followed ) ) {
3067+
return true;
3068+
}
3069+
3070+
return false;
3071+
}
3072+
28703073
}

0 commit comments

Comments
 (0)