Add wp-nostr-widget/nostr-widget.php

Initial commit, not yet tested.
This commit is contained in:
2025-06-24 14:34:23 +02:00
commit 3ba4a63cb2

View File

@ -0,0 +1,111 @@
<?php
/*
Plugin Name: Nostr Widget
Description: Display Nostr posts from a configurable public key and relay(s).
Version: 0.2
Author: martien.io
*/
class Nostr_Widget extends WP_Widget {
function __construct() {
parent::__construct(
'nostr_widget',
__('Nostr Widget', 'nostr_widget_domain'),
array('description' => __('Shows Nostr posts from a public key and relay(s).', 'nostr_widget_domain'))
);
}
public function widget($args, $instance) {
$pubkey = !empty($instance['pubkey']) ? $instance['pubkey'] : '';
$relays = $this->get_relays_from_instance($instance);
echo $args['before_widget'];
if (!empty($pubkey) && !empty($relays[0])) {
echo $args['before_title'] . 'Nostr Posts' . $args['after_title'];
$this->display_nostr_posts($pubkey, $relays);
} else {
echo 'Please configure at least a public key and one relay.';
}
echo $args['after_widget'];
}
public function form($instance) {
$pubkey = !empty($instance['pubkey']) ? $instance['pubkey'] : '';
$relays = $this->get_relays_from_instance($instance);
?>
<p>
<label for="<?php echo $this->get_field_id('pubkey'); ?>"><?php _e('Nostr Public Key:'); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id('pubkey'); ?>" name="<?php echo $this->get_field_name('pubkey'); ?>" type="text" value="<?php echo esc_attr($pubkey); ?>" />
</p>
<p>
<strong>Relay URLs (at least one, max five):</strong>
<?php for ($i = 0; $i < 5; $i++): ?>
<input class="widefat" id="<?php echo $this->get_field_id('relay' . $i); ?>"
name="<?php echo $this->get_field_name('relay' . $i); ?>" type="text"
value="<?php echo esc_attr($relays[$i]); ?>" placeholder="Relay URL #<?php echo $i + 1; ?>" /><br/>
<?php endfor; ?>
<small>Example: <code>https://nostr.band/api/v0/search</code> (for nostr.band)</small>
</p>
<?php
}
public function update($new_instance, $old_instance) {
$instance = array();
$instance['pubkey'] = (!empty($new_instance['pubkey'])) ? strip_tags($new_instance['pubkey']) : '';
for ($i = 0; $i < 5; $i++) {
$key = 'relay' . $i;
$instance[$key] = (!empty($new_instance[$key])) ? esc_url_raw($new_instance[$key]) : '';
}
return $instance;
}
private function get_relays_from_instance($instance) {
$relays = [];
for ($i = 0; $i < 5; $i++) {
$relays[] = !empty($instance['relay' . $i]) ? $instance['relay' . $i] : '';
}
return $relays;
}
private function display_nostr_posts($pubkey, $relays) {
$posts_found = false;
foreach ($relays as $relay) {
if (empty($relay)) continue;
// nostr.band/Mutiny API compatible
if (strpos($relay, 'nostr.band') !== false || strpos($relay, 'mutinywallet') !== false) {
$url = trailingslashit($relay) . '?author=' . $pubkey . '&limit=5&type=text_note';
} else {
// Fallback for custom APIs, may need more customization!
$url = $relay . '?author=' . $pubkey . '&limit=5';
}
$response = wp_remote_get($url, ['timeout' => 8]);
if (is_wp_error($response)) continue;
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
if (!empty($data['events'])) {
$posts_found = true;
echo '<ul class="nostr-posts">';
foreach ($data['events'] as $event) {
$content = esc_html($event['content']);
$date = date('Y-m-d H:i', $event['created_at']);
echo "<li><div class='nostr-date'>$date</div><div class='nostr-content'>$content</div></li>";
}
echo '</ul>';
break; // Stop after first relay with results
}
}
if (!$posts_found) {
echo 'No posts found on any configured relay.';
}
}
}
function register_nostr_widget() {
register_widget('Nostr_Widget');
}
add_action('widgets_init', 'register_nostr_widget');