Skip to content

Commit 96cbf44

Browse files
committed
Update
1 parent 260b279 commit 96cbf44

11 files changed

Lines changed: 250 additions & 26 deletions

File tree

_config.i2p.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,13 @@ theme_settings:
44
p2p_player:
55
media_urls_overwrite:
66
- http://codnaft43k7ncna2hfsxrzi2nqoxieu22vbyjkmhkwdrrta2ghlq.b32.i2p
7+
nostr:
8+
spam_api: http://codnaft43k7ncna2hfsxrzi2nqoxieu22vbyjkmhkwdrrta2ghlq.b32.i2p/nostr/spam.nostr.band/spam_api
9+
profile_relays:
10+
- ws://codnaft43k7ncna2hfsxrzi2nqoxieu22vbyjkmhkwdrrta2ghlq.b32.i2p/nostr/purplepag.es
11+
- ws://codnaft43k7ncna2hfsxrzi2nqoxieu22vbyjkmhkwdrrta2ghlq.b32.i2p/nostr/hist.nostr.land
12+
relays:
13+
- ws://codnaft43k7ncna2hfsxrzi2nqoxieu22vbyjkmhkwdrrta2ghlq.b32.i2p/nostr
14+
read_cache_relays:
15+
- ws://codnaft43k7ncna2hfsxrzi2nqoxieu22vbyjkmhkwdrrta2ghlq.b32.i2p/nostr
16+
- ws://codnaft43k7ncna2hfsxrzi2nqoxieu22vbyjkmhkwdrrta2ghlq.b32.i2p/nostr/relay.primal.net

_config.tor.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,14 @@ theme_settings:
44
p2p_player:
55
media_urls_overwrite:
66
- http://codonaftct3jsouvfyrjq4yumyngzv3el2msndf5oddccktgghnw7eyd.onion
7+
nostr:
8+
spam_api: http://codonaftct3jsouvfyrjq4yumyngzv3el2msndf5oddccktgghnw7eyd.onion/nostr/spam.nostr.band/spam_api
9+
profile_relays:
10+
- wss://purplepag.es
11+
- wss://hist.nostr.land
12+
relays:
13+
- ws://oxtrdevav64z64yb7x6rjg4ntzqjhedm5b5zjqulugknhzr46ny2qbad.onion
14+
- ws://gnostr2jnapk72mnagq3cuykfon73temzp77hcbncn4silgt77boruid.onion
15+
read_cache_relays:
16+
- ws://codonaftct3jsouvfyrjq4yumyngzv3el2msndf5oddccktgghnw7eyd.onion/nostr
17+
- ws://codonaftct3jsouvfyrjq4yumyngzv3el2msndf5oddccktgghnw7eyd.onion/nostr/relay.primal.net

_config.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,14 @@ theme_settings:
126126
zapthreads: true
127127

128128
nostr:
129+
enabled: true
129130
npub: npub1alptdev5srcw2hxg03567p4k6xs3lgj7f6545suc0rzp0xw98svse7rg94
130131
community: codonaft
131132
max_comment_length: 5000
132133
min_read_pow: 7
134+
profile_relays:
135+
- wss://purplepag.es
136+
- wss://hist.nostr.land
133137
relays:
134138
- wss://nostr-pub.wellorder.net
135139
- wss://relay.nostr.band

_do.cr

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require "json"
1212
require "uri"
1313
require "yaml"
1414

15-
DEBUG = ARGV.empty? || !["sync", "build", "deploy", "health"].includes?(ARGV[0])
15+
DEBUG = ARGV.empty? || !["sync", "sync-nostr", "build", "deploy", "health"].includes?(ARGV[0])
1616
TRACE = ENV["TRACE"]? == "1"
1717

