Skip to content

Commit 86a52a4

Browse files
committed
Update
1 parent 260b279 commit 86a52a4

9 files changed

Lines changed: 194 additions & 18 deletions

File tree

_config.i2p.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,11 @@ 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+
read_cache_relays:
13+
- ws://codnaft43k7ncna2hfsxrzi2nqoxieu22vbyjkmhkwdrrta2ghlq.b32.i2p/nostr
14+
- ws://codnaft43k7ncna2hfsxrzi2nqoxieu22vbyjkmhkwdrrta2ghlq.b32.i2p/nostr/relay.primal.net

_config.tor.yml

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

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,41 @@ server {
167167

168168
proxy_pass http://localhost:6666/;
169169
}
170+
171+
location /nostr/purplepag.es {
172+
proxy_hide_header "Access-Control-Allow-Origin";
173+
add_header "Access-Control-Allow-Origin" $origin always;
174+
175+
proxy_http_version 1.1;
176+
proxy_connect_timeout 10m;
177+
proxy_socket_keepalive on;
178+
proxy_send_timeout 365d;
179+
proxy_read_timeout 365d;
180+
181+
proxy_set_header Upgrade $http_upgrade;
182+
proxy_set_header Connection "upgrade";
183+
184+
proxy_ssl_server_name on;
185+
proxy_pass https://purplepag.es/;
186+
}
187+
188+
location ~ /nostr/(spam\.nostr\.band/spam_api.*|hist\.nostr\.land|relay\.primal\.net)$ {
189+
proxy_hide_header "Access-Control-Allow-Origin";
190+
add_header "Access-Control-Allow-Origin" $origin always;
191+
192+
add_header Cache-Control "public, max-age=600";
193+
expires 600s;
194+
195+
proxy_http_version 1.1;
196+
proxy_connect_timeout 10m;
197+
proxy_socket_keepalive on;
198+
proxy_send_timeout 365d;
199+
proxy_read_timeout 365d;
200+
201+
proxy_set_header Upgrade $http_upgrade;
202+
proxy_set_header Connection "upgrade";
203+
204+
proxy_ssl_server_name on;
205+
proxy_pass https://$1$is_args$args;
206+
}
170207
}

_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 = 1000
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" />

_publish-post.cr

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ PROD_BRANCH = "master"
1212

1313
ALLOWED_TIME_DIFF = 5.minutes
1414

15+
TRACE = true
16+
1517
class PostMetadata
1618
include YAML::Serializable
1719

@@ -218,17 +220,28 @@ end
218220
def nak_raw(args, input = nil)
219221
# TODO: exit after timeout
220222
output = Channel(Tuple(String, Process::Status)).new
223+
trace("running nak #{args}")
221224
spawn do
222225
value = Process.run(command: "nak", args: args) do |p|
223226
if input
227+
trace("writing stdin")
224228
p.input.puts(input)
229+
trace("closing stdin")
225230
p.input.close
231+
trace("closed stdin")
226232
end
227-
p.output.gets_to_end
233+
trace("reading stdout")
234+
result = p.output.gets_to_end
235+
trace("finished reading stdout")
236+
result
228237
end
238+
trace("sending stdout")
229239
output.send({value.strip, $?})
240+
trace("sent stdout")
230241
end
242+
trace("waiting for stdout")
231243
value, status = output.receive
244+
trace("received stdout")
232245
raise "#{args}: unexpected exit code #{status}, value=#{value}" unless status.success?
233246
value
234247
end
@@ -319,4 +332,11 @@ def wait(time : Time::Span)
319332
sleep(time)
320333
end
321334

335+
def trace(text)
336+
return unless TRACE
337+
Colorize.with.dark_gray.surround(STDOUT) do
338+
puts(text)
339+
end
340+
end
341+
322342
main

0 commit comments

Comments
 (0)