1818
WILDCARD_HOST = "0.0.0.0"
@@ -74,6 +74,9 @@ def main
7474
elsif ARGV.size == 1 && ARGV[0] == "sync"
7575
check
7676
sync
77+
elsif ARGV.size >= 1 && ARGV[0] == "sync-nostr"
78+
profile = ARGV.size > 1 && ARGV[1] == "profile"
79+
sync_nostr(config, profile: profile, output_relays: ["ws://localhost:7777", "wss://nostr.codonaft.com", "wss://nostr.oxtr.dev", "wss://nostr.girino.org"])
7780
elsif ARGV.size == 1 && ARGV[0] == "health"
7881
check
7982
health(config)
@@ -126,6 +129,10 @@ def usage
126129
download newest non-conflicting versioned files to _ohmyvps and _hosts
127130
upload newest files from _ohmyvps, _hosts and .build
128131
132+
#{script} sync-nostr [profile]
133+
fetch nostr events, push them to my relays
134+
don't send events to profile-specific relays by default
135+
129136
#{script} health
130137
run health checks
131138
@@ -461,7 +468,7 @@ def health(config)
461468
.map { |i| i.strip }
462469
.reject { |i| i.empty? }
463470
.map { |i| URI.parse(i) }
464-
.reject { |i| i.hostname.nil? || i.hostname == "127.0.0.1" } + relay_mirrors
471+
.reject { |i| i.hostname.nil? || i.hostname == "localhost" } + relay_mirrors
465472
wss_uris = (trackers + other_relays + `git grep --only-matching 'wss://[a-zA-Z0-9/._-]*'`
466473
.split('\n')
467474
.map { |i| i.strip.gsub(/.*wss:\/\//, "") }
@@ -1120,6 +1127,102 @@ def check_manual_upload(host : String, *, owner : String, group : String, mode :
11201127
end
11211128
end
11221129

1130+
def sync_nostr(config, *, profile : Bool, output_relays : Array(String))
1131+
# TODO: do the same thing as cron bash job that uses rust nostr cli client? connect to relays over tor?
1132+
1133+
now = Time.utc
1134+
from = now - 3.years # TODO: last commit date? last blog date? previous blog date?
1135+
to = now + 15.minutes
1136+
1137+
nostr_config = config["theme_settings"]["nostr"]
1138+
npub = nostr_config["npub"].as_s
1139+
pk = JSON.parse(`nak decode #{npub}`)["pubkey"].as_s
1140+
1141+
profile_relays = nostr_config["profile_relays"].as_a.map { |i| i.as_s }
1142+
relays = nostr_config["relays"].as_a.map { |i| i.as_s }
1143+
read_cache_relays = nostr_config["read_cache_relays"].as_a.map { |i| i.as_s }
1144+
input_relays : Array(String) = relays + read_cache_relays + profile_relays
1145+
1146+
step("sync-nostr")
1147+
trace("pk=#{pk} input_relays=#{input_relays} output_relays=#{output_relays}")
1148+
1149+
nak = "nak req --limit 1000 --since #{from.to_unix} --until #{to.to_unix}"
1150+
1151+
mentions = parse_nostr_events(`#{nak} -p #{pk} #{input_relays.join(' ')}`)
1152+
.reject { |i|
1153+
return false unless i["tags"].as_a.any? { |t| t.size > 1 && t[0] == "p" && t[1] == pk }
1154+
k = i["kind"].as_i
1155+
[3, 1984, 4454].includes?(k) || (k >= 5000 && k <= 7000) || (k >= 10000 && k <= 10102) || (k >= 20000 && k < 30000) || (k >= 30000 && k <= 30267)
1156+
}
1157+
puts("fetched #{mentions.size} mentions")
1158+
1159+
parsed_authored_events = parse_nostr_events(`#{nak} -a #{pk} #{input_relays.join(' ')}`)
1160+
authored_events = parsed_authored_events
1161+
.reject { |i|
1162+
return false unless i["pubkey"].as_s == pk
1163+
k = i["kind"].as_i
1164+
[4454, 10044].includes?(k) || (k >= 20000 && k < 30000)
1165+
}
1166+
puts("fetched #{authored_events.size} authored events")
1167+
1168+
# TODO: check spam
1169+
1170+
puts("writing events")
1171+
nak_raw(["event"] + output_relays, (mentions + authored_events).map { |i| i.to_json })
1172+
1173+
if profile
1174+
profile_events = parsed_authored_events.select { |i|
1175+
k = i["kind"].as_i
1176+
[0, 3, 10002].includes?(k)
1177+
}
1178+
.group_by { |i| i["kind"].as_i }
1179+
.map { |k, g| g.max_by { |i| i["created_at"].as_i } }
1180+
1181+
puts("writing #{profile_events.size} profile events")
1182+
nak_raw(["event"] + profile_relays, profile_events.map { |i| i.to_json })
1183+
end
1184+
1185+
puts("finished writing events")
1186+
end
1187+
1188+
def nak_raw(args, input : Array(String) = [] of String)
1189+
# TODO: exit after timeout
1190+
output = Channel(Tuple(String, Process::Status)).new
1191+
trace("running nak #{args}")
1192+
spawn do
1193+
value = Process.run(command: "nak", args: args) do |p|
1194+
input.each do |line|
1195+
trace("writing stdin")
1196+
p.input.puts(line)
1197+
trace("writing stdin ok")
1198+
end
1199+
trace("closing stdin")
1200+
p.input.close
1201+
trace("closed stdin")
1202+
trace("reading stdout")
1203+
result = p.output.gets_to_end
1204+
trace("finished reading stdout")
1205+
result
1206+
end
1207+
trace("sending stdout")
1208+
output.send({value.strip, $?})
1209+
trace("sent stdout")
1210+
end
1211+
trace("waiting for stdout")
1212+
value, status = output.receive
1213+
trace("received stdout")
1214+
raise "#{args}: unexpected exit code #{status}, value=#{value}" unless status.success?
1215+
value
1216+
end
1217+
1218+
def parse_nostr_events(text)
1219+
text
1220+
.split('\n')
1221+
.reject { |i| i.strip.empty? }
1222+
.to_set
1223+
.map { |i| JSON.parse(i) }
1224+
end
1225+
11231226
def processes
11241227
Dir.entries("/proc")
11251228
.select { |entry| entry =~ /^\d+$/ }

_hosts/media.codonaft/etc/init.d/rnostr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ name="rnostr"
55
command="/usr/local/bin/${name}"
66
command_user="${name}:${name}"
77
command_background="true"
8-
command_args="relay --watch -c /etc/${name}/${name}.toml"
8+
command_args="relay -c /etc/${name}/${name}.toml"
9+
retry="60"
910

1011
pidfile="/run/${name}.pid"
1112
output_logger="logger"

_hosts/media.codonaft/etc/local.d/90-inotify-extra.start

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
fi
1616
done &
1717

18-
# using rnostr relay --watch for now, however it's unclear whether it's working correctly
19-
# [ -f /etc/init.d/rnostr ] && inotifywait --event close_write,moved_to,create --monitor --recursive /etc/rnostr/ |
20-
# while read -r directory events filename ; do
21-
# if [[ "${filename}" == "rnostr.toml" ]] ; then
22-
# rc-service --ifstarted rnostr restart 2>>/dev/stdout | logger
23-
# fi
24-
# done &
18+
# rnostr relay --watch does nothing (probably under load only)
19+
[ -f /etc/init.d/rnostr ] && inotifywait --event close_write,moved_to,create --monitor --recursive /etc/rnostr/ |
20+
while read -r directory events filename ; do
21+
if [[ "${filename}" == "rnostr.toml" ]] ; then
22+
rc-service --ifstarted rnostr restart 2>>/dev/stdout | logger
23+
fi
24+
done &

_hosts/media.codonaft/etc/nginx/http.d/media.conf

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ server {
6464
}
6565

6666
location ~ \.(m3u8|mp4|ts|vtt|webp)$ {
67+
if ($http_origin != $origin) {
68+
return 404;
69+
}
70+
6771
add_header "Access-Control-Allow-Origin" $origin always;
6872

6973
add_header Cache-Control "public, max-age=31536000, immutable";
@@ -132,6 +136,10 @@ server {
132136
ignore_invalid_headers on;
133137

134138
location ~ \.(m3u8|mp4|ts|vtt|webp)$ {
139+
if ($http_origin != $origin) {
140+
return 404;
141+
}
142+
135143
add_header "Access-Control-Allow-Origin" $origin always;
136144

137145
add_header Cache-Control "public, max-age=31536000, immutable";
@@ -167,4 +175,71 @@ server {
167175

168176
proxy_pass http://localhost:6666/;
169177
}
178+
179+
location /nostr/relay.primal.net {
180+
if ($http_origin != $origin) {
181+
return 404;
182+
}
183+
184+
proxy_hide_header "Host";
185+
proxy_set_header "Host" "relay.primal.net";
186+
proxy_hide_header "Access-Control-Allow-Origin";
187+
188+
proxy_http_version 1.1;
189+
proxy_connect_timeout 10m;
190+
proxy_socket_keepalive on;
191+
proxy_send_timeout 365d;
192+
proxy_read_timeout 365d;
193+
194+
proxy_set_header Upgrade $http_upgrade;
195+
proxy_set_header Connection "upgrade";
196+
197+
proxy_ssl_server_name on;
198+
proxy_pass https://relay.primal.net/;
199+
}
200+
201+
location ~ /nostr/(hist\.nostr\.land|purplepag\.es)$ {
202+
if ($http_origin != "http://codonaft.i2p") {
203+
return 404;
204+
}
205+
206+
proxy_hide_header "Host";
207+
proxy_set_header "Host" $1;
208+
proxy_hide_header "Access-Control-Allow-Origin";
209+
210+
proxy_http_version 1.1;
211+
proxy_connect_timeout 10m;
212+
proxy_socket_keepalive on;
213+
proxy_send_timeout 365d;
214+
proxy_read_timeout 365d;
215+
216+
proxy_set_header Upgrade $http_upgrade;
217+
proxy_set_header Connection "upgrade";
218+
219+
proxy_ssl_server_name on;
220+
proxy_pass https://$1/;
221+
}
222+
223+
location ~ /nostr/(spam\.nostr\.band/spam_api.*)$ {
224+
if ($http_origin != $origin) {
225+
return 404;
226+
}
227+
228+
proxy_hide_header "Host";
229+
proxy_set_header "Host" "spam.nostr.band";
230+
proxy_hide_header "Access-Control-Allow-Origin";
231+
add_header "Access-Control-Allow-Origin" $origin always;
232+
233+
add_header Cache-Control "public, max-age=86400";
234+
expires 86400s;
235+
236+
proxy_http_version 1.1;
237+
proxy_connect_timeout 10m;
238+
proxy_socket_keepalive on;
239+
proxy_send_timeout 10m;
240+
proxy_read_timeout 10m;
241+
242+
proxy_ssl_server_name on;
243+
proxy_pass https://$1$is_args$args;
244+
}
170245
}

_hosts/media.codonaft/etc/rnostr/rnostr.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ reader = 1
2121
max_message_length = 524288
2222
max_subscriptions = 20
2323
max_filters = 10
24-
max_limit = 300
24+
max_limit = 2000
2525
max_subid_length = 100
2626
min_prefix = 10
2727
max_event_tags = 5000

_includes/zapthreads.html

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -341,25 +341,23 @@ <h3>Report this <span class="report-content-type">comment thread? 💬</span></h
341341
return !controller.signal.aborted;
342342
}
343343

344-
const i2p = window.location.hostname.endsWith('.i2p');
345344
const commentsSection = document.querySelector('.comments-section');
346-
347-
if (i2p) {
348-
commentsSection.innerHTML = '💬 {{ page.str.leave_comment_on_upstream }} <a href="{{ page.url | prepend: site.theme_settings.tor }}" target="_blank">tor</a> | <a href="{{ page.url | prepend: site.theme_settings.upstream_url }}" target="_blank">clearnet</a></div>';
349-
} else {
345+
{% if site.theme_settings.nostr.enabled %}
350346
commentsSection.innerHTML = `
351347
<zap-threads
352348
anchor="{% if page.nostr.comments %}{{ page.nostr.comments }}{% else %}{{ page.url | prepend: site.baseurl | prepend: site.url }}{% endif %}"
353349
author="{{ site.theme_settings.nostr.npub }}"
354-
{%if site.theme_settings.nostr.community %}community="{{ site.theme_settings.nostr.community }}"{% endif %}
350+
{% if site.theme_settings.nostr.community %}community="{{ site.theme_settings.nostr.community }}"{% endif %}
355351
disable="relayInformation,likes,zaps,singleVoteCounter"
356352
language="{{ page.lang }}"
357353
client="{{ zapthreads_client }}"
358354
max-comment-length="{{ site.theme_settings.nostr.max_comment_length }}"
359355
min-read-pow="{% if page.nostr.min_read_pow %}{{ page.nostr.min_read_pow }}{% else %}{{ site.theme_settings.nostr.min_read_pow }}{% endif %}"
360356
max-write-pow="{% if page.nostr.max_write_pow %}{{ page.nostr.max_write_pow }}{% else %}{{ site.theme_settings.nostr.max_write_pow }}{% endif %}"
361-
relays="{{ site.theme_settings.nostr.relays | concat: site.theme_settings.nostr.read_cache_relays | join: ',' }}">
362-
</zap-threads>`;
357+
relays="{{ site.theme_settings.nostr.relays | concat: site.theme_settings.nostr.read_cache_relays | join: ',' }}"
358+
profile-relays="{{ site.theme_settings.nostr.profile_relays | join: ',' }}"
359+
{% if site.theme_settings.nostr.spam_api %}spam-api="{{ site.theme_settings.nostr.spam_api }}"{% endif %}
360+
></zap-threads>`;
363361

364362
const style = document.createElement('style');
365363
style.innerHTML = 'code { font-family: "Iosevka Term SS08 Web", Monaco, Consolas, "Lucida Console", monospace }';
@@ -416,7 +414,9 @@ <h3>Report this <span class="report-content-type">comment thread? 💬</span></h
416414
};
417415
})
418416
.start();
419-
}
417+
{% else %}
418+
commentsSection.innerHTML = '💬 {{ page.str.leave_comment_on_upstream }} <a href="{{ page.url | prepend: site.theme_settings.tor }}" target="_blank">tor</a> | <a href="{{ page.url | prepend: site.theme_settings.upstream_url }}" target="_blank">clearnet</a></div>';
419+
{% endif %}
420420
</script>
421421

422422
<div class="comments-section" />

0 commit comments

Comments
 (0